Skip to content

Commit b689e88

Browse files
committed
More cleanup
1 parent a395569 commit b689e88

File tree

5 files changed

+51
-67
lines changed

5 files changed

+51
-67
lines changed

packages/cloud/src/AuthService.ts

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as vscode from "vscode"
66

77
import type { CloudUserInfo } from "@roo-code/types"
88

9+
import { CloudServiceCallbacks } from "./types"
910
import { getClerkBaseUrl, getRooCodeApiUrl } from "./Config"
1011
import { RefreshTimer } from "./RefreshTimer"
1112

@@ -22,27 +23,28 @@ type AuthState = "initializing" | "logged-out" | "active-session" | "inactive-se
2223

2324
export class AuthService extends EventEmitter<AuthServiceEvents> {
2425
private context: vscode.ExtensionContext
26+
private userChanged: CloudServiceCallbacks["userChanged"]
27+
private timer: RefreshTimer
2528
private state: AuthState = "initializing"
2629

2730
private clientToken: string | null = null
2831
private sessionToken: string | null = null
2932
private sessionId: string | null = null
3033

31-
private timer: RefreshTimer
32-
33-
constructor(context: vscode.ExtensionContext, onUserInfo: (userInfo: CloudUserInfo | undefined) => void) {
34+
constructor(context: vscode.ExtensionContext, userChanged: CloudServiceCallbacks["userChanged"]) {
3435
super()
3536

3637
this.context = context
38+
this.userChanged = userChanged
3739

3840
this.timer = new RefreshTimer({
3941
callback: async () => {
40-
await this.refreshSession(onUserInfo)
42+
await this.refreshSession()
4143
return true
4244
},
43-
successInterval: 50000,
44-
initialBackoffMs: 1000,
45-
maxBackoffMs: 300000,
45+
successInterval: 50_000,
46+
initialBackoffMs: 1_000,
47+
maxBackoffMs: 300_000,
4648
})
4749
}
4850

@@ -62,7 +64,7 @@ export class AuthService extends EventEmitter<AuthServiceEvents> {
6264
this.clientToken = (await this.context.secrets.get(CLIENT_TOKEN_KEY)) || null
6365
this.sessionId = this.context.globalState.get<string>(SESSION_ID_KEY) || null
6466

65-
// Determine initial state
67+
// Determine initial state.
6668
if (!this.clientToken || !this.sessionId) {
6769
// TODO: it may be possible to get a new session with the client,
6870
// but the obvious Clerk endpoints don't support that.
@@ -109,18 +111,14 @@ export class AuthService extends EventEmitter<AuthServiceEvents> {
109111
* @param code The authorization code from the callback
110112
* @param state The state parameter from the callback
111113
*/
112-
public async handleCallback(
113-
code: string | null,
114-
state: string | null,
115-
onUserInfo?: (userInfo: CloudUserInfo | undefined) => void,
116-
): Promise<void> {
114+
public async handleCallback(code: string | null, state: string | null): Promise<void> {
117115
if (!code || !state) {
118116
vscode.window.showInformationMessage("Invalid Roo Code Cloud sign in url")
119117
return
120118
}
121119

122120
try {
123-
// 1. Validate state parameter to prevent CSRF attacks
121+
// Validate state parameter to prevent CSRF attacks.
124122
const storedState = this.context.globalState.get(AUTH_STATE_KEY)
125123

126124
if (state !== storedState) {
@@ -142,11 +140,10 @@ export class AuthService extends EventEmitter<AuthServiceEvents> {
142140
this.emit("active-session", { previousState })
143141
this.timer.start()
144142

145-
if (onUserInfo) {
146-
this.getUserInfo().then(onUserInfo)
143+
if (this.userChanged) {
144+
this.getUserInfo().then(this.userChanged)
147145
}
148146

149-
// Show success message
150147
vscode.window.showInformationMessage("Successfully authenticated with Roo Code Cloud")
151148
console.log("[auth] Successfully authenticated with Roo Code Cloud")
152149
} catch (error) {
@@ -163,7 +160,7 @@ export class AuthService extends EventEmitter<AuthServiceEvents> {
163160
*
164161
* This method removes all stored tokens and stops the refresh timer.
165162
*/
166-
public async logout(onUserInfo?: (userInfo: CloudUserInfo | undefined) => void): Promise<void> {
163+
public async logout(): Promise<void> {
167164
try {
168165
this.timer.stop()
169166

@@ -185,8 +182,8 @@ export class AuthService extends EventEmitter<AuthServiceEvents> {
185182
await this.clerkLogout(oldClientToken, oldSessionId)
186183
}
187184

188-
if (onUserInfo) {
189-
this.getUserInfo().then(onUserInfo)
185+
if (this.userChanged) {
186+
this.getUserInfo().then(this.userChanged)
190187
}
191188

192189
vscode.window.showInformationMessage("Logged out from Roo Code Cloud")
@@ -227,7 +224,7 @@ export class AuthService extends EventEmitter<AuthServiceEvents> {
227224
*
228225
* This method refreshes the session token using the client token.
229226
*/
230-
private async refreshSession(onUserInfo: (userInfo: CloudUserInfo | undefined) => void): Promise<void> {
227+
private async refreshSession() {
231228
if (!this.sessionId || !this.clientToken) {
232229
console.log("[auth] Cannot refresh session: missing session ID or token")
233230
this.state = "inactive-session"
@@ -240,7 +237,10 @@ export class AuthService extends EventEmitter<AuthServiceEvents> {
240237

241238
if (previousState !== "active-session") {
242239
this.emit("active-session", { previousState })
243-
this.getUserInfo().then(onUserInfo)
240+
241+
if (this.userChanged) {
242+
this.getUserInfo().then(this.userChanged)
243+
}
244244
}
245245
}
246246

@@ -383,15 +383,12 @@ export class AuthService extends EventEmitter<AuthServiceEvents> {
383383
return this._instance
384384
}
385385

386-
static async createInstance(
387-
context: vscode.ExtensionContext,
388-
onUserInfo: (userInfo: CloudUserInfo | undefined) => void,
389-
) {
386+
static async createInstance(context: vscode.ExtensionContext, userChanged: CloudServiceCallbacks["userChanged"]) {
390387
if (this._instance) {
391388
throw new Error("AuthService instance already created")
392389
}
393390

394-
this._instance = new AuthService(context, onUserInfo)
391+
this._instance = new AuthService(context, userChanged)
395392
await this._instance.initialize()
396393
return this._instance
397394
}

packages/cloud/src/CloudService.ts

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
11
import * as vscode from "vscode"
2-
import EventEmitter from "events"
32

4-
import type { CloudUserInfo, TelemetryEvent } from "@roo-code/types"
3+
import type { CloudUserInfo, TelemetryEvent, OrganizationAllowList, OrganizationSettings } from "@roo-code/types"
54
import { TelemetryService } from "@roo-code/telemetry"
65

7-
import { AuthService, type AuthServiceEvents } from "./AuthService"
6+
import { CloudServiceCallbacks } from "./types"
7+
import { AuthService } from "./AuthService"
88
import { SettingsService } from "./SettingsService"
99
import { TelemetryClient } from "./TelemetryClient"
1010

11-
export type CloudServiceEvents = AuthServiceEvents
12-
13-
export interface CloudServiceCallbacks {
14-
onUserInfoChanged?: (userInfo: CloudUserInfo | undefined) => void
15-
onSettingsChanged?: () => void
16-
}
17-
18-
export class CloudService extends EventEmitter<CloudServiceEvents> {
11+
export class CloudService {
1912
private static _instance: CloudService | null = null
2013

2114
private context: vscode.ExtensionContext
@@ -26,7 +19,6 @@ export class CloudService extends EventEmitter<CloudServiceEvents> {
2619
private isInitialized = false
2720

2821
private constructor(context: vscode.ExtensionContext, callbacks: CloudServiceCallbacks) {
29-
super()
3022
this.context = context
3123
this.callbacks = callbacks
3224
}
@@ -38,14 +30,11 @@ export class CloudService extends EventEmitter<CloudServiceEvents> {
3830

3931
try {
4032
this.authService = await AuthService.createInstance(this.context, (userInfo) => {
41-
this.callbacks.onUserInfoChanged?.(userInfo)
33+
this.callbacks.userChanged?.(userInfo)
4234
})
4335

44-
this.authService.on("active-session", (args) => this.emit("active-session", args))
45-
this.authService.on("logged-out", (args) => this.emit("logged-out", args))
46-
4736
this.settingsService = await SettingsService.createInstance(this.context, () =>
48-
this.callbacks.onSettingsChanged?.(),
37+
this.callbacks.settingsChanged?.(),
4938
)
5039

5140
this.telemetryClient = new TelemetryClient(this.authService)
@@ -72,7 +61,7 @@ export class CloudService extends EventEmitter<CloudServiceEvents> {
7261

7362
public async logout(): Promise<void> {
7463
this.ensureInitialized()
75-
return this.authService!.logout((userInfo) => this.callbacks.onUserInfoChanged?.(userInfo))
64+
return this.authService!.logout()
7665
}
7766

7867
public isAuthenticated(): boolean {
@@ -102,17 +91,17 @@ export class CloudService extends EventEmitter<CloudServiceEvents> {
10291

10392
public async handleAuthCallback(code: string | null, state: string | null): Promise<void> {
10493
this.ensureInitialized()
105-
return this.authService!.handleCallback(code, state, (userInfo) => this.callbacks.onUserInfoChanged?.(userInfo))
94+
return this.authService!.handleCallback(code, state)
10695
}
10796

10897
// SettingsService
10998

110-
public getOrganizationSettings() {
99+
public getOrganizationSettings(): OrganizationSettings | undefined {
111100
this.ensureInitialized()
112101
return this.settingsService!.getSettings()
113102
}
114103

115-
public getAllowList() {
104+
public getAllowList(): OrganizationAllowList {
116105
this.ensureInitialized()
117106
return this.settingsService!.getAllowList()
118107
}
@@ -131,7 +120,6 @@ export class CloudService extends EventEmitter<CloudServiceEvents> {
131120
this.settingsService.dispose()
132121
}
133122

134-
this.removeAllListeners()
135123
this.isInitialized = false
136124
}
137125

packages/cloud/src/__tests__/CloudService.test.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { CloudService } from "../CloudService"
66
import { AuthService } from "../AuthService"
77
import { SettingsService } from "../SettingsService"
88
import { TelemetryService } from "@roo-code/telemetry"
9+
import { CloudServiceCallbacks } from "../types"
910

1011
vi.mock("vscode", () => ({
1112
ExtensionContext: vi.fn(),
@@ -108,16 +109,10 @@ describe("CloudService", () => {
108109
}
109110

110111
vi.mocked(AuthService.createInstance).mockResolvedValue(mockAuthService as unknown as AuthService)
111-
Object.defineProperty(AuthService, "instance", {
112-
get: () => mockAuthService,
113-
configurable: true,
114-
})
112+
Object.defineProperty(AuthService, "instance", { get: () => mockAuthService, configurable: true })
115113

116114
vi.mocked(SettingsService.createInstance).mockResolvedValue(mockSettingsService as unknown as SettingsService)
117-
Object.defineProperty(SettingsService, "instance", {
118-
get: () => mockSettingsService,
119-
configurable: true,
120-
})
115+
Object.defineProperty(SettingsService, "instance", { get: () => mockSettingsService, configurable: true })
121116

122117
vi.mocked(TelemetryService.hasInstance).mockReturnValue(true)
123118
Object.defineProperty(TelemetryService, "instance", {
@@ -133,11 +128,7 @@ describe("CloudService", () => {
133128

134129
describe("createInstance", () => {
135130
it("should create and initialize CloudService instance", async () => {
136-
const callbacks = {
137-
onUserInfoChanged: vi.fn(),
138-
onSettingsChanged: vi.fn(),
139-
}
140-
131+
const callbacks = { userChanged: vi.fn(), settingsChanged: vi.fn() }
141132
const cloudService = await CloudService.createInstance(mockContext, callbacks)
142133

143134
expect(cloudService).toBeInstanceOf(CloudService)
@@ -156,9 +147,11 @@ describe("CloudService", () => {
156147

157148
describe("authentication methods", () => {
158149
let cloudService: CloudService
150+
let callbacks: CloudServiceCallbacks
159151

160152
beforeEach(async () => {
161-
cloudService = await CloudService.createInstance(mockContext)
153+
callbacks = { userChanged: vi.fn(), settingsChanged: vi.fn() }
154+
cloudService = await CloudService.createInstance(mockContext, callbacks)
162155
})
163156

164157
it("should delegate login to AuthService", async () => {
@@ -168,7 +161,7 @@ describe("CloudService", () => {
168161

169162
it("should delegate logout to AuthService", async () => {
170163
await cloudService.logout()
171-
expect(mockAuthService.logout).toHaveBeenCalledWith(expect.any(Function))
164+
expect(mockAuthService.logout).toHaveBeenCalled()
172165
})
173166

174167
it("should delegate isAuthenticated to AuthService", () => {
@@ -201,7 +194,7 @@ describe("CloudService", () => {
201194

202195
it("should delegate handleAuthCallback to AuthService", async () => {
203196
await cloudService.handleAuthCallback("code", "state")
204-
expect(mockAuthService.handleCallback).toHaveBeenCalledWith("code", "state", expect.any(Function))
197+
expect(mockAuthService.handleCallback).toHaveBeenCalledWith("code", "state")
205198
})
206199
})
207200

packages/cloud/src/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { CloudUserInfo } from "@roo-code/types"
2+
3+
export interface CloudServiceCallbacks {
4+
userChanged?: (userInfo: CloudUserInfo | undefined) => void
5+
settingsChanged?: () => void
6+
}

src/extension.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ export async function activate(context: vscode.ExtensionContext) {
7070

7171
// Initialize Roo Code Cloud service.
7272
await CloudService.createInstance(context, {
73-
onUserInfoChanged: (userInfo) =>
73+
userChanged: (userInfo) =>
7474
ClineProvider.getVisibleInstance()?.postMessageToWebview({ type: "authenticatedUser", userInfo }),
75-
onSettingsChanged: () => ClineProvider.getVisibleInstance()?.postStateToWebview(),
75+
settingsChanged: () => ClineProvider.getVisibleInstance()?.postStateToWebview(),
7676
})
7777

7878
// Initialize i18n for internationalization support

0 commit comments

Comments
 (0)