From b32a02c37bcea2c618da9d2cb1d6a82bbfc3a726 Mon Sep 17 00:00:00 2001 From: Alan Hamlett Date: Fri, 15 Nov 2024 13:33:39 +0100 Subject: [PATCH] Add apiUrl vscode settings json --- package.json | 7 +++- src/options.ts | 49 ++++++++++++++-------------- src/wakatime.ts | 86 ++++++++++++++++++++++++------------------------- 3 files changed, 72 insertions(+), 70 deletions(-) diff --git a/package.json b/package.json index 0ae840e..2f5f804 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,11 @@ "type": "string", "description": "Defaults to value from ~/.wakatime.cfg, unless running in browser.", "scope": "application" + }, + "wakatime.apiUrl": { + "type": "string", + "description": "Defaults to https://api.wakatime.com/api/v1.", + "scope": "application" } } } @@ -146,4 +151,4 @@ "webpack-cli": "^4.9.2", "which": "^2.0.2" } -} +} \ No newline at end of file diff --git a/src/options.ts b/src/options.ts index c723870..087446e 100644 --- a/src/options.ts +++ b/src/options.ts @@ -202,7 +202,7 @@ export class Options { return this.logFile; } - public async getApiKeyAsync(): Promise { + public async getApiKey(): Promise { if (!Utils.apiKeyInvalid(this.cache.api_key)) { return this.cache.api_key; } @@ -233,6 +233,11 @@ export class Options { return apiKey; } catch (err) { this.logger.debug(`Exception while reading API Key from config file: ${err}`); + if (`${err}`.includes('spawn EPERM')) { + vscode.window.showErrorMessage( + 'Microsoft Defender is blocking WakaTime. Please allow WakaTime to run so it can upload code stats to your dashboard.', + ); + } return ''; } } @@ -275,30 +280,14 @@ export class Options { } } - public getApiKey(callback: (apiKey: string | null) => void): void { - this.getApiKeyAsync() - .then((apiKey) => { - if (!Utils.apiKeyInvalid(apiKey)) { - callback(apiKey); - } else { - callback(null); - } - }) - .catch((err) => { - this.logger.warn(`Unable to get api key: ${err}`); - if (`${err}`.includes('spawn EPERM')) { - vscode.window.showErrorMessage( - 'Microsoft Defender is blocking WakaTime. Please allow WakaTime to run so it can upload code stats to your dashboard.', - ); - } - callback(null); - }); - } - private getApiKeyFromEditor(): string { return vscode.workspace.getConfiguration().get('wakatime.apiKey') || ''; } + private getApiUrlFromEditor(): string { + return vscode.workspace.getConfiguration().get('wakatime.apiUrl') || ''; + } + // Support for gitpod.io https://github.com/wakatime/vscode-wakatime/pull/220 public getApiKeyFromEnv(): string { if (this.cache.api_key_from_env !== undefined) return this.cache.api_key_from_env; @@ -308,8 +297,17 @@ export class Options { return this.cache.api_key_from_env; } - public async getApiUrl(): Promise { - let apiUrl = this.getApiUrlFromEnv(); + public async getApiUrl(checkSettingsFile = false): Promise { + let apiUrl = this.getApiUrlFromEditor(); + + if (!apiUrl) { + apiUrl = this.getApiUrlFromEnv(); + } + + if (!apiUrl && !checkSettingsFile) { + return ''; + } + if (!apiUrl) { try { apiUrl = await this.getSettingAsync('settings', 'api_url'); @@ -317,6 +315,7 @@ export class Options { this.logger.debug(`Exception while reading API Url from config file: ${err}`); } } + if (!apiUrl) apiUrl = 'https://api.wakatime.com/api/v1'; const suffixes = ['/', '.bulk', '/users/current/heartbeats', '/heartbeats', '/heartbeat']; @@ -329,7 +328,7 @@ export class Options { return apiUrl; } - public getApiUrlFromEnv(): string { + private getApiUrlFromEnv(): string { if (this.cache.api_url_from_env !== undefined) return this.cache.api_url_from_env; this.cache.api_url_from_env = process.env.WAKATIME_API_URL || ''; @@ -338,7 +337,7 @@ export class Options { } public hasApiKey(callback: (valid: boolean) => void): void { - this.getApiKeyAsync() + this.getApiKey() .then((apiKey) => callback(!Utils.apiKeyInvalid(apiKey))) .catch((err) => { this.logger.warn(`Unable to check for api key: ${err}`); diff --git a/src/wakatime.ts b/src/wakatime.ts index f7513bb..3de8744 100644 --- a/src/wakatime.ts +++ b/src/wakatime.ts @@ -226,30 +226,29 @@ export class WakaTime { this.statusBarTeamOther.tooltip = tooltipText; } - public promptForApiKey(hidden: boolean = true): void { - this.options.getApiKey((defaultVal: string | null) => { - if (Utils.apiKeyInvalid(defaultVal ?? undefined)) defaultVal = ''; - let promptOptions = { - prompt: 'WakaTime Api Key', - placeHolder: 'Enter your api key from https://wakatime.com/api-key', - value: defaultVal!, - ignoreFocusOut: true, - password: hidden, - validateInput: Utils.apiKeyInvalid.bind(this), - }; - vscode.window.showInputBox(promptOptions).then((val) => { - if (val != undefined) { - let invalid = Utils.apiKeyInvalid(val); - if (!invalid) { - this.options.setSetting('settings', 'api_key', val, false); - } else vscode.window.setStatusBarMessage(invalid); - } else vscode.window.setStatusBarMessage('WakaTime api key not provided'); - }); + public async promptForApiKey(hidden: boolean = true): Promise { + let defaultVal = await this.options.getApiKey(); + if (Utils.apiKeyInvalid(defaultVal ?? undefined)) defaultVal = ''; + let promptOptions = { + prompt: 'WakaTime Api Key', + placeHolder: 'Enter your api key from https://wakatime.com/api-key', + value: defaultVal!, + ignoreFocusOut: true, + password: hidden, + validateInput: Utils.apiKeyInvalid.bind(this), + }; + vscode.window.showInputBox(promptOptions).then((val) => { + if (val != undefined) { + let invalid = Utils.apiKeyInvalid(val); + if (!invalid) { + this.options.setSetting('settings', 'api_key', val, false); + } else vscode.window.setStatusBarMessage(invalid); + } else vscode.window.setStatusBarMessage('WakaTime api key not provided'); }); } public async promptForApiUrl(): Promise { - const apiUrl = await this.options.getApiUrl(); + const apiUrl = await this.options.getApiUrl(true); let promptOptions = { prompt: 'WakaTime Api Url (Defaults to https://api.wakatime.com/api/v1)', placeHolder: 'https://api.wakatime.com/api/v1', @@ -379,7 +378,7 @@ export class WakaTime { } public async openDashboardWebsite(): Promise { - const url = (await this.options.getApiUrl()).replace('/api/v1', '').replace('api.', ''); + const url = (await this.options.getApiUrl(true)).replace('/api/v1', '').replace('api.', ''); vscode.env.openExternal(vscode.Uri.parse(url)); } @@ -519,31 +518,30 @@ export class WakaTime { }, this.debounceMs); } - private sendHeartbeat( + private async sendHeartbeat( doc: vscode.TextDocument, time: number, selection: vscode.Position, isWrite: boolean, isCompiling: boolean, isDebugging: boolean, - ): void { - this.options.getApiKey((apiKey) => { - if (apiKey) { - this._sendHeartbeat(doc, time, selection, isWrite, isCompiling, isDebugging); - } else { - this.promptForApiKey(); - } - }); + ): Promise { + const apiKey = await this.options.getApiKey(); + if (apiKey) { + await this._sendHeartbeat(doc, time, selection, isWrite, isCompiling, isDebugging); + } else { + await this.promptForApiKey(); + } } - private _sendHeartbeat( + private async _sendHeartbeat( doc: vscode.TextDocument, time: number, selection: vscode.Position, isWrite: boolean, isCompiling: boolean, isDebugging: boolean, - ): void { + ): Promise { if (!this.dependencies.isCliInstalled()) return; let file = doc.fileName; @@ -580,7 +578,7 @@ export class WakaTime { const apiKey = this.options.getApiKeyFromEnv(); if (!Utils.apiKeyInvalid(apiKey)) args.push('--key', Utils.quote(apiKey)); - const apiUrl = this.options.getApiUrlFromEnv(); + const apiUrl = await this.options.getApiUrl(); if (apiUrl) args.push('--api-url', Utils.quote(apiUrl)); const project = this.getProjectName(doc.uri); @@ -612,7 +610,7 @@ export class WakaTime { this.logger.error(error.toString()); } }); - proc.on('close', (code, _signal) => { + proc.on('close', async (code, _signal) => { if (code == 0) { if (this.showStatusBar) this.getCodingActivity(); } else if (code == 102 || code == 112) { @@ -642,7 +640,7 @@ export class WakaTime { let now: number = Date.now(); if (this.lastApiKeyPrompted < now - 86400000) { // only prompt once per day - this.promptForApiKey(false); + await this.promptForApiKey(false); this.lastApiKeyPrompted = now; } } else { @@ -656,7 +654,7 @@ export class WakaTime { }); } - private getCodingActivity() { + private async getCodingActivity() { if (!this.showStatusBar) return; const cutoff = Date.now() - this.fetchTodayInterval; @@ -664,13 +662,13 @@ export class WakaTime { this.lastFetchToday = Date.now(); - this.options.getApiKey((apiKey) => { - if (!apiKey) return; - this._getCodingActivity(); - }); + const apiKey = await this.options.getApiKey(); + if (!apiKey) return; + + await this._getCodingActivity(); } - private _getCodingActivity() { + private async _getCodingActivity() { if (!this.dependencies.isCliInstalled()) return; let user_agent = @@ -682,7 +680,7 @@ export class WakaTime { const apiKey = this.options.getApiKeyFromEnv(); if (!Utils.apiKeyInvalid(apiKey)) args.push('--key', Utils.quote(apiKey)); - const apiUrl = this.options.getApiUrlFromEnv(); + const apiUrl = await this.options.getApiUrl(); if (apiUrl) args.push('--api-url', Utils.quote(apiUrl)); if (Desktop.isWindows()) { @@ -764,7 +762,7 @@ export class WakaTime { } } - private updateTeamStatusBar(doc?: vscode.TextDocument) { + private async updateTeamStatusBar(doc?: vscode.TextDocument) { if (!this.showStatusBarTeam) return; if (!this.hasTeamFeatures) return; if (!this.dependencies.isCliInstalled()) return; @@ -802,7 +800,7 @@ export class WakaTime { const apiKey = this.options.getApiKeyFromEnv(); if (!Utils.apiKeyInvalid(apiKey)) args.push('--key', Utils.quote(apiKey)); - const apiUrl = this.options.getApiUrlFromEnv(); + const apiUrl = await this.options.getApiUrl(); if (apiUrl) args.push('--api-url', Utils.quote(apiUrl)); const project = this.getProjectName(doc.uri);