Skip to content

Commit 21aaf9d

Browse files
committed
Testing
1 parent c7c9de1 commit 21aaf9d

File tree

6 files changed

+139
-6
lines changed

6 files changed

+139
-6
lines changed

packages/core/src/auth/auth2.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import { LanguageClient } from 'vscode-languageclient'
4141
import { getLogger } from '../shared/logger/logger'
4242
import { ToolkitError } from '../shared/errors'
4343
import { useDeviceFlow } from './sso/ssoAccessTokenProvider'
44+
import { getCacheFileWatcher } from './sso/cache'
4445

4546
export const notificationTypes = {
4647
updateBearerToken: new RequestType<UpdateCredentialsParams, ResponseMessage, Error>(
@@ -74,12 +75,18 @@ export type TokenSource = IamIdentityCenterSsoTokenSource | AwsBuilderIdSsoToken
7475
* Handles auth requests to the Identity Server in the Amazon Q LSP.
7576
*/
7677
export class LanguageClientAuth {
78+
readonly #ssoCacheWatcher = getCacheFileWatcher()
79+
7780
constructor(
7881
private readonly client: LanguageClient,
7982
private readonly clientName: string,
8083
public readonly encryptionKey: Buffer
8184
) {}
8285

86+
public get cacheWatcher() {
87+
return this.#ssoCacheWatcher
88+
}
89+
8390
getSsoToken(
8491
tokenSource: TokenSource,
8592
login: boolean = false,
@@ -160,6 +167,11 @@ export class LanguageClientAuth {
160167
registerSsoTokenChangedHandler(ssoTokenChangedHandler: (params: SsoTokenChangedParams) => any) {
161168
this.client.onNotification(ssoTokenChangedRequestType.method, ssoTokenChangedHandler)
162169
}
170+
171+
registerCacheWatcher(cacheChangedHandler: (event: string) => any) {
172+
this.cacheWatcher.onDidCreate(() => cacheChangedHandler('create'))
173+
this.cacheWatcher.onDidDelete(() => cacheChangedHandler('delete'))
174+
}
163175
}
164176

165177
/**

packages/core/src/codewhisperer/region/regionProfileManager.ts

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ import { localize } from '../../shared/utilities/vsCodeUtils'
2424
import { IAuthProvider } from '../util/authUtil'
2525
import { Commands } from '../../shared/vscode/commands2'
2626
import { CachedResource } from '../../shared/utilities/resourceCache'
27+
import { fs } from '../../shared/fs/fs'
28+
import path from 'path'
29+
import { globalKey } from '../../shared/globalState'
2730

2831
// TODO: is there a better way to manage all endpoint strings in one place?
2932
export const defaultServiceConfig: CodeWhispererConfig = {
@@ -57,6 +60,7 @@ export class RegionProfileManager {
5760
public readonly onDidChangeRegionProfile = this._onDidChangeRegionProfile.event
5861
// Store the last API results (for UI propuse) so we don't need to call service again if doesn't require "latest" result
5962
private _profiles: RegionProfile[] = []
63+
//private sharedState: SharedState
6064

6165
private readonly cache = new (class extends CachedResource<RegionProfile[]> {
6266
constructor(private readonly profileProvider: () => Promise<RegionProfile[]>) {
@@ -120,7 +124,22 @@ export class RegionProfileManager {
120124
return this._profiles
121125
}
122126

123-
constructor(private readonly authProvider: IAuthProvider) {}
127+
constructor(private readonly authProvider: IAuthProvider) {
128+
const getProfileFunction = () =>
129+
globals.globalState.tryGet<{ [label: string]: RegionProfile }>('aws.amazonq.regionProfiles', Object, {})
130+
131+
const profileChangedHandler = async () => {
132+
const profile = await this.loadPersistedRegionProfle()
133+
void this._switchRegionProfile(profile[this.authProvider.profileName], 'reload')
134+
}
135+
136+
GlobalStatePoller.create(getProfileFunction, profileChangedHandler)
137+
138+
// , async () => {
139+
// void this._switchRegionProfile((await this.loadPersistedRegionProfle())[this.authProvider.profileName], 'user')
140+
// })
141+
//this.sharedState = new SharedState('aws.amazonq.regionProfiles')
142+
}
124143

125144
async getProfiles(): Promise<RegionProfile[]> {
126145
return this.cache.getResource()
@@ -232,6 +251,10 @@ export class RegionProfileManager {
232251
}
233252

234253
private async _switchRegionProfile(regionProfile: RegionProfile | undefined, source: ProfileSwitchIntent) {
254+
if (this._activeRegionProfile?.arn === regionProfile?.arn) {
255+
return
256+
}
257+
235258
this._activeRegionProfile = regionProfile
236259

237260
this._onDidChangeRegionProfile.fire({
@@ -246,6 +269,8 @@ export class RegionProfileManager {
246269
// persist to state
247270
await this.persistSelectRegionProfile()
248271

272+
//this.sharedState.updateSharedState(this._activeRegionProfile)
273+
249274
// Force status bar to reflect this change in state
250275
await Commands.tryExecute('aws.amazonq.refreshStatusBar')
251276
}
@@ -258,7 +283,7 @@ export class RegionProfileManager {
258283

259284
// Note: should be called after [this.authProvider.isConnected()] returns non null
260285
async restoreRegionProfile() {
261-
const previousSelected = this.loadPersistedRegionProfle()[this.authProvider.profileName] || undefined
286+
const previousSelected = (await this.loadPersistedRegionProfle())[this.authProvider.profileName] || undefined
262287
if (!previousSelected) {
263288
return
264289
}
@@ -292,7 +317,7 @@ export class RegionProfileManager {
292317
await this.switchRegionProfile(previousSelected, 'reload')
293318
}
294319

295-
private loadPersistedRegionProfle(): { [label: string]: RegionProfile } {
320+
private async loadPersistedRegionProfle(): Promise<{ [label: string]: RegionProfile }> {
296321
const previousPersistedState = globals.globalState.tryGet<{ [label: string]: RegionProfile }>(
297322
'aws.amazonq.regionProfiles',
298323
Object,
@@ -317,6 +342,13 @@ export class RegionProfileManager {
317342

318343
previousPersistedState[this.authProvider.profileName] = this.activeRegionProfile
319344
await globals.globalState.update('aws.amazonq.regionProfiles', previousPersistedState)
345+
346+
const persistedState = globals.globalState.tryGet<{ [label: string]: RegionProfile }>(
347+
'aws.amazonq.regionProfiles',
348+
Object,
349+
{}
350+
)
351+
console.log(persistedState)
320352
}
321353

322354
async generateQuickPickItem(): Promise<DataQuickPickItem<string>[]> {
@@ -360,6 +392,7 @@ export class RegionProfileManager {
360392
if (arn) {
361393
if (this.activeRegionProfile && this.activeRegionProfile.arn === arn) {
362394
this._activeRegionProfile = undefined
395+
//this.sharedState.updateSharedState(this._activeRegionProfile)
363396
}
364397

365398
const profiles = this.loadPersistedRegionProfle()
@@ -419,3 +452,82 @@ export class RegionProfileManager {
419452
return c
420453
}
421454
}
455+
456+
export class GlobalStatePoller {
457+
protected oldValue: any
458+
protected getState: Function
459+
protected changeHandler: Function
460+
461+
constructor(getState: Function, changeHandler: Function) {
462+
this.getState = getState
463+
this.changeHandler = changeHandler
464+
this.oldValue = getState()
465+
}
466+
467+
static create(getState: Function, changeHandler: () => void) {
468+
const instance = new GlobalStatePoller(getState, changeHandler)
469+
instance.poll()
470+
return instance
471+
}
472+
473+
poll() {
474+
const interval = 1000 // ms
475+
setInterval(() => {
476+
const newValue = this.getState()
477+
if (this.oldValue !== newValue) {
478+
this.oldValue = newValue
479+
this.changeHandler()
480+
}
481+
}, interval)
482+
}
483+
}
484+
485+
export class SharedState {
486+
readonly key: globalKey
487+
protected value: any
488+
readonly filePath: string
489+
490+
constructor(key: globalKey) {
491+
this.key = key
492+
this.filePath = path.join(globals.context.globalStorageUri.fsPath, `${key}.json`)
493+
}
494+
495+
static async create(key: globalKey, changeHandler: () => void) {
496+
const instance = new SharedState(key)
497+
await instance.createGlobalStateFile()
498+
const fileWatcher = instance.getSharedStateFileWatcher()
499+
fileWatcher.onDidChange(changeHandler)
500+
}
501+
502+
protected async createGlobalStateFile() {
503+
if (!(await fs.existsFile(this.filePath))) {
504+
await this.updateFile()
505+
}
506+
}
507+
508+
protected async updateFile() {
509+
await fs.writeFile(this.filePath, `${new Date().toISOString()}`, { encoding: 'utf8' })
510+
}
511+
512+
protected getSharedStateFileWatcher() {
513+
const watcher = vscode.workspace.createFileSystemWatcher(
514+
new vscode.RelativePattern(globals.context.globalStorageUri, `${this.key}.json`)
515+
)
516+
globals.context.subscriptions.push(watcher)
517+
return watcher
518+
}
519+
520+
async updateSharedState(value: any) {
521+
const persistedState = globals.globalState.tryGet<{ [label: string]: RegionProfile }>(
522+
'aws.amazonq.regionProfiles',
523+
Object,
524+
{}
525+
)
526+
console.log(persistedState)
527+
if (value === this.value && value !== undefined) {
528+
return
529+
}
530+
this.value = value
531+
await this.updateFile()
532+
}
533+
}

packages/core/src/codewhisperer/util/authUtil.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export class AuthUtil implements IAuthProvider {
9090
this.regionProfileManager.onDidChangeRegionProfile(async () => {
9191
await this.setVscodeContextProps()
9292
})
93+
lspAuth.registerCacheWatcher((event: string) => this.cacheChangedHandler(event))
9394
}
9495

9596
// Do NOT use this in production code, only used for testing
@@ -276,6 +277,14 @@ export class AuthUtil implements IAuthProvider {
276277
})
277278
}
278279

280+
private cacheChangedHandler(event: string) {
281+
if (event === 'delete') {
282+
this.logout()
283+
} else if (event === 'create') {
284+
this.restore()
285+
}
286+
}
287+
279288
private async stateChangeHandler(e: AuthStateEvent) {
280289
if (e.state === 'refreshed') {
281290
const params = this.isSsoSession() ? (await this.session.getToken()).updateCredentialsParams : undefined

packages/core/src/shared/fs/fs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export class FileSystem {
123123
* The {@link vscode.workspace.fs} implementation does not explicitly provide an append method
124124
* so we must do it ourselves (this implementation is inefficient).
125125
*/
126-
async appendFile(path: Uri | string, content: Uint8Array | string): Promise<void> {
126+
async appendFile(path: Uri | string, content: Uint8Array | string, overwrite: boolean = false): Promise<void> {
127127
path = toUri(path)
128128

129129
const currentContent: Uint8Array = (await this.existsFile(path))

packages/core/src/shared/globalState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export type globalKey =
5151
| 'aws.amazonq.customization.overrideV2'
5252
| 'aws.amazonq.regionProfiles'
5353
| 'aws.amazonq.regionProfiles.cache'
54-
// Deprecated/legacy names. New keys should start with "aws.".
54+
// Deprecated/legacy names. New keys should start with "aws.".x
5555
| '#sessionCreationDates' // Legacy name from `ssoAccessTokenProvider.ts`.
5656
| 'CODECATALYST_RECONNECT'
5757
| 'CODEWHISPERER_AUTO_SCANS_ENABLED'

packages/toolkit/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "aws-toolkit-vscode",
33
"displayName": "AWS Toolkit",
44
"description": "Including CodeCatalyst, Infrastructure Composer, and support for Lambda, S3, CloudWatch Logs, CloudFormation, and many other services.",
5-
"version": "3.61.0-SNAPSHOT",
5+
"version": "3.61.0-gc7c9de1",
66
"extensionKind": [
77
"workspace"
88
],

0 commit comments

Comments
 (0)