diff --git a/src/plus/gk/authenticationConnection.ts b/src/plus/gk/authenticationConnection.ts index 566c9ac..eaab741 100644 --- a/src/plus/gk/authenticationConnection.ts +++ b/src/plus/gk/authenticationConnection.ts @@ -44,11 +44,7 @@ export class AuthenticationConnection implements Disposable { let rsp: Response; try { - rsp = await this.connection.fetch( - Uri.joinPath(this.connection.baseApiUri, 'user').toString(), - undefined, - token, - ); + rsp = await this.connection.fetchApi('user', undefined, token); } catch (ex) { Logger.error(ex, scope); throw ex; @@ -78,11 +74,12 @@ export class AuthenticationConnection implements Disposable { ), ); - const uri = Uri.joinPath(this.connection.baseAccountUri, 'register').with({ - query: `${ - scopes.includes('gitlens') ? 'referrer=gitlens&' : '' - }pass-token=true&return-url=${encodeURIComponent(callbackUri.toString())}`, - }); + const uri = this.connection.getAccountsUri( + 'register', + `${scopes.includes('gitlens') ? 'referrer=gitlens&' : ''}pass-token=true&return-url=${encodeURIComponent( + callbackUri.toString(), + )}`, + ); void (await env.openExternal(uri)); // Ensure there is only a single listener for the URI callback, in case the user starts the login process multiple times before completing it diff --git a/src/plus/gk/serverConnection.ts b/src/plus/gk/serverConnection.ts index bcb5835..cc0a692 100644 --- a/src/plus/gk/serverConnection.ts +++ b/src/plus/gk/serverConnection.ts @@ -13,33 +13,45 @@ export class ServerConnection implements Disposable { dispose() {} @memoize() - get baseApiUri(): Uri { + private get accountsUri(): Uri { if (this.container.env === 'staging') { - return Uri.parse('https://stagingapi.gitkraken.com'); + return Uri.parse('https://stagingapp.gitkraken.com'); } if (this.container.env === 'dev') { - return Uri.parse('https://devapi.gitkraken.com'); + return Uri.parse('https://devapp.gitkraken.com'); } - return Uri.parse('https://api.gitkraken.com'); + return Uri.parse('https://app.gitkraken.com'); + } + + getAccountsUri(path?: string, query?: string) { + let uri = path != null ? Uri.joinPath(this.accountsUri, path) : this.accountsUri; + if (query != null) { + uri = uri.with({ query: query }); + } + return uri; } @memoize() - get baseAccountUri(): Uri { + private get baseApiUri(): Uri { if (this.container.env === 'staging') { - return Uri.parse('https://stagingapp.gitkraken.com'); + return Uri.parse('https://stagingapi.gitkraken.com'); } if (this.container.env === 'dev') { - return Uri.parse('https://devapp.gitkraken.com'); + return Uri.parse('https://devapi.gitkraken.com'); } - return Uri.parse('https://app.gitkraken.com'); + return Uri.parse('https://api.gitkraken.com'); + } + + getApiUrl(...pathSegments: string[]) { + return Uri.joinPath(this.baseApiUri, ...pathSegments).toString(); } @memoize() - get baseGkApiUri(): Uri { + private get baseGkDevApiUri(): Uri { if (this.container.env === 'staging') { return Uri.parse('https://staging-api.gitkraken.dev'); } @@ -51,8 +63,12 @@ export class ServerConnection implements Disposable { return Uri.parse('https://api.gitkraken.dev'); } + getGkDevApiUrl(...pathSegments: string[]) { + return Uri.joinPath(this.baseGkDevApiUri, ...pathSegments).toString(); + } + @memoize() - get baseSiteUri(): Uri { + get siteUri(): Uri { const { env } = this.container; if (env === 'staging') { return Uri.parse('https://staging.gitkraken.com'); @@ -65,6 +81,14 @@ export class ServerConnection implements Disposable { return Uri.parse('https://gitkraken.com'); } + getSiteUri(path?: string, query?: string) { + let uri = path != null ? Uri.joinPath(this.siteUri, path) : this.siteUri; + if (query != null) { + uri = uri.with({ query: query }); + } + return uri; + } + @memoize() get userAgent(): string { // TODO@eamodio figure out standardized format/structure for our user agents @@ -86,6 +110,9 @@ export class ServerConnection implements Disposable { ...init?.headers, }, }; + + // TODO@eamodio handle common response errors + return await _fetch(url, options); } catch (ex) { Logger.error(ex, scope); @@ -93,14 +120,22 @@ export class ServerConnection implements Disposable { } } - async fetchGraphQL(url: RequestInfo, request: GraphQLRequest, init?: RequestInit) { - return this.fetch(url, { + async fetchApi(path: string, init?: RequestInit, token?: string): Promise { + return this.fetch(this.getApiUrl(path), init, token); + } + + async fetchApiGraphQL(path: string, request: GraphQLRequest, init?: RequestInit) { + return this.fetchApi(path, { method: 'POST', ...init, body: JSON.stringify(request), }); } + async fetchGkDevApi(path: string, init?: RequestInit, token?: string): Promise { + return this.fetch(this.getGkDevApiUrl(path), init, token); + } + private async getAccessToken() { const session = await this.container.subscription.getAuthenticationSession(); if (session != null) return session.accessToken; @@ -114,3 +149,7 @@ export interface GraphQLRequest { operationName?: string; variables?: Record; } + +export function getUrl(base: Uri, ...pathSegments: string[]) { + return Uri.joinPath(base, ...pathSegments).toString(); +} diff --git a/src/plus/subscription/subscriptionService.ts b/src/plus/subscription/subscriptionService.ts index ada8ee1..a0e67d2 100644 --- a/src/plus/subscription/subscriptionService.ts +++ b/src/plus/subscription/subscriptionService.ts @@ -17,7 +17,6 @@ import { ProgressLocation, StatusBarAlignment, ThemeColor, - Uri, window, } from 'vscode'; import { getPlatform } from '@env/platform'; @@ -324,7 +323,7 @@ export class SubscriptionService implements Disposable { @log() manage(): void { - void env.openExternal(this.connection.baseAccountUri); + void env.openExternal(this.connection.getAccountsUri()); } @log() @@ -334,11 +333,7 @@ export class SubscriptionService implements Disposable { if (this._subscription.account == null) { this.showPlans(); } else { - void env.openExternal( - Uri.joinPath(this.connection.baseAccountUri, 'subscription').with({ - query: 'product=gitlens&license=PRO', - }), - ); + void env.openExternal(this.connection.getAccountsUri('subscription', 'product=gitlens&license=PRO')); } await this.showAccountView(); } @@ -356,8 +351,8 @@ export class SubscriptionService implements Disposable { if (session == null) return false; try { - const rsp = await this.connection.fetch( - Uri.joinPath(this.connection.baseApiUri, 'resend-email').toString(), + const rsp = await this.connection.fetchApi( + 'resend-email', { method: 'POST', body: JSON.stringify({ id: session.account.id }), @@ -410,7 +405,7 @@ export class SubscriptionService implements Disposable { } private showPlans(): void { - void env.openExternal(Uri.joinPath(this.connection.baseSiteUri, 'gitlens/pricing')); + void env.openExternal(this.connection.getSiteUri('gitlens/pricing')); } @gate() @@ -550,8 +545,8 @@ export class SubscriptionService implements Disposable { previewExpiresOn: this._subscription.previewTrial?.expiresOn, }; - const rsp = await this.connection.fetch( - Uri.joinPath(this.connection.baseApiUri, 'gitlens/checkin').toString(), + const rsp = await this.connection.fetchApi( + 'gitlens/checkin', { method: 'POST', body: JSON.stringify(checkInData), diff --git a/src/plus/workspaces/workspacesApi.ts b/src/plus/workspaces/workspacesApi.ts index b4acc07..838f0eb 100644 --- a/src/plus/workspaces/workspacesApi.ts +++ b/src/plus/workspaces/workspacesApi.ts @@ -1,4 +1,3 @@ -import { Uri } from 'vscode'; import type { RequestInit } from '@env/fetch'; import type { Container } from '../../container'; import { Logger } from '../../system/logger'; @@ -478,10 +477,6 @@ export class WorkspacesApi { } private async fetch(request: GraphQLRequest, init?: RequestInit) { - return this.connection.fetchGraphQL( - Uri.joinPath(this.connection.baseApiUri, 'api/projects/graphql').toString(), - request, - init, - ); + return this.connection.fetchApiGraphQL('api/projects/graphql', request, init); } }