Skip to content

Commit dee9185

Browse files
committed
Splits url handling into UrlProvider
1 parent 4aa7344 commit dee9185

File tree

8 files changed

+140
-135
lines changed

8 files changed

+140
-135
lines changed

src/container.ts

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ConfigurationChangeEvent, Disposable, Event, ExtensionContext } from 'vscode';
2-
import { EventEmitter, ExtensionMode, Uri } from 'vscode';
2+
import { EventEmitter, ExtensionMode } from 'vscode';
33
import {
44
getSharedGKStorageLocationProvider,
55
getSupportedGitProviders,
@@ -30,6 +30,7 @@ import { OrganizationService } from './plus/gk/organizationService';
3030
import { ProductConfigProvider } from './plus/gk/productConfigProvider';
3131
import { ServerConnection } from './plus/gk/serverConnection';
3232
import { SubscriptionService } from './plus/gk/subscriptionService';
33+
import { UrlsProvider } from './plus/gk/urlsProvider';
3334
import { GraphStatusBarController } from './plus/graph/statusbar';
3435
import type { CloudIntegrationService } from './plus/integrations/authentication/cloudIntegrationService';
3536
import { ConfiguredIntegrationService } from './plus/integrations/authentication/configuredIntegrationService';
@@ -193,7 +194,8 @@ export class Container {
193194
configuration.onDidChangeAny(this.onAnyConfigurationChanged, this),
194195
];
195196

196-
this._disposables.push((this._connection = new ServerConnection(this)));
197+
this._urls = new UrlsProvider(this.env);
198+
this._disposables.push((this._connection = new ServerConnection(this, this._urls)));
197199

198200
this._disposables.push(
199201
(this._accountAuthentication = new AccountAuthenticationProvider(this, this._connection)),
@@ -429,7 +431,7 @@ export class Container {
429431
private _enrichments: EnrichmentService | undefined;
430432
get enrichments(): EnrichmentService {
431433
if (this._enrichments == null) {
432-
this._disposables.push((this._enrichments = new EnrichmentService(this, new ServerConnection(this))));
434+
this._disposables.push((this._enrichments = new EnrichmentService(this, this._connection)));
433435
}
434436

435437
return this._enrichments;
@@ -686,6 +688,11 @@ export class Container {
686688
return this._uri;
687689
}
688690

691+
private readonly _urls: UrlsProvider;
692+
get urls(): UrlsProvider {
693+
return this._urls;
694+
}
695+
689696
private readonly _usage: UsageTracker;
690697
get usage(): UsageTracker {
691698
return this._usage;
@@ -827,31 +834,6 @@ export class Container {
827834
},
828835
});
829836
}
830-
831-
@memoize()
832-
private get baseGkDevUri(): Uri {
833-
if (this.env === 'staging') {
834-
return Uri.parse('https://staging.gitkraken.dev');
835-
}
836-
837-
if (this.env === 'dev') {
838-
return Uri.parse('https://dev.gitkraken.dev');
839-
}
840-
841-
return Uri.parse('https://gitkraken.dev');
842-
}
843-
844-
getGkDevUri(path?: string, query?: string): Uri {
845-
let uri = path != null ? Uri.joinPath(this.baseGkDevUri, path) : this.baseGkDevUri;
846-
if (query != null) {
847-
uri = uri.with({ query: query });
848-
}
849-
return uri;
850-
}
851-
852-
generateWebGkDevUrl(path?: string): string {
853-
return this.getGkDevUri(path, '?source=gitlens').toString();
854-
}
855837
}
856838

857839
export function isContainer(container: any): container is Container {

src/plus/drafts/draftsService.ts

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -453,20 +453,13 @@ export class DraftService implements Disposable {
453453

454454
let headers;
455455
if (options?.providerAuth) {
456-
headers = {
457-
'Provider-Auth': Buffer.from(JSON.stringify(options.providerAuth)).toString('base64'),
458-
};
456+
headers = { 'Provider-Auth': Buffer.from(JSON.stringify(options.providerAuth)).toString('base64') };
459457
}
460458

461459
const rsp = await this.connection.fetchGkApi(
462460
'/v1/drafts',
463-
{
464-
method: 'GET',
465-
headers: headers,
466-
},
467-
{
468-
query: queryStrings.length ? queryStrings.join('&') : undefined,
469-
},
461+
{ method: 'GET', headers: headers },
462+
{ query: queryStrings.length ? queryStrings.join('&') : undefined },
470463
);
471464

472465
if (!rsp.ok) {
@@ -870,13 +863,8 @@ export class DraftService implements Disposable {
870863
try {
871864
const rsp = await this.connection.fetchGkApi(
872865
'v1/drafts/counts',
873-
{
874-
method: 'POST',
875-
body: body,
876-
},
877-
{
878-
query: 'type=suggested_pr_change',
879-
},
866+
{ method: 'POST', body: body },
867+
{ query: 'type=suggested_pr_change' },
880868
);
881869

882870
if (!rsp.ok) {
@@ -896,7 +884,7 @@ export class DraftService implements Disposable {
896884
generateWebUrl(draft: Draft): string;
897885
generateWebUrl(draftOrDraftId: Draft | string): string {
898886
const id = typeof draftOrDraftId === 'string' ? draftOrDraftId : draftOrDraftId.id;
899-
return this.container.generateWebGkDevUrl(`/drafts/${id}`);
887+
return this.container.urls.getGkDevUrl(['drafts', id]);
900888
}
901889
}
902890

src/plus/gk/authenticationConnection.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,14 @@ export class AuthenticationConnection implements Disposable {
8282
Uri.parse(`${env.uriScheme}://${this.container.context.extension.id}/${AuthenticationUriPathPrefix}`),
8383
);
8484

85-
const uri = this.container.getGkDevUri(
85+
const url = this.container.urls.getGkDevUrl(
8686
signUp ? 'register' : 'login',
8787
`${scopes.includes('gitlens') ? 'source=gitlens&' : ''}${
8888
context != null ? `context=${context}&` : ''
8989
}state=${encodeURIComponent(gkstate)}&redirect_uri=${encodeURIComponent(callbackUri.toString(true))}`,
9090
);
9191

92-
if (!(await openUrl(uri.toString(true)))) {
92+
if (!(await openUrl(url))) {
9393
Logger.error(undefined, scope, 'Opening login URL failed');
9494

9595
this._pendingStates.delete(scopeKey);
@@ -206,9 +206,7 @@ export class AuthenticationConnection implements Disposable {
206206
state: state ?? '',
207207
}),
208208
},
209-
{
210-
unAuthenticated: true,
211-
},
209+
{ token: false },
212210
);
213211

214212
if (!rsp.ok) {

src/plus/gk/serverConnection.ts

Lines changed: 44 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { RequestError } from '@octokit/request-error';
22
import type { CancellationToken } from 'vscode';
33
import { version as codeVersion, env, Uri, window } from 'vscode';
4-
import type { HeadersInit, RequestInfo, RequestInit, Response } from '@env/fetch';
4+
import type { RequestInfo, RequestInit, Response } from '@env/fetch';
55
import { fetch as _fetch, getProxyAgent } from '@env/fetch';
66
import { getPlatform } from '@env/platform';
77
import type { Disposable } from '../../api/gitlens';
@@ -27,45 +27,27 @@ import { memoize } from '../../system/decorators/-webview/memoize';
2727
import { Logger } from '../../system/logger';
2828
import type { LogScope } from '../../system/logger.scope';
2929
import { getLogScope } from '../../system/logger.scope';
30+
import type { UrlsProvider } from './urlsProvider';
3031

3132
interface FetchOptions {
3233
cancellation?: CancellationToken;
3334
timeout?: number;
3435
}
3536

3637
interface GKFetchOptions extends FetchOptions {
37-
token?: string;
38-
unAuthenticated?: boolean;
39-
query?: string;
38+
token?: string | false;
4039
organizationId?: string | false;
40+
query?: string;
4141
}
4242

4343
export class ServerConnection implements Disposable {
44-
constructor(private readonly container: Container) {}
44+
constructor(
45+
private readonly container: Container,
46+
public readonly urls: UrlsProvider,
47+
) {}
4548

4649
dispose(): void {}
4750

48-
@memoize()
49-
private get baseGkApiUri(): Uri {
50-
if (this.container.env === 'staging') {
51-
return Uri.parse('https://staging-api.gitkraken.dev');
52-
}
53-
54-
if (this.container.env === 'dev') {
55-
return Uri.parse('https://dev-api.gitkraken.dev');
56-
}
57-
58-
return Uri.parse('https://api.gitkraken.dev');
59-
}
60-
61-
getGkApiUrl(...pathSegments: string[]): string {
62-
return Uri.joinPath(this.baseGkApiUri, ...pathSegments).toString();
63-
}
64-
65-
getGkConfigUrl(...pathSegments: string[]): string {
66-
return Uri.joinPath(Uri.parse('https://configs.gitkraken.dev'), 'gitlens', ...pathSegments).toString();
67-
}
68-
6951
@memoize()
7052
get userAgent(): string {
7153
// TODO@eamodio figure out standardized format/structure for our user agents
@@ -121,11 +103,11 @@ export class ServerConnection implements Disposable {
121103
}
122104

123105
async fetchGkApi(path: string, init?: RequestInit, options?: GKFetchOptions): Promise<Response> {
124-
return this.gkFetch(this.getGkApiUrl(path), init, options);
106+
return this.gkFetch(this.urls.getGkApiUrl(path), init, options);
125107
}
126108

127109
async fetchGkConfig(path: string, init?: RequestInit, options?: FetchOptions): Promise<Response> {
128-
return this.fetch(this.getGkConfigUrl(path), init, options);
110+
return this.fetch(this.urls.getGkConfigUrl(path), init, options);
129111
}
130112

131113
async fetchGkApiGraphQL(
@@ -134,15 +116,34 @@ export class ServerConnection implements Disposable {
134116
init?: RequestInit,
135117
options?: GKFetchOptions,
136118
): Promise<Response> {
137-
return this.fetchGkApi(
138-
path,
139-
{
140-
method: 'POST',
141-
...init,
142-
body: JSON.stringify(request),
143-
},
144-
options,
145-
);
119+
return this.fetchGkApi(path, { method: 'POST', ...init, body: JSON.stringify(request) }, options);
120+
}
121+
122+
async getGkHeaders(
123+
token?: string | false,
124+
organizationId?: string | false,
125+
init?: Record<string, string>,
126+
): Promise<Record<string, string>> {
127+
const headers: Record<string, string> = {
128+
'Content-Type': 'application/json',
129+
'Client-Name': this.clientName,
130+
'Client-Version': this.container.version,
131+
'User-Agent': this.userAgent,
132+
...init,
133+
};
134+
135+
token ??= await this.getAccessToken();
136+
if (token) {
137+
headers.Authorization = `Bearer ${token}`;
138+
}
139+
140+
// only check for cached subscription or we'll get into an infinite loop
141+
organizationId ??= (await this.container.subscription.getSubscription(true)).activeOrganization?.id;
142+
if (organizationId) {
143+
headers['gk-org-id'] = organizationId;
144+
}
145+
146+
return headers;
146147
}
147148

148149
private async gkFetch(url: RequestInfo, init?: RequestInit, options?: GKFetchOptions): Promise<Response> {
@@ -152,29 +153,11 @@ export class ServerConnection implements Disposable {
152153
const scope = getLogScope();
153154

154155
try {
155-
let token;
156-
({ token, ...options } = options ?? {});
157-
if (!options?.unAuthenticated) {
158-
token ??= await this.getAccessToken();
159-
}
160-
161-
const headers: Record<string, unknown> = {
162-
Authorization: `Bearer ${token}`,
163-
'Content-Type': 'application/json',
164-
'Client-Name': this.clientName,
165-
'Client-Version': this.container.version,
166-
...init?.headers,
167-
};
168-
169-
// only check for cached subscription or we'll get into an infinite loop
170-
let organizationId = options?.organizationId;
171-
if (organizationId === undefined) {
172-
organizationId = (await this.container.subscription.getSubscription(true)).activeOrganization?.id;
173-
}
174-
175-
if (organizationId) {
176-
headers['gk-org-id'] = organizationId;
177-
}
156+
const headers = await this.getGkHeaders(
157+
options?.token,
158+
options?.organizationId,
159+
init?.headers ? { ...(init?.headers as Record<string, string>) } : undefined,
160+
);
178161

179162
if (options?.query != null) {
180163
if (url instanceof URL) {
@@ -184,14 +167,7 @@ export class ServerConnection implements Disposable {
184167
}
185168
}
186169

187-
const rsp = await this.fetch(
188-
url,
189-
{
190-
...init,
191-
headers: headers as HeadersInit,
192-
},
193-
options,
194-
);
170+
const rsp = await this.fetch(url, { ...init, headers: headers }, options);
195171
if (!rsp.ok) {
196172
await this.handleGkUnsuccessfulResponse(rsp, scope);
197173
} else {

src/plus/gk/subscriptionService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -635,10 +635,10 @@ export class SubscriptionService implements Disposable {
635635

636636
try {
637637
const exchangeToken = await this.container.accountAuthentication.getExchangeToken();
638-
await openUrl(this.container.getGkDevUri('account', `token=${exchangeToken}`).toString(true));
638+
await openUrl(this.container.urls.getGkDevUrl('account', `token=${exchangeToken}`));
639639
} catch (ex) {
640640
Logger.error(ex, scope);
641-
await openUrl(this.container.getGkDevUri('account').toString(true));
641+
await openUrl(this.container.urls.getGkDevUrl('account'));
642642
}
643643
}
644644

@@ -950,7 +950,7 @@ export class SubscriptionService implements Disposable {
950950
Logger.error(ex, scope);
951951
}
952952

953-
aborted = !(await openUrl(this.container.getGkDevUri('purchase/checkout', query.toString()).toString(true)));
953+
aborted = !(await openUrl(this.container.urls.getGkDevUrl('purchase/checkout', query)));
954954

955955
if (aborted) {
956956
return;

0 commit comments

Comments
 (0)