Skip to content

Commit 5d58fca

Browse files
committed
refactor(codecatalyst): use globalState abstraction
1 parent f6a02ae commit 5d58fca

File tree

10 files changed

+55
-54
lines changed

10 files changed

+55
-54
lines changed

packages/core/src/auth/secondaryAuth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export class SecondaryAuth<T extends Connection = Connection> {
9999
public readonly toolLabel: string,
100100
public readonly isUsable: (conn: Connection) => conn is T,
101101
private readonly auth: Auth,
102-
private readonly memento = globals.globalState
102+
private readonly memento = globals.context.globalState
103103
) {
104104
const handleConnectionChanged = async (newActiveConn?: Connection) => {
105105
if (newActiveConn === undefined && this.#activeConnection?.id) {

packages/core/src/codecatalyst/auth.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { Auth } from '../auth/auth'
99
import * as localizedText from '../shared/localizedText'
1010
import { getSecondaryAuth, setScopes } from '../auth/secondaryAuth'
1111
import { getLogger } from '../shared/logger'
12+
import globals from '../shared/extensionGlobals'
1213
import { ToolkitError, isAwsError } from '../shared/errors'
1314
import { MetricName, MetricShapes, telemetry } from '../shared/telemetry/telemetry'
1415
import { openUrl } from '../shared/utilities/vsCodeUtils'
@@ -70,12 +71,8 @@ export class CodeCatalystAuthenticationProvider {
7071
private readonly onDidChangeEmitter = new vscode.EventEmitter<void>()
7172
public readonly onDidChange = this.onDidChangeEmitter.event
7273

73-
private readonly mementoKey = 'codecatalyst.connections'
74-
7574
public constructor(
7675
protected readonly storage: CodeCatalystAuthStorage,
77-
protected readonly memento: vscode.Memento,
78-
7976
public readonly auth = Auth.instance,
8077
public readonly secondaryAuth = getSecondaryAuth(
8178
auth,
@@ -364,7 +361,7 @@ export class CodeCatalystAuthenticationProvider {
364361
}
365362

366363
private getStates(): Record<string, ConnectionState> {
367-
return this.memento.get(this.mementoKey, {} as Record<string, ConnectionState>)
364+
return globals.globalState.tryGet<Record<string, ConnectionState>>('codecatalyst.connections', Object, {})
368365
}
369366

370367
public tryGetConnectionState(conn: SsoConnection): ConnectionState | undefined {
@@ -380,7 +377,7 @@ export class CodeCatalystAuthenticationProvider {
380377
}
381378

382379
private async setConnectionState(conn: SsoConnection, state: ConnectionState) {
383-
await this.memento.update(this.mementoKey, {
380+
await globals.globalState.update('codecatalyst.connections', {
384381
...this.getStates(),
385382
[conn.id]: state,
386383
})
@@ -424,7 +421,7 @@ export class CodeCatalystAuthenticationProvider {
424421
return CodeCatalystAuthenticationProvider.#instance
425422
}
426423

427-
public static fromContext(ctx: Pick<vscode.ExtensionContext, 'secrets' | 'globalState'>) {
428-
return (this.#instance ??= new this(new CodeCatalystAuthStorage(ctx.secrets), ctx.globalState))
424+
public static fromContext(ctx: Pick<vscode.ExtensionContext, 'secrets'>) {
425+
return (this.#instance ??= new this(new CodeCatalystAuthStorage(ctx.secrets)))
429426
}
430427
}

packages/core/src/codecatalyst/commands.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ export class CodeCatalystCommands {
335335
return devenv
336336
}
337337

338-
public static fromContext(ctx: Pick<vscode.ExtensionContext, 'secrets' | 'globalState'>) {
338+
public static fromContext(ctx: Pick<vscode.ExtensionContext, 'secrets'>) {
339339
const auth = CodeCatalystAuthenticationProvider.fromContext(ctx)
340340

341341
return new this(auth)

packages/core/src/codecatalyst/reconnect.ts

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ function handleRestart(conn: SsoConnection, ctx: ExtContext, envId: string | und
5555
getLogger().info('codecatalyst: attempting to poll dev environments')
5656

5757
// Reconnect devenvs (if coming from a restart)
58-
reconnectDevEnvs(conn, ctx).catch((err) => {
58+
reconnectDevEnvs(conn).catch((err) => {
5959
getLogger().error(`codecatalyst: error while resuming devenvs: ${err}`)
6060
})
6161
}
@@ -66,9 +66,12 @@ function handleRestart(conn: SsoConnection, ctx: ExtContext, envId: string | und
6666
* @param conn a connection that may be used for CodeCatalyst
6767
* @param ctx the extension context
6868
*/
69-
async function reconnectDevEnvs(conn: SsoConnection, ctx: ExtContext): Promise<void> {
70-
const memento = ctx.extensionContext.globalState
71-
const pendingDevEnvs = memento.get<Record<string, DevEnvMemento>>('CODECATALYST_RECONNECT', {})
69+
async function reconnectDevEnvs(conn: SsoConnection): Promise<void> {
70+
const pendingDevEnvs = globals.globalState.tryGet<Record<string, DevEnvMemento>>(
71+
'CODECATALYST_RECONNECT',
72+
Object,
73+
{}
74+
)
7275
const validDevEnvs = filterInvalidDevEnvs(pendingDevEnvs)
7376
if (Object.keys(validDevEnvs).length === 0) {
7477
return
@@ -93,7 +96,7 @@ async function reconnectDevEnvs(conn: SsoConnection, ctx: ExtContext): Promise<v
9396
progress.report({ message: progressTitle })
9497
const client = await createClient(conn)
9598

96-
return pollDevEnvs(client, progress, token, memento, validDevEnvs)
99+
return pollDevEnvs(client, progress, token, validDevEnvs)
97100
}
98101
)
99102
}
@@ -115,14 +118,13 @@ function filterInvalidDevEnvs(devenvs: Record<string, DevEnvMemento>) {
115118
/**
116119
* Ensure that all devenvs that are currently being looked at set to attempting to reconnect so that they are not looked at
117120
* by any other instance of VSCode.
118-
* @param memento
119121
* @param devenvs
120122
*/
121-
function setWatchedDevEnvStatus(memento: vscode.Memento, devenvs: Record<string, DevEnvMemento>, watchStatus: boolean) {
123+
function setWatchedDevEnvStatus(devenvs: Record<string, DevEnvMemento>, watchStatus: boolean) {
122124
for (const [id, detail] of Object.entries(devenvs)) {
123125
devenvs[id] = { ...detail, attemptingReconnect: watchStatus }
124126
}
125-
return memento.update('CODECATALYST_RECONNECT', devenvs)
127+
return globals.globalState.update('CODECATALYST_RECONNECT', devenvs)
126128
}
127129

128130
/**
@@ -131,26 +133,24 @@ function setWatchedDevEnvStatus(memento: vscode.Memento, devenvs: Record<string,
131133
* 2. In a terminating state or expired, in which case no longer watch the devenv
132134
* 3. Failed to start, in which case notify the user
133135
* @param client A connected client
134-
* @param memento vscode global storage library
135136
* @param devenvs All VALID devenvs that are not being watched by any other VSCode instance
136137
*/
137138
async function pollDevEnvs(
138139
client: CodeCatalystClient,
139140
progress: vscode.Progress<{ message: string }>,
140141
token: vscode.CancellationToken,
141-
memento: vscode.Memento,
142142
devenvs: Record<string, DevEnvMemento>
143143
) {
144144
// Ensure that all devenvs that you want to look at are attempting reconnection
145145
// and won't be watched by any other VSCode instance
146-
await setWatchedDevEnvStatus(memento, devenvs, true)
146+
await setWatchedDevEnvStatus(devenvs, true)
147147

148148
const shouldCloseRootInstance = Object.keys(devenvs).length === 1
149149
getLogger().info(`codecatalyst: reconnect: pollDevEnvs: ${Object.keys(devenvs).length}`)
150150

151151
while (Object.keys(devenvs).length > 0) {
152152
if (token.isCancellationRequested) {
153-
await setWatchedDevEnvStatus(memento, devenvs, false)
153+
await setWatchedDevEnvStatus(devenvs, false)
154154
return
155155
}
156156

@@ -197,7 +197,7 @@ async function pollDevEnvs(
197197
progress.report({ message: `Dev Environment ${devenvName} has expired` })
198198
}
199199
} catch {
200-
await failDevEnv(memento, id)
200+
await failDevEnv(id)
201201
delete devenvs[id]
202202
void showViewLogsMessage(
203203
localize('AWS.codecatalyst.reconnect', 'Unable to reconnect to ${0}', devenvName)
@@ -220,14 +220,13 @@ function isExpired(previousConnectionTime: number): boolean {
220220
}
221221

222222
/**
223-
* When a devenv fails, remove it from the memento so we no longer watch it in the future
224-
* @param memento The memento instance from vscode
223+
* When a devenv fails, remove it from globalState so we no longer watch it in the future
225224
* @param devenvId the id of the deveng to fail
226225
*/
227-
function failDevEnv(memento: vscode.Memento, devenvId: string) {
228-
const curr = memento.get<Record<string, DevEnvMemento>>('CODECATALYST_RECONNECT', {})
226+
function failDevEnv(devenvId: string) {
227+
const curr = globals.globalState.tryGet<Record<string, DevEnvMemento>>('CODECATALYST_RECONNECT', Object, {})
229228
delete curr[devenvId]
230-
return memento.update('CODECATALYST_RECONNECT', curr)
229+
return globals.globalState.update('CODECATALYST_RECONNECT', curr)
231230
}
232231

233232
async function openReconnectedDevEnv(
@@ -268,8 +267,11 @@ export function isLongReconnect(oldSettings: DevEnvironmentSettings, newSettings
268267
}
269268

270269
export function saveReconnectionInformation(devenv: DevEnvironmentId & Pick<DevEnvironment, 'alias'>): Thenable<void> {
271-
const memento = globals.context.globalState
272-
const pendingReconnects = memento.get<Record<string, DevEnvMemento>>('CODECATALYST_RECONNECT', {})
270+
const pendingReconnects = globals.globalState.tryGet<Record<string, DevEnvMemento>>(
271+
'CODECATALYST_RECONNECT',
272+
Object,
273+
{}
274+
)
273275
const workspaceFolders = vscode.workspace.workspaceFolders
274276
const currentWorkspace =
275277
workspaceFolders !== undefined && workspaceFolders.length > 0 ? workspaceFolders[0].uri.fsPath : '/projects'
@@ -281,12 +283,15 @@ export function saveReconnectionInformation(devenv: DevEnvironmentId & Pick<DevE
281283
previousConnectionTimestamp: Date.now(),
282284
alias: devenv.alias,
283285
}
284-
return memento.update('CODECATALYST_RECONNECT', pendingReconnects)
286+
return globals.globalState.update('CODECATALYST_RECONNECT', pendingReconnects)
285287
}
286288

287289
export function removeReconnectionInformation(devenv: DevEnvironmentId): Thenable<void> {
288-
const memento = globals.context.globalState
289-
const pendingReconnects = memento.get<Record<string, DevEnvMemento>>('CODECATALYST_RECONNECT', {})
290+
const pendingReconnects = globals.globalState.tryGet<Record<string, DevEnvMemento>>(
291+
'CODECATALYST_RECONNECT',
292+
Object,
293+
{}
294+
)
290295
delete pendingReconnects[devenv.id]
291-
return memento.update('CODECATALYST_RECONNECT', pendingReconnects)
296+
return globals.globalState.update('CODECATALYST_RECONNECT', pendingReconnects)
292297
}

packages/core/src/dev/beta.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,19 @@ import { CancellationError } from '../shared/utilities/timeoutUtils'
2222
const localize = nls.loadMessageBundle()
2323

2424
const downloadIntervalMs = 1000 * 60 * 60 * 24 // A day in milliseconds
25-
const betaToolkitKey = 'dev.beta'
2625

2726
interface BetaToolkit {
2827
readonly needUpdate: boolean
2928
readonly lastCheck: number
3029
}
3130

3231
function getBetaToolkitData(vsixUrl: string): BetaToolkit | undefined {
33-
return globals.context.globalState.get<Record<string, BetaToolkit>>(betaToolkitKey, {})[vsixUrl]
32+
return globals.globalState.tryGet<Record<string, BetaToolkit>>('dev.beta', Object, {})[vsixUrl]
3433
}
3534

3635
async function updateBetaToolkitData(vsixUrl: string, data: BetaToolkit) {
37-
await globals.context.globalState.update(betaToolkitKey, {
38-
...globals.context.globalState.get<Record<string, BetaToolkit>>(betaToolkitKey, {}),
36+
await globals.globalState.update('dev.beta', {
37+
...globals.globalState.get<Record<string, BetaToolkit>>('dev.beta', {}),
3938
[vsixUrl]: data,
4039
})
4140
}

packages/core/src/shared/globalState.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,19 @@ type globalKey =
4545
| 'CODEWHISPERER_SELECTED_CUSTOMIZATION'
4646
| 'CODEWHISPERER_USER_GROUP'
4747
| 'awsTelemetryNoticeVersionAck'
48+
| 'codecatalyst.connections'
49+
| 'dev.beta'
4850
| 'globalsMostRecentVersion'
4951
| 'gumby.wasQCodeTransformationUsed'
5052
| 'hasAlreadyOpenedAmazonQ'
5153
| 'isExtensionFirstUse'
5254
| 'lastExtensionVersion'
55+
| 'lastSelectedRegion'
56+
| 'recentCredentials'
57+
// List of regions enabled in AWS Explorer.
58+
| 'region'
59+
// TODO: implement this via `PromptSettings` instead of globalState.
60+
| 'sam.sync.updateMessage'
5361

5462
/**
5563
* Extension-local (not visible to other vscode extensions) shared state which persists after IDE

packages/core/src/shared/ui/common/region.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@ export function createRegionPrompter(
2727
regions = globals.regionProvider.getRegions(),
2828
options: RegionPrompterOptions = {}
2929
): QuickPickPrompter<Region> {
30-
const lastRegionKey = 'lastSelectedRegion'
3130
const defaultRegion = options.defaultRegion ?? globals.regionProvider.defaultRegionId
3231
const filteredRegions = regions.filter(
3332
(r) => !options.serviceFilter || globals.regionProvider.isServiceInRegion(options.serviceFilter, r.id)
3433
)
3534

36-
const lastRegion = globals.context.globalState.get<Region>(lastRegionKey)
35+
const lastRegion = globals.globalState.tryGet<Region>('lastSelectedRegion', Object)
3736
const items = filteredRegions.map((region) => ({
3837
label: region.name,
3938
detail: region.id,
@@ -60,9 +59,7 @@ export function createRegionPrompter(
6059

6160
return prompter.transform((item) => {
6261
getLogger().debug('createRegionPrompter: selected %O', item)
63-
globals.context.globalState.update(lastRegionKey, item).then(undefined, (e) => {
64-
getLogger().error('globalState.update() failed: %s', (e as Error).message)
65-
})
62+
globals.globalState.tryUpdate('lastSelectedRegion', item)
6663
return item
6764
})
6865
}

packages/core/src/shared/utilities/messages.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -364,17 +364,14 @@ export async function copyToClipboard(data: string, label?: string): Promise<voi
364364
getLogger().verbose('copied %s to clipboard: %O', label ?? '', data)
365365
}
366366

367-
export async function showOnce<T>(
368-
key: string,
369-
fn: () => Promise<T>,
370-
memento = globals.context.globalState
371-
): Promise<T | undefined> {
372-
if (memento.get(key)) {
367+
/** TODO: eliminate this, callers should use `PromptSettings` instead. */
368+
export async function showOnce<T>(key: 'sam.sync.updateMessage', fn: () => Promise<T>): Promise<T | undefined> {
369+
if (globals.globalState.tryGet(key, Boolean, false)) {
373370
return
374371
}
375372

376373
const result = fn()
377-
await memento.update(key, true)
374+
await globals.globalState.update(key, true)
378375

379376
return result
380377
}

packages/core/src/test/codecatalyst/auth.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import assert from 'assert'
77
import { CodeCatalystAuthStorage, CodeCatalystAuthenticationProvider, defaultScopes } from '../../codecatalyst/auth'
88
import { getTestWindow } from '../shared/vscode/window'
9-
import { FakeMemento, FakeSecretStorage } from '../fakeExtensionContext'
9+
import { FakeSecretStorage } from '../fakeExtensionContext'
1010
import { createBuilderIdProfile, createSsoProfile, createTestAuth } from '../credentials/testUtil'
1111
import Sinon from 'sinon'
1212
import { isAnySsoConnection } from '../../auth/connection'
@@ -21,7 +21,6 @@ describe('CodeCatalystAuthenticationProvider', async function () {
2121
auth = createTestAuth()
2222
codecatalystAuth = new CodeCatalystAuthenticationProvider(
2323
new CodeCatalystAuthStorage(new FakeSecretStorage()),
24-
new FakeMemento(),
2524
auth
2625
)
2726
})

packages/core/src/test/login/webview/vue/backend_toolkit.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
CodeCatalystAuthStorage,
1717
defaultScopes,
1818
} from '../../../../codecatalyst/auth'
19-
import { FakeSecretStorage, FakeMemento } from '../../../fakeExtensionContext'
19+
import { FakeSecretStorage } from '../../../fakeExtensionContext'
2020
import * as authUtils from '../../../../auth/utils'
2121

2222
// TODO: remove auth page and tests
@@ -37,7 +37,6 @@ describe('Toolkit Login', function () {
3737
auth = createTestAuth()
3838
codecatalystAuth = new CodeCatalystAuthenticationProvider(
3939
new CodeCatalystAuthStorage(new FakeSecretStorage()),
40-
new FakeMemento(),
4140
auth
4241
)
4342
sandbox.stub(Auth, 'instance').value(auth)

0 commit comments

Comments
 (0)