Skip to content

Commit 1ec3170

Browse files
committed
refactor: remove call from cc
1 parent 597393d commit 1ec3170

File tree

2 files changed

+81
-114
lines changed

2 files changed

+81
-114
lines changed

packages/core/src/shared/clients/clientWrapper.ts

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,28 @@ import globals from '../extensionGlobals'
77
import { AwsClient, AwsClientConstructor, AwsCommand, AwsCommandConstructor } from '../awsClientBuilderV3'
88
import { PaginationConfiguration, Paginator } from '@aws-sdk/types'
99
import { AsyncCollection, toCollection } from '../utilities/asyncCollection'
10-
import { isDefined } from '../utilities/tsUtils'
11-
// import { PerfLog } from '../logger/perfLogger'
12-
// import { truncateProps } from '../utilities/textUtilities'
13-
// import { getLogger } from '../logger/logger'
14-
// import { ToolkitError } from '../errors'
10+
import { hasKey, isDefined } from '../utilities/tsUtils'
11+
import { PerfLog } from '../logger/perfLogger'
12+
import { getLogger } from '../logger/logger'
13+
import { truncateProps } from '../utilities/textUtilities'
14+
import { ToolkitError } from '../errors'
1515

1616
type SDKPaginator<C, CommandInput extends object, CommandOutput extends object> = (
1717
config: Omit<PaginationConfiguration, 'client'> & { client: C },
1818
input: CommandInput,
1919
...rest: any[]
2020
) => Paginator<CommandOutput>
21+
22+
interface RequestOptions<Output extends object> {
23+
/**
24+
* Resolve this value if the request fails. If not present, will re-throw error.
25+
*/
26+
fallbackValue?: Output
27+
/**
28+
* Do not used cached client for the request.
29+
*/
30+
ignoreCache?: boolean
31+
}
2132
export abstract class ClientWrapper<C extends AwsClient> implements vscode.Disposable {
2233
protected client?: C
2334

@@ -38,29 +49,39 @@ export abstract class ClientWrapper<C extends AwsClient> implements vscode.Dispo
3849
CommandOutput extends object,
3950
CommandOptions extends CommandInput,
4051
Command extends AwsCommand<CommandInput, CommandOutput>,
41-
>(command: AwsCommandConstructor<CommandInput, Command>, commandOptions: CommandOptions): Promise<CommandOutput> {
42-
// const action = 'API Request'
43-
// const perflog = new PerfLog(action)
44-
return await this.getClient().send(new command(commandOptions))
45-
// return await this.getClient()
46-
// .send(new command(commandOptions))
47-
// .catch((e) => {
48-
// const errWithoutStack = { ...e, name: e.name, message: e.message }
49-
// delete errWithoutStack['stack']
50-
// const timecost = perflog.elapsed().toFixed(1)
51-
// getLogger().error(
52-
// `${action} failed (time: %dms) \nparams: %O\nerror: %O`,
53-
// timecost,
54-
// truncateProps(commandOptions, 20, ['nextToken']),
55-
// errWithoutStack
56-
// )
57-
// throw new ToolkitError(`${action}: ${errWithoutStack.message}`, {
58-
// code: extractCode(errWithoutStack),
59-
// cause: errWithoutStack,
60-
// })
61-
// })
52+
>(
53+
command: AwsCommandConstructor<CommandInput, Command>,
54+
commandOptions: CommandOptions,
55+
requestOptions?: RequestOptions<CommandOutput>
56+
): Promise<CommandOutput> {
57+
const action = 'API Request'
58+
const perflog = new PerfLog(action)
59+
return await this.getClient(requestOptions?.ignoreCache)
60+
.send(new command(commandOptions))
61+
.catch(async (e) => {
62+
await this.onError(e)
63+
const errWithoutStack = { ...e, name: e.name, message: e.message }
64+
delete errWithoutStack['stack']
65+
const timecost = perflog.elapsed().toFixed(1)
66+
getLogger().error(
67+
`${action} failed (time: %dms) \nparams: %O\nerror: %O`,
68+
timecost,
69+
truncateProps(commandOptions, 20, ['nextToken']),
70+
errWithoutStack
71+
)
72+
if (requestOptions?.fallbackValue) {
73+
return requestOptions.fallbackValue
74+
}
75+
throw new ToolkitError(`${action}: ${errWithoutStack.message}`, {
76+
code: extractCode(errWithoutStack),
77+
cause: errWithoutStack,
78+
})
79+
})
6280
}
6381

82+
// Intended to be overwritten by subclasses to implement custom error handling behavior.
83+
protected onError(_: Error): void | Promise<void> {}
84+
6485
protected makePaginatedRequest<CommandInput extends object, CommandOutput extends object, Output extends object>(
6586
paginator: SDKPaginator<C, CommandInput, CommandOutput>,
6687
input: CommandInput,
@@ -89,10 +110,10 @@ export abstract class ClientWrapper<C extends AwsClient> implements vscode.Dispo
89110
}
90111
}
91112

92-
// function extractCode(e: Error): string {
93-
// return hasKey(e, 'code') && typeof e['code'] === 'string'
94-
// ? e.code
95-
// : hasKey(e, 'Code') && typeof e['Code'] === 'string'
96-
// ? e.Code
97-
// : e.name
98-
// }
113+
function extractCode(e: Error): string {
114+
return hasKey(e, 'code') && typeof e['code'] === 'string'
115+
? e.code
116+
: hasKey(e, 'Code') && typeof e['Code'] === 'string'
117+
? e.Code
118+
: e.name
119+
}

packages/core/src/shared/clients/codecatalystClient.ts

Lines changed: 27 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ import {
9898
import { SsoConnection } from '../../auth/connection'
9999
import { DevSettings } from '../settings'
100100
import { getServiceEnvVarConfig } from '../vscode/env'
101-
import { AwsCommand, AwsCommandConstructor } from '../awsClientBuilderV3'
102101
import { ClientWrapper } from './clientWrapper'
103102
import { ServiceException } from '@aws-sdk/smithy-client'
104103
import { AccessDeniedException } from '@aws-sdk/client-sso-oidc'
@@ -335,62 +334,11 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
335334
return { id: this.userDetails.userId, name: this.userDetails.userName }
336335
}
337336

338-
private async call<
339-
CommandInput extends object,
340-
CommandOutput extends object,
341-
CommandOptions extends CommandInput,
342-
Command extends AwsCommand<CommandInput, CommandOutput>,
343-
>(
344-
cmd: AwsCommandConstructor<CommandInput, Command>,
345-
commandOptions: CommandOptions,
346-
silent: true,
347-
defaultVal: CommandOutput
348-
): Promise<CommandOutput>
349-
private async call<
350-
CommandInput extends object,
351-
CommandOutput extends object,
352-
CommandOptions extends CommandInput,
353-
Command extends AwsCommand<CommandInput, CommandOutput>,
354-
>(
355-
cmd: AwsCommandConstructor<CommandInput, Command>,
356-
commandOptions: CommandOptions,
357-
silent: false
358-
): Promise<CommandOutput>
359-
private async call<
360-
CommandInput extends object,
361-
CommandOutput extends object,
362-
CommandOptions extends CommandInput,
363-
Command extends AwsCommand<CommandInput, CommandOutput>,
364-
>(
365-
cmd: AwsCommandConstructor<CommandInput, Command>,
366-
commandOptions: CommandOptions,
367-
silent: boolean,
368-
defaultVal?: CommandOutput
369-
): Promise<CommandOutput> {
337+
protected override async onError(e: Error): Promise<void> {
370338
const bearerToken = (await this.connection.getToken()).accessToken
371-
372-
return new Promise<CommandOutput>(async (resolve, reject) => {
373-
try {
374-
const data = await this.makeRequest<CommandInput, CommandOutput, CommandOptions, Command>(
375-
cmd,
376-
commandOptions
377-
)
378-
resolve(data)
379-
} catch (e) {
380-
const error = e as Error
381-
if (error instanceof ServiceException && isAccessDeniedError(error)) {
382-
CodeCatalystClientInternal.identityCache.delete(bearerToken)
383-
}
384-
if (silent && defaultVal !== undefined) {
385-
resolve(defaultVal)
386-
} else {
387-
// SDKv3 does not have error codes so we use the name instead (see: https://github.com/aws/aws-sdk-js-v3/issues/759)
388-
reject(
389-
new ToolkitError(`CodeCatalyst: request failed with error`, { cause: error, code: error.name })
390-
)
391-
}
392-
}
393-
})
339+
if (e instanceof ServiceException && isAccessDeniedError(e)) {
340+
CodeCatalystClientInternal.identityCache.delete(bearerToken)
341+
}
394342

395343
function isAccessDeniedError(e: ServiceException): boolean {
396344
return (
@@ -412,7 +360,7 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
412360
args: CreateAccessTokenRequest
413361
): Promise<RequiredProps<CreateAccessTokenResponse, 'secret'>> {
414362
try {
415-
return await this.call(CreateAccessTokenCommand, args, false)
363+
return await this.makeRequest(CreateAccessTokenCommand, args)
416364
} catch (e) {
417365
if ((e as Error).name === 'ServiceQuotaExceededException') {
418366
throw new ToolkitError('Access token limit exceeded', { cause: e as Error })
@@ -422,7 +370,7 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
422370
}
423371

424372
public async getSubscription(request: GetSubscriptionRequest): Promise<CodeCatalyst.GetSubscriptionResponse> {
425-
return this.call(GetSubscriptionCommand, request, false)
373+
return this.makeRequest(GetSubscriptionCommand, request)
426374
}
427375

428376
/**
@@ -443,7 +391,7 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
443391
return CodeCatalystClientInternal.identityCache.get(accessToken)!
444392
}
445393

446-
const r: VerifySessionCommandOutput = await this.call(VerifySessionCommand, {}, false)
394+
const r: VerifySessionCommandOutput = await this.makeRequest(VerifySessionCommand, {})
447395
assertHasProps(r, 'identity')
448396

449397
CodeCatalystClientInternal.identityCache.set(accessToken, r.identity)
@@ -460,20 +408,20 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
460408
}
461409

462410
private async getUserDetails(args: GetUserDetailsRequest) {
463-
const resp: GetUserDetailsCommandOutput = await this.call(GetUserDetailsCommand, args, false)
411+
const resp: GetUserDetailsCommandOutput = await this.makeRequest(GetUserDetailsCommand, args)
464412
assertHasProps(resp, 'userId', 'userName', 'displayName', 'primaryEmail')
465413

466414
return { ...resp, version: resp.version } as const
467415
}
468416

469417
public async getSpace(request: GetSpaceRequest): Promise<CodeCatalystOrg> {
470-
const resp: GetSpaceCommandOutput = await this.call(GetSpaceCommand, request, false)
418+
const resp: GetSpaceCommandOutput = await this.makeRequest(GetSpaceCommand, request)
471419
assertHasProps(resp, 'name', 'regionName')
472420
return { ...resp, type: 'org' }
473421
}
474422

475423
public async getProject(request: RequiredProps<GetProjectRequest, 'spaceName'>): Promise<CodeCatalystProject> {
476-
const resp: GetProjectCommandOutput = await this.call(GetProjectCommand, request, false)
424+
const resp: GetProjectCommandOutput = await this.makeRequest(GetProjectCommand, request)
477425
assertHasProps(resp, 'name')
478426
return { ...resp, type: 'project', org: { name: request.spaceName } }
479427
}
@@ -483,7 +431,7 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
483431
*/
484432
public listSpaces(request: ListSpacesRequest = {}): AsyncCollection<CodeCatalystOrg[]> {
485433
const requester: (request: ListSpacesRequest) => Promise<ListSpacesResponse> = async (request) =>
486-
this.call(ListSpacesCommand, request, true, { items: [] })
434+
this.makeRequest(ListSpacesCommand, request, { fallbackValue: { items: [] } })
487435
const collection = pageableToCollection(requester, request, 'nextToken', 'items').filter(isDefined)
488436
// ts doesn't recognize nested assertion, so we add cast.This is safe because we assert it in the same line.
489437
return collection.map((summaries) => summaries.filter(hasName).map(toOrg))
@@ -512,7 +460,7 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
512460
]
513461

514462
const requester: (request: ListProjectsRequest) => Promise<ListProjectsResponse> = (request) =>
515-
this.call(ListProjectsCommand, request, true, { items: [] })
463+
this.makeRequest(ListProjectsCommand, request, { fallbackValue: { items: [] } })
516464

517465
const collection = pageableToCollection(requester, request, 'nextToken', 'items')
518466
return collection.filter(isDefined).map((summaries) => summaries.filter(hasName).map(toProject))
@@ -532,7 +480,7 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
532480
public listDevEnvironments(proj: CodeCatalystProject): AsyncCollection<DevEnvironment[]> {
533481
const initRequest = { spaceName: proj.org.name, projectName: proj.name }
534482
const requester: (request: ListDevEnvironmentsRequest) => Promise<ListDevEnvironmentsResponse> = (request) =>
535-
this.call(ListDevEnvironmentsCommand, request, true, { items: [] })
483+
this.makeRequest(ListDevEnvironmentsCommand, request, { fallbackValue: { items: [] } })
536484
const collection = pageableToCollection(requester, initRequest, 'nextToken' as never, 'items').filter(isDefined)
537485
// ts unable to recognize nested assertion here, so we need to cast. This is safe because we assert it in the same line.
538486
return collection.map((envs) => {
@@ -552,11 +500,10 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
552500
thirdParty: boolean = true
553501
): AsyncCollection<CodeCatalystRepo[]> {
554502
const requester = async (r: typeof request) => {
555-
const allRepositories: Promise<ListSourceRepositoriesResponse> = this.call(
503+
const allRepositories: Promise<ListSourceRepositoriesResponse> = this.makeRequest(
556504
ListSourceRepositoriesCommand,
557505
r,
558-
true,
559-
{ items: [] }
506+
{ fallbackValue: { items: [] } }
560507
)
561508
let finalRepositories = allRepositories
562509

@@ -596,7 +543,7 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
596543
>
597544
): AsyncCollection<CodeCatalystBranch[]> {
598545
const requester = async (r: typeof request) =>
599-
this.call(ListSourceRepositoryBranchesCommand, r, true, { items: [] })
546+
this.makeRequest(ListSourceRepositoryBranchesCommand, r, { fallbackValue: { items: [] } })
600547
const collection = pageableToCollection(requester, request, 'nextToken' as never, 'items')
601548

602549
return collection
@@ -645,17 +592,16 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
645592
public async createSourceBranch(
646593
args: CreateSourceRepositoryBranchRequest
647594
): Promise<CreateSourceRepositoryBranchResponse> {
648-
return this.call(CreateSourceRepositoryBranchCommand, args, false)
595+
return this.makeRequest(CreateSourceRepositoryBranchCommand, args)
649596
}
650597

651598
/**
652599
* Gets the git source host URL for the given CodeCatalyst or third-party repo.
653600
*/
654601
public async getRepoCloneUrl(args: GetSourceRepositoryCloneUrlsRequest): Promise<string> {
655-
const r: GetSourceRepositoryCloneUrlsResponse = await this.call(
602+
const r: GetSourceRepositoryCloneUrlsResponse = await this.makeRequest(
656603
GetSourceRepositoryCloneUrlsCommand,
657-
args,
658-
false
604+
args
659605
)
660606
assertHasProps(r, 'https')
661607
// The git extension skips over credential providers if the username is included in the authority
@@ -667,7 +613,7 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
667613
args: RequiredProps<CreateDevEnvironmentRequest, 'projectName' | 'spaceName'>
668614
): Promise<DevEnvironment> {
669615
const request = fixAliasInRequest(args)
670-
const response: CreateDevEnvironmentCommandOutput = await this.call(CreateDevEnvironmentCommand, request, false)
616+
const response: CreateDevEnvironmentCommandOutput = await this.makeRequest(CreateDevEnvironmentCommand, request)
671617
assertHasProps(response, 'id')
672618

673619
return this.getDevEnvironment({
@@ -678,29 +624,29 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
678624
}
679625

680626
public async startDevEnvironment(args: StartDevEnvironmentRequest): Promise<StartDevEnvironmentResponse> {
681-
return this.call(StartDevEnvironmentCommand, args, false)
627+
return this.makeRequest(StartDevEnvironmentCommand, args)
682628
}
683629

684630
public async createProject(
685631
args: RequiredProps<CreateProjectRequest, 'displayName' | 'spaceName'>
686632
): Promise<CodeCatalystProject> {
687-
await this.call(CreateProjectCommand, args, false)
633+
await this.makeRequest(CreateProjectCommand, args)
688634

689635
return { ...args, name: args.displayName, type: 'project', org: { name: args.spaceName } }
690636
}
691637

692638
public async startDevEnvironmentSession(
693639
args: StartDevEnvironmentSessionRequest
694640
): Promise<StartDevEnvironmentSessionResponse & { sessionId: string }> {
695-
const r: StartDevEnvironmentSessionResponse = await this.call(StartDevEnvironmentSessionCommand, args, false)
641+
const r: StartDevEnvironmentSessionResponse = await this.makeRequest(StartDevEnvironmentSessionCommand, args)
696642
if (!r.sessionId) {
697643
throw new TypeError('got falsy dev environment "sessionId"')
698644
}
699645
return { ...r, sessionId: r.sessionId }
700646
}
701647

702648
public async stopDevEnvironment(args: StopDevEnvironmentRequest): Promise<StopDevEnvironmentResponse> {
703-
return this.call(StopDevEnvironmentCommand, args, false)
649+
return this.makeRequest(StopDevEnvironmentCommand, args)
704650
}
705651

706652
public async getDevEnvironment(
@@ -710,7 +656,7 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
710656
delete (a as any).ides
711657
delete (a as any).repositories
712658

713-
const r: GetDevEnvironmentResponse = await this.call(GetDevEnvironmentCommand, a, false)
659+
const r: GetDevEnvironmentResponse = await this.makeRequest(GetDevEnvironmentCommand, a)
714660
const summary = { ...args, ...r }
715661
if (!isValidEnvSummary(summary)) {
716662
throw new ToolkitError(`GetDevEnvironment failed due to response missing required properties`)
@@ -720,12 +666,12 @@ class CodeCatalystClientInternal extends ClientWrapper<CodeCatalystSDKClient> {
720666
}
721667

722668
public async deleteDevEnvironment(args: DeleteDevEnvironmentRequest): Promise<DeleteDevEnvironmentResponse> {
723-
return this.call(DeleteDevEnvironmentCommand, args, false)
669+
return this.makeRequest(DeleteDevEnvironmentCommand, args)
724670
}
725671

726672
public updateDevEnvironment(args: UpdateDevEnvironmentRequest): Promise<UpdateDevEnvironmentResponse> {
727673
const request = fixAliasInRequest(args)
728-
return this.call(UpdateDevEnvironmentCommand, request, false)
674+
return this.makeRequest(UpdateDevEnvironmentCommand, request)
729675
}
730676

731677
/**

0 commit comments

Comments
 (0)