/ src / utils / awsAuthStatusManager.ts
awsAuthStatusManager.ts
 1  /**
 2   * Singleton manager for cloud-provider authentication status (AWS Bedrock,
 3   * GCP Vertex). Communicates auth refresh state between auth utilities and
 4   * React components / SDK output. The SDK 'auth_status' message shape is
 5   * provider-agnostic, so a single manager serves all providers.
 6   *
 7   * Legacy name: originally AWS-only; now used by all cloud auth refresh flows.
 8   */
 9  
10  import { createSignal } from './signal.js'
11  
12  export type AwsAuthStatus = {
13    isAuthenticating: boolean
14    output: string[]
15    error?: string
16  }
17  
18  export class AwsAuthStatusManager {
19    private static instance: AwsAuthStatusManager | null = null
20    private status: AwsAuthStatus = {
21      isAuthenticating: false,
22      output: [],
23    }
24    private changed = createSignal<[status: AwsAuthStatus]>()
25  
26    static getInstance(): AwsAuthStatusManager {
27      if (!AwsAuthStatusManager.instance) {
28        AwsAuthStatusManager.instance = new AwsAuthStatusManager()
29      }
30      return AwsAuthStatusManager.instance
31    }
32  
33    getStatus(): AwsAuthStatus {
34      return {
35        ...this.status,
36        output: [...this.status.output],
37      }
38    }
39  
40    startAuthentication(): void {
41      this.status = {
42        isAuthenticating: true,
43        output: [],
44      }
45      this.changed.emit(this.getStatus())
46    }
47  
48    addOutput(line: string): void {
49      this.status.output.push(line)
50      this.changed.emit(this.getStatus())
51    }
52  
53    setError(error: string): void {
54      this.status.error = error
55      this.changed.emit(this.getStatus())
56    }
57  
58    endAuthentication(success: boolean): void {
59      if (success) {
60        // Clear the status completely on success
61        this.status = {
62          isAuthenticating: false,
63          output: [],
64        }
65      } else {
66        // Keep the output visible on failure
67        this.status.isAuthenticating = false
68      }
69      this.changed.emit(this.getStatus())
70    }
71  
72    subscribe = this.changed.subscribe
73  
74    // Clean up for testing
75    static reset(): void {
76      if (AwsAuthStatusManager.instance) {
77        AwsAuthStatusManager.instance.changed.clear()
78        AwsAuthStatusManager.instance = null
79      }
80    }
81  }