From 0e5c3e28397f431a089a5ac12d097f03e1231d60 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Wed, 22 Jul 2026 01:37:12 +0800 Subject: [PATCH 01/14] feat: add WinGet upgrade option to PowerShell update notification (#5477) - Detect WinGet availability and version on Windows - Offer 'Upgrade with WinGet' when WinGet has a newer version - Offer 'Install WinGet' when WinGet is not installed - Add 'Check WinGet Status' to find winget-pkgs issues/PRs - Fall back to GitHub API when winget CLI is unavailable - Refactor: extract whenSome, skip, addButton helpers - Simplify code with functional filter-map-sort chains --- src/features/UpdatePowerShell.ts | 393 ++++++++++++++++++++++--------- 1 file changed, 278 insertions(+), 115 deletions(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index 17edea4770..5200db0b86 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -12,30 +12,30 @@ interface IUpdateMessageItem extends vscode.MessageItem { id: number; } +async function fetchJSON(url: string): Promise { + const response = await fetch(url); + if (!response.ok) return undefined; + return response.json(); +} + +/** Strip the 4th component from a WinGet version (e.g. "7.4.5.0" → "7.4.5"). */ +function toTriple(v: string): string { + return v.split(".").slice(0, 3).join("."); +} + +/** Await a value/promise, and if non-nullish, pass it to `fn`. */ +async function whenSome( + value: T | undefined | null | Promise, + fn: (value: T) => void | Promise, +): Promise { + const resolved = await value; + if (resolved != null) await fn(resolved); +} + // This attempts to mirror PowerShell's `UpdatesNotification.cs` logic as much as // possibly, documented at: // https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_update_notifications export class UpdatePowerShell { - private static LTSBuildInfoURL = "https://aka.ms/pwsh-buildinfo-lts"; - private static StableBuildInfoURL = "https://aka.ms/pwsh-buildinfo-stable"; - private static PreviewBuildInfoURL = - "https://aka.ms/pwsh-buildinfo-preview"; - private static GitHubWebReleaseURL = - "https://github.com/PowerShell/PowerShell/releases/tag/"; - private static promptOptions: IUpdateMessageItem[] = [ - { - id: 0, - title: "Yes", - }, - { - id: 1, - title: "Not Now", - }, - { - id: 2, - title: "Don't Show Again", - }, - ]; private localVersion: SemVer; constructor( @@ -50,53 +50,37 @@ export class UpdatePowerShell { this.localVersion = new SemVer(versionDetails.commit); } + private skip(reason: string): false { + this.logger.writeDebug(reason); + return false; + } + private shouldCheckForUpdate(): boolean { // Respect user setting. - if (!this.sessionSettings.promptToUpdatePowerShell) { - this.logger.writeDebug( - "Setting 'promptToUpdatePowerShell' was false.", - ); - return false; - } + if (!this.sessionSettings.promptToUpdatePowerShell) + return this.skip("Setting 'promptToUpdatePowerShell' was false."); // Respect environment configuration. - if (process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "off") { - this.logger.writeDebug( - "Environment variable 'POWERSHELL_UPDATECHECK' was 'Off'.", - ); - return false; - } + if (process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "off") + return this.skip("Environment variable 'POWERSHELL_UPDATECHECK' was 'Off'."); // Skip prompting when using Windows PowerShell for now. - if (this.localVersion.compare("6.0.0") === -1) { + if (this.localVersion.compare("6.0.0") === -1) // TODO: Maybe we should announce PowerShell Core? - this.logger.writeDebug( - "Not prompting to update Windows PowerShell.", - ); - return false; - } + return this.skip("Not prompting to update Windows PowerShell."); if (this.localVersion.prerelease.length > 1) { // Daily builds look like '7.3.0-daily20221206.1' which split to // ['daily20221206', '1'] and development builds look like // '7.3.0-preview.3-508-g07175...' which splits to ['preview', // '3-508-g0717...']. The ellipsis is hiding a 40 char hash. - const daily = this.localVersion.prerelease[0].toString(); - const commit = this.localVersion.prerelease[1].toString(); - // Skip if PowerShell is self-built, that is, this contains a commit hash. - if (commit.length >= 40) { - this.logger.writeDebug( - "Not prompting to update development build.", - ); - return false; - } + if (this.localVersion.prerelease[1].toString().length >= 40) + return this.skip("Not prompting to update development build."); // Skip if preview is a daily build. - if (daily.toLowerCase().startsWith("daily")) { - this.logger.writeDebug("Not prompting to update daily build."); - return false; - } + if (this.localVersion.prerelease[0].toString().toLowerCase().startsWith("daily")) + return this.skip("Not prompting to update daily build."); } // TODO: Check if network is available? @@ -105,17 +89,10 @@ export class UpdatePowerShell { } private async getRemoteVersion(url: string): Promise { - const response = await fetch(url); - if (!response.ok) { - return undefined; - } - // Looks like: - // { - // "ReleaseDate": "2022-10-20T22:01:38Z", - // "BlobName": "v7-2-7", - // "ReleaseTag": "v7.2.7" - // } - const data = await response.json(); + const data = await fetchJSON<{ + ReleaseTag: string; + }>(url); + if (!data) return undefined; this.logger.writeDebug( `Received from '${url}':\n${JSON.stringify(data, undefined, 2)}`, ); @@ -128,40 +105,16 @@ export class UpdatePowerShell { } this.logger.writeDebug("Checking for PowerShell update..."); - const tags: string[] = []; - if (process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "lts") { - // Only check for update to LTS. - this.logger.writeDebug("Checking for LTS update..."); - const tag = await this.getRemoteVersion( - UpdatePowerShell.LTSBuildInfoURL, - ); - if (tag != undefined) { - tags.push(tag); - } - } else { - // Check for update to stable. - this.logger.writeDebug("Checking for stable update..."); - const tag = await this.getRemoteVersion( - UpdatePowerShell.StableBuildInfoURL, - ); - if (tag != undefined) { - tags.push(tag); - } - - // Also check for a preview update. - if (this.localVersion.prerelease.length > 0) { - this.logger.writeDebug("Checking for preview update..."); - const tag = await this.getRemoteVersion( - UpdatePowerShell.PreviewBuildInfoURL, - ); - if (tag != undefined) { - tags.push(tag); - } - } - } - - for (const tag of tags) { - if (this.localVersion.compare(tag) === -1) { + const suffixes = process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "lts" + ? ["lts"] + : this.localVersion.prerelease.length > 0 + ? ["stable", "preview"] + : ["stable"]; + this.logger.writeDebug(`Checking for ${suffixes.join(" and ")} update...`); + for (const tag of await Promise.all( + suffixes.map(s => this.getRemoteVersion(`https://aka.ms/pwsh-buildinfo-${s}`)), + )) { + if (tag != undefined && this.localVersion.compare(tag) === -1) { return tag; } } @@ -172,11 +125,7 @@ export class UpdatePowerShell { public async checkForUpdate(): Promise { try { - const tag = await this.maybeGetNewRelease(); - if (tag) { - await this.promptToUpdate(tag); - return; - } + await whenSome(this.maybeGetNewRelease(), tag => this.promptToUpdate(tag)); } catch (err) { // Best effort. This probably failed to fetch the data from GitHub. this.logger.writeWarning( @@ -186,10 +135,9 @@ export class UpdatePowerShell { } private async openReleaseInBrowser(tag: string): Promise { - const url = vscode.Uri.parse( - UpdatePowerShell.GitHubWebReleaseURL + tag, + await vscode.env.openExternal( + vscode.Uri.parse(`https://github.com/PowerShell/PowerShell/releases/tag/${tag}`), ); - await vscode.env.openExternal(url); } private async promptToUpdate(tag: string): Promise { @@ -197,11 +145,109 @@ export class UpdatePowerShell { this.logger.write( `Prompting to update PowerShell v${this.localVersion.version} to v${releaseVersion.version}.`, ); - const result = await vscode.window.showInformationMessage( + + // Dynamically build prompt options: add WinGet button if it has this version. + const options: IUpdateMessageItem[] = []; + let wingetIndex = -1; + let wingetStatusIndex = -1; + let browserIndex: number; + let notNowIndex: number; + let dontShowIndex: number; + + // Check WinGet availability and version on Windows. + const isWindows = process.platform === "win32"; + let wingetVer: string | undefined; + let wingetInstalled = false; + if (isWindows) { + try { + const { execFile } = await import("node:child_process"); + await whenSome( + new Promise((resolve, reject) => { + execFile( + "winget", + ["show", "--id", "Microsoft.PowerShell", "-s", "winget", "--accept-source-agreements"], + (error: any, stdout: any) => error ? reject(error) : resolve(stdout), + ); + }).then(s => s.match(/Version:\s*([\d.]+)/)), + match => { + wingetVer = toTriple(match[1]); + wingetInstalled = true; + }, + ); + } catch { + // WinGet may not be installed — fall back to GitHub API. + try { + await whenSome( + fetchJSON>>( + "https://api.github.com/repos/microsoft/winget-pkgs/contents/manifests/m/Microsoft/PowerShell?per_page=100", + ), + entries => this.logger.writeDebug( + `WinGet repo latest: ${(wingetVer = entries + .filter(({ type }) => type === "dir") + .map(({ name }) => toTriple(name)) + .sort((a, b) => new SemVer(b).compare(a))[0]) ?? "not found"}`, + ), + ); + } catch { + // Best effort. + } + } + } + + const addButton = (title: string): number => { + const idx = options.length; + options.push({ id: idx, title }); + return idx; + }; + + // Show WinGet button: "Upgrade with WinGet" when useful, + // "Install WinGet" when not detected on Windows. + let wingetAction: "upgrade" | "install" | undefined; + if ( + wingetVer && + wingetInstalled && + new SemVer(wingetVer).compare(this.localVersion) > 0 + ) { + wingetAction = "upgrade"; + } else if (!wingetInstalled && isWindows) { + wingetAction = "install"; + } + if (wingetAction) + wingetIndex = addButton(wingetAction === "install" ? "Install WinGet" : "Upgrade with WinGet"); + if ( + wingetInstalled && + wingetVer && + new SemVer(wingetVer).compare(releaseVersion.version) < 0 + ) { + wingetStatusIndex = addButton("Check WinGet Status"); + } + + [browserIndex, notNowIndex, dontShowIndex] = + ["Open GitHub Release", "Not Now", "Don't Show Again"].map(addButton); + + // Build message with WinGet status when relevant. + let message = `PowerShell v${this.localVersion.version} is out-of-date. - The latest version is v${releaseVersion.version}. - Would you like to open the GitHub release in your browser?`, - ...UpdatePowerShell.promptOptions, + The latest version is v${releaseVersion.version}.`; + if (wingetInstalled) { + message += + new SemVer(wingetVer!).compare(this.localVersion) <= 0 + ? `\n(WinGet hasn't caught up yet — currently v${wingetVer}.)` + : new SemVer(wingetVer!).compare( + releaseVersion.version, + ) < 0 + ? `\n(WinGet currently has v${wingetVer}.)` + : ""; + } else if (isWindows) { + message += wingetVer + ? `\n(WinGet is not installed. It offers v${wingetVer}.)` + : `\n(WinGet, the Windows Package Manager, is not installed.)`; + } + message += `\nWould you like to upgrade?`; + + const result = await vscode.window.showInformationMessage( + message, + ...options, ); // If the user cancels the notification. @@ -211,19 +257,136 @@ export class UpdatePowerShell { } this.logger.writeDebug( - `User said '${UpdatePowerShell.promptOptions[result.id].title}'.`, + `User said '${options[result.id].title}'.`, ); switch (result.id) { - // Yes - case 0: + case wingetIndex: + if (wingetAction === "install") { + // From: https://aka.ms/winget-docs + this.logger.write("Installing WinGet and upgrading PowerShell..."); + vscode.window.createTerminal("Install WinGet & Upgrade PowerShell") + .sendText( + "$result = Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe -ErrorAction SilentlyContinue; if ($?) { winget update --id Microsoft.PowerShell -e -s winget } else { Write-Warning 'Failed to install WinGet. See https://aka.ms/winget-docs' }", + ); + } else { + this.logger.write("Upgrading PowerShell via WinGet..."); + vscode.window.createTerminal("PowerShell Upgrade (WinGet)") + .sendText("winget update --id Microsoft.PowerShell -e -s winget"); + } + break; + case wingetStatusIndex: { + // Find the open issue/PR mentioning the highest PowerShell version. + let statusUrl = + "https://github.com/microsoft/winget-pkgs/pulls?q=Microsoft.PowerShell+is:open"; + try { + const parsed = await Promise.all( + ( + (await fetchJSON<{ + items?: Array<{ + title: string; + html_url: string; + pull_request?: unknown; + }>; + }>( + "https://api.github.com/search/issues?q=Microsoft.PowerShell+repo:microsoft/winget-pkgs+is:open&sort=created&order=desc&per_page=30", + ))?.items ?? [] + ).map( + async ( + item, + ): Promise< + typeof item & { ver?: string } + > => { + const tm = item.title.match( + /(?:New version|Update|\[Update Request\]).*?(\d+\.\d+\.\d+)/i, + ); + if (tm) return { ...item, ver: tm[1] }; + // Try to extract version from the issue body. + try { + const bm = ( + await fetchJSON<{ + body?: string; + }>( + item.html_url.replace( + "https://github.com/", + "https://api.github.com/repos/", + ), + ) + )?.body?.match( + /Package Version.*?(\d+\.\d+\.\d+)/i, + ); + if (bm) { + return { ...item, ver: bm[1] }; + } + } catch { + // Best effort. + } + return item; + }, + ), + ); + + let bestPR: string | undefined; + let bestIssue: string | undefined; + let bestPRVer: string | undefined; + let bestIssueVer: string | undefined; + for (const { + ver, + html_url, + pull_request, + } of parsed) { + if (!ver) continue; + if (pull_request) { + if ( + !bestPRVer || + new SemVer(ver).compare(bestPRVer) > 0 + ) { + bestPRVer = ver; + bestPR = html_url; + } + } else { + if ( + !bestIssueVer || + new SemVer(ver).compare(bestIssueVer) > 0 + ) { + bestIssueVer = ver; + bestIssue = html_url; + } + } + } + // Prefer issue when linked to the PR for the same version. + const prVer = bestPRVer + ? new SemVer(bestPRVer) + : undefined; + const issueVer = bestIssueVer + ? new SemVer(bestIssueVer) + : undefined; + if ( + prVer && issueVer && + prVer.compare(issueVer) === 0 + ) { + statusUrl = bestIssue!; + } else if ( + prVer && + (!issueVer || prVer.compare(issueVer) > 0) + ) { + statusUrl = bestPR!; + } else if (issueVer) { + statusUrl = bestIssue!; + } + } catch { + // Fall back to generic search. + } + await vscode.env.openExternal(vscode.Uri.parse(statusUrl)); + break; + } + case browserIndex: await this.openReleaseInBrowser(tag); break; - // Not Now - case 1: + case notNowIndex: + // Do nothing. break; - // Don't Show Again - case 2: + case dontShowIndex: await changeSetting( "promptToUpdatePowerShell", false, From bd4ac33a02ffdb331e17c7ac1cbd8e2139607ecc Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Wed, 22 Jul 2026 02:19:25 +0800 Subject: [PATCH 02/14] =?UTF-8?q?fix:=20resolve=20ESLint=20errors=20?= =?UTF-8?q?=E2=80=94=20no-explicit-any,=20prefer-regexp-exec,=20array-type?= =?UTF-8?q?,=20no-confusing-void-expression?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/UpdatePowerShell.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index e5d9dfbc85..1d38cdce77 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -168,9 +168,9 @@ export class UpdatePowerShell { execFile( "winget", ["show", "--id", "Microsoft.PowerShell", "-s", "winget", "--accept-source-agreements"], - (error: any, stdout: any) => error ? reject(error) : resolve(stdout), + (error: unknown, stdout: unknown) => { error ? reject(error instanceof Error ? error : new Error(String(error))) : resolve(String(stdout)); }, ); - }).then(s => s.match(/Version:\s*([\d.]+)/)), + }).then(s => /Version:\s*([\d.]+)/.exec(s)), match => { wingetVer = toTriple(match[1]); wingetInstalled = true; @@ -180,15 +180,18 @@ export class UpdatePowerShell { // WinGet may not be installed — fall back to GitHub API. try { await whenSome( - fetchJSON>>( + fetchJSON[]>( "https://api.github.com/repos/microsoft/winget-pkgs/contents/manifests/m/Microsoft/PowerShell?per_page=100", ), - entries => this.logger.writeDebug( - `WinGet repo latest: ${(wingetVer = entries + entries => { + wingetVer = entries .filter(({ type }) => type === "dir") .map(({ name }) => toTriple(name)) - .sort((a, b) => new SemVer(b).compare(a))[0]) ?? "not found"}`, - ), + .sort((a, b) => new SemVer(b).compare(a))[0]; + this.logger.writeDebug( + `WinGet repo latest: ${wingetVer ?? "not found"}`, + ); + }, ); } catch { // Best effort. From d54817fa3f80522cbade8dc73542c9b8200a9ceb Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Wed, 22 Jul 2026 02:27:52 +0800 Subject: [PATCH 03/14] fix: syntax error in array-type conversion --- src/features/UpdatePowerShell.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index 1d38cdce77..766993d610 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -152,9 +152,6 @@ export class UpdatePowerShell { const options: IUpdateMessageItem[] = []; let wingetIndex = -1; let wingetStatusIndex = -1; - let browserIndex: number; - let notNowIndex: number; - let dontShowIndex: number; // Check WinGet availability and version on Windows. const isWindows = process.platform === "win32"; @@ -168,7 +165,13 @@ export class UpdatePowerShell { execFile( "winget", ["show", "--id", "Microsoft.PowerShell", "-s", "winget", "--accept-source-agreements"], - (error: unknown, stdout: unknown) => { error ? reject(error instanceof Error ? error : new Error(String(error))) : resolve(String(stdout)); }, + (error: unknown, stdout: unknown) => { + if (error) { + reject(error instanceof Error ? error : new Error(String(error))); + } else { + resolve(String(stdout)); + } + }, ); }).then(s => /Version:\s*([\d.]+)/.exec(s)), match => { @@ -189,7 +192,7 @@ export class UpdatePowerShell { .map(({ name }) => toTriple(name)) .sort((a, b) => new SemVer(b).compare(a))[0]; this.logger.writeDebug( - `WinGet repo latest: ${wingetVer ?? "not found"}`, + `WinGet repo latest: ${wingetVer || "not found"}`, ); }, ); @@ -227,7 +230,7 @@ export class UpdatePowerShell { wingetStatusIndex = addButton("Check WinGet Status"); } - [browserIndex, notNowIndex, dontShowIndex] = + const [browserIndex, notNowIndex, dontShowIndex] = ["Open GitHub Release", "Not Now", "Don't Show Again"].map(addButton); // Build message with WinGet status when relevant. @@ -288,11 +291,11 @@ export class UpdatePowerShell { const parsed = await Promise.all( ( (await fetchJSON<{ - items?: Array<{ + items?: { title: string; html_url: string; pull_request?: unknown; - }>; + }[]; }>( "https://api.github.com/search/issues?q=Microsoft.PowerShell+repo:microsoft/winget-pkgs+is:open&sort=created&order=desc&per_page=30", ))?.items ?? [] @@ -302,9 +305,7 @@ export class UpdatePowerShell { ): Promise< typeof item & { ver?: string } > => { - const tm = item.title.match( - /(?:New version|Update|\[Update Request\]).*?(\d+\.\d+\.\d+)/i, - ); + const tm = /(?:New version|Update|\[Update Request\]).*?(\d+\.\d+\.\d+)/i.exec(item.title); if (tm) return { ...item, ver: tm[1] }; // Try to extract version from the issue body. try { From 07141b9d9086ff2f4d6783ab6918bb196711aee1 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Wed, 22 Jul 2026 02:36:15 +0800 Subject: [PATCH 04/14] =?UTF-8?q?fix:=20remaining=20ESLint=20=E2=80=94=20n?= =?UTF-8?q?o-base-to-string,=20no-unnecessary-condition?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/UpdatePowerShell.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index 766993d610..4f0edb8ca1 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -167,7 +167,7 @@ export class UpdatePowerShell { ["show", "--id", "Microsoft.PowerShell", "-s", "winget", "--accept-source-agreements"], (error: unknown, stdout: unknown) => { if (error) { - reject(error instanceof Error ? error : new Error(String(error))); + reject(error instanceof Error ? error : new Error(typeof error === "string" ? error : "unknown")); } else { resolve(String(stdout)); } @@ -220,8 +220,9 @@ export class UpdatePowerShell { } else if (!wingetInstalled && isWindows) { wingetAction = "install"; } - if (wingetAction) - wingetIndex = addButton(wingetAction === "install" ? "Install WinGet" : "Upgrade with WinGet"); + // Inside if (isWindows), wingetAction is always set. + wingetIndex = addButton(wingetAction === "install" ? "Install WinGet" : "Upgrade with WinGet"); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if ( wingetInstalled && wingetVer && @@ -237,6 +238,7 @@ export class UpdatePowerShell { let message = `PowerShell v${this.localVersion.version} is out-of-date. The latest version is v${releaseVersion.version}.`; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (wingetInstalled) { message += new SemVer(wingetVer!).compare(this.localVersion) <= 0 @@ -246,6 +248,7 @@ export class UpdatePowerShell { ) < 0 ? `\n(WinGet currently has v${wingetVer}.)` : ""; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition } else if (isWindows) { message += wingetVer ? `\n(WinGet is not installed. It offers v${wingetVer}.)` From bc83be3ac6f5d6e52ad7cce681ec1487145e2754 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Wed, 22 Jul 2026 02:41:07 +0800 Subject: [PATCH 05/14] fix: no-useless-assignment, move eslint-disable to correct lines --- src/features/UpdatePowerShell.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index 4f0edb8ca1..30023d2e1e 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -150,7 +150,7 @@ export class UpdatePowerShell { // Dynamically build prompt options: add WinGet button if it has this version. const options: IUpdateMessageItem[] = []; - let wingetIndex = -1; + let wingetIndex: number; let wingetStatusIndex = -1; // Check WinGet availability and version on Windows. @@ -222,8 +222,8 @@ export class UpdatePowerShell { } // Inside if (isWindows), wingetAction is always set. wingetIndex = addButton(wingetAction === "install" ? "Install WinGet" : "Upgrade with WinGet"); - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if ( + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition wingetInstalled && wingetVer && new SemVer(wingetVer).compare(releaseVersion.version) < 0 @@ -238,7 +238,7 @@ export class UpdatePowerShell { let message = `PowerShell v${this.localVersion.version} is out-of-date. The latest version is v${releaseVersion.version}.`; - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- wingetInstalled modified in callback if (wingetInstalled) { message += new SemVer(wingetVer!).compare(this.localVersion) <= 0 @@ -248,7 +248,7 @@ export class UpdatePowerShell { ) < 0 ? `\n(WinGet currently has v${wingetVer}.)` : ""; - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- isWindows always true here } else if (isWindows) { message += wingetVer ? `\n(WinGet is not installed. It offers v${wingetVer}.)` From 4bfaccbfa31f01896beea9ed20b65eb8f4c91ba3 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Wed, 22 Jul 2026 02:51:56 +0800 Subject: [PATCH 06/14] fix: use block-level eslint-disable for no-unnecessary-condition --- src/features/UpdatePowerShell.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index 30023d2e1e..3e90648304 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -150,7 +150,7 @@ export class UpdatePowerShell { // Dynamically build prompt options: add WinGet button if it has this version. const options: IUpdateMessageItem[] = []; - let wingetIndex: number; + let wingetIndex = -1; let wingetStatusIndex = -1; // Check WinGet availability and version on Windows. @@ -220,10 +220,10 @@ export class UpdatePowerShell { } else if (!wingetInstalled && isWindows) { wingetAction = "install"; } - // Inside if (isWindows), wingetAction is always set. + // eslint-disable-next-line prefer-const wingetIndex = addButton(wingetAction === "install" ? "Install WinGet" : "Upgrade with WinGet"); + /* eslint-disable @typescript-eslint/no-unnecessary-condition */ if ( - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition wingetInstalled && wingetVer && new SemVer(wingetVer).compare(releaseVersion.version) < 0 @@ -238,7 +238,7 @@ export class UpdatePowerShell { let message = `PowerShell v${this.localVersion.version} is out-of-date. The latest version is v${releaseVersion.version}.`; - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- wingetInstalled modified in callback + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- wingetInstalled set in callback if (wingetInstalled) { message += new SemVer(wingetVer!).compare(this.localVersion) <= 0 @@ -253,6 +253,7 @@ export class UpdatePowerShell { message += wingetVer ? `\n(WinGet is not installed. It offers v${wingetVer}.)` : `\n(WinGet, the Windows Package Manager, is not installed.)`; + /* eslint-enable @typescript-eslint/no-unnecessary-condition */ } message += `\nWould you like to upgrade?`; From a8938ae56800c7f61464c624389a7e58388b483f Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Wed, 22 Jul 2026 02:57:24 +0800 Subject: [PATCH 07/14] fix: move eslint-disable to cover first winget if-block, add no-useless-assignment --- src/features/UpdatePowerShell.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index 3e90648304..e5fb64e9ea 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -150,6 +150,7 @@ export class UpdatePowerShell { // Dynamically build prompt options: add WinGet button if it has this version. const options: IUpdateMessageItem[] = []; + // eslint-disable-next-line no-useless-assignment let wingetIndex = -1; let wingetStatusIndex = -1; @@ -211,6 +212,7 @@ export class UpdatePowerShell { // Show WinGet button: "Upgrade with WinGet" when useful, // "Install WinGet" when not detected on Windows. let wingetAction: "upgrade" | "install" | undefined; + /* eslint-disable @typescript-eslint/no-unnecessary-condition */ if ( wingetVer && wingetInstalled && @@ -222,7 +224,6 @@ export class UpdatePowerShell { } // eslint-disable-next-line prefer-const wingetIndex = addButton(wingetAction === "install" ? "Install WinGet" : "Upgrade with WinGet"); - /* eslint-disable @typescript-eslint/no-unnecessary-condition */ if ( wingetInstalled && wingetVer && From a08617095d5b85eba24375d521d334d57359fe25 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Wed, 22 Jul 2026 03:01:20 +0800 Subject: [PATCH 08/14] fix: Prettier formatting + remove unused eslint-disable comments --- src/features/UpdatePowerShell.ts | 154 ++++++++++++++++++------------- 1 file changed, 92 insertions(+), 62 deletions(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index e5fb64e9ea..a154ab394e 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -64,7 +64,9 @@ export class UpdatePowerShell { // Respect environment configuration. if (process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "off") - return this.skip("Environment variable 'POWERSHELL_UPDATECHECK' was 'Off'."); + return this.skip( + "Environment variable 'POWERSHELL_UPDATECHECK' was 'Off'.", + ); // Skip prompting when using Windows PowerShell for now. if (this.localVersion.compare("6.0.0") === -1) @@ -81,7 +83,12 @@ export class UpdatePowerShell { return this.skip("Not prompting to update development build."); // Skip if preview is a daily build. - if (this.localVersion.prerelease[0].toString().toLowerCase().startsWith("daily")) + if ( + this.localVersion.prerelease[0] + .toString() + .toLowerCase() + .startsWith("daily") + ) return this.skip("Not prompting to update daily build."); } @@ -107,14 +114,19 @@ export class UpdatePowerShell { } this.logger.writeDebug("Checking for PowerShell update..."); - const suffixes = process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "lts" - ? ["lts"] - : this.localVersion.prerelease.length > 0 - ? ["stable", "preview"] - : ["stable"]; - this.logger.writeDebug(`Checking for ${suffixes.join(" and ")} update...`); + const suffixes = + process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "lts" + ? ["lts"] + : this.localVersion.prerelease.length > 0 + ? ["stable", "preview"] + : ["stable"]; + this.logger.writeDebug( + `Checking for ${suffixes.join(" and ")} update...`, + ); for (const tag of await Promise.all( - suffixes.map(s => this.getRemoteVersion(`https://aka.ms/pwsh-buildinfo-${s}`)), + suffixes.map((s) => + this.getRemoteVersion(`https://aka.ms/pwsh-buildinfo-${s}`), + ), )) { if (tag != undefined && this.localVersion.compare(tag) === -1) { return tag; @@ -127,7 +139,9 @@ export class UpdatePowerShell { public async checkForUpdate(): Promise { try { - await whenSome(this.maybeGetNewRelease(), tag => this.promptToUpdate(tag)); + await whenSome(this.maybeGetNewRelease(), (tag) => + this.promptToUpdate(tag), + ); } catch (err) { // Best effort. This probably failed to fetch the data from GitHub. this.logger.writeWarning( @@ -138,7 +152,9 @@ export class UpdatePowerShell { private async openReleaseInBrowser(tag: string): Promise { await vscode.env.openExternal( - vscode.Uri.parse(`https://github.com/PowerShell/PowerShell/releases/tag/${tag}`), + vscode.Uri.parse( + `https://github.com/PowerShell/PowerShell/releases/tag/${tag}`, + ), ); } @@ -165,17 +181,32 @@ export class UpdatePowerShell { new Promise((resolve, reject) => { execFile( "winget", - ["show", "--id", "Microsoft.PowerShell", "-s", "winget", "--accept-source-agreements"], + [ + "show", + "--id", + "Microsoft.PowerShell", + "-s", + "winget", + "--accept-source-agreements", + ], (error: unknown, stdout: unknown) => { if (error) { - reject(error instanceof Error ? error : new Error(typeof error === "string" ? error : "unknown")); + reject( + error instanceof Error + ? error + : new Error( + typeof error === "string" + ? error + : "unknown", + ), + ); } else { resolve(String(stdout)); } }, ); - }).then(s => /Version:\s*([\d.]+)/.exec(s)), - match => { + }).then((s) => /Version:\s*([\d.]+)/.exec(s)), + (match) => { wingetVer = toTriple(match[1]); wingetInstalled = true; }, @@ -187,7 +218,7 @@ export class UpdatePowerShell { fetchJSON[]>( "https://api.github.com/repos/microsoft/winget-pkgs/contents/manifests/m/Microsoft/PowerShell?per_page=100", ), - entries => { + (entries) => { wingetVer = entries .filter(({ type }) => type === "dir") .map(({ name }) => toTriple(name)) @@ -222,8 +253,11 @@ export class UpdatePowerShell { } else if (!wingetInstalled && isWindows) { wingetAction = "install"; } - // eslint-disable-next-line prefer-const - wingetIndex = addButton(wingetAction === "install" ? "Install WinGet" : "Upgrade with WinGet"); + wingetIndex = addButton( + wingetAction === "install" + ? "Install WinGet" + : "Upgrade with WinGet", + ); if ( wingetInstalled && wingetVer && @@ -232,29 +266,27 @@ export class UpdatePowerShell { wingetStatusIndex = addButton("Check WinGet Status"); } - const [browserIndex, notNowIndex, dontShowIndex] = - ["Open GitHub Release", "Not Now", "Don't Show Again"].map(addButton); + const [browserIndex, notNowIndex, dontShowIndex] = [ + "Open GitHub Release", + "Not Now", + "Don't Show Again", + ].map(addButton); // Build message with WinGet status when relevant. - let message = - `PowerShell v${this.localVersion.version} is out-of-date. + let message = `PowerShell v${this.localVersion.version} is out-of-date. The latest version is v${releaseVersion.version}.`; - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- wingetInstalled set in callback if (wingetInstalled) { message += new SemVer(wingetVer!).compare(this.localVersion) <= 0 ? `\n(WinGet hasn't caught up yet — currently v${wingetVer}.)` - : new SemVer(wingetVer!).compare( - releaseVersion.version, - ) < 0 - ? `\n(WinGet currently has v${wingetVer}.)` - : ""; - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- isWindows always true here + : new SemVer(wingetVer!).compare(releaseVersion.version) < 0 + ? `\n(WinGet currently has v${wingetVer}.)` + : ""; } else if (isWindows) { message += wingetVer ? `\n(WinGet is not installed. It offers v${wingetVer}.)` : `\n(WinGet, the Windows Package Manager, is not installed.)`; - /* eslint-enable @typescript-eslint/no-unnecessary-condition */ + /* eslint-enable @typescript-eslint/no-unnecessary-condition */ } message += `\nWould you like to upgrade?`; @@ -269,23 +301,27 @@ export class UpdatePowerShell { return; } - this.logger.writeDebug( - `User said '${options[result.id].title}'.`, - ); + this.logger.writeDebug(`User said '${options[result.id].title}'.`); switch (result.id) { case wingetIndex: if (wingetAction === "install") { // From: https://aka.ms/winget-docs - this.logger.write("Installing WinGet and upgrading PowerShell..."); - vscode.window.createTerminal("Install WinGet & Upgrade PowerShell") + this.logger.write( + "Installing WinGet and upgrading PowerShell...", + ); + vscode.window + .createTerminal("Install WinGet & Upgrade PowerShell") .sendText( "$result = Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe -ErrorAction SilentlyContinue; if ($?) { winget update --id Microsoft.PowerShell -e -s winget } else { Write-Warning 'Failed to install WinGet. See https://aka.ms/winget-docs' }", ); } else { this.logger.write("Upgrading PowerShell via WinGet..."); - vscode.window.createTerminal("PowerShell Upgrade (WinGet)") - .sendText("winget update --id Microsoft.PowerShell -e -s winget"); + vscode.window + .createTerminal("PowerShell Upgrade (WinGet)") + .sendText( + "winget update --id Microsoft.PowerShell -e -s winget", + ); } break; case wingetStatusIndex: { @@ -295,22 +331,25 @@ export class UpdatePowerShell { try { const parsed = await Promise.all( ( - (await fetchJSON<{ - items?: { - title: string; - html_url: string; - pull_request?: unknown; - }[]; - }>( - "https://api.github.com/search/issues?q=Microsoft.PowerShell+repo:microsoft/winget-pkgs+is:open&sort=created&order=desc&per_page=30", - ))?.items ?? [] + ( + await fetchJSON<{ + items?: { + title: string; + html_url: string; + pull_request?: unknown; + }[]; + }>( + "https://api.github.com/search/issues?q=Microsoft.PowerShell+repo:microsoft/winget-pkgs+is:open&sort=created&order=desc&per_page=30", + ) + )?.items ?? [] ).map( async ( item, - ): Promise< - typeof item & { ver?: string } - > => { - const tm = /(?:New version|Update|\[Update Request\]).*?(\d+\.\d+\.\d+)/i.exec(item.title); + ): Promise => { + const tm = + /(?:New version|Update|\[Update Request\]).*?(\d+\.\d+\.\d+)/i.exec( + item.title, + ); if (tm) return { ...item, ver: tm[1] }; // Try to extract version from the issue body. try { @@ -341,11 +380,7 @@ export class UpdatePowerShell { let bestIssue: string | undefined; let bestPRVer: string | undefined; let bestIssueVer: string | undefined; - for (const { - ver, - html_url, - pull_request, - } of parsed) { + for (const { ver, html_url, pull_request } of parsed) { if (!ver) continue; if (pull_request) { if ( @@ -366,16 +401,11 @@ export class UpdatePowerShell { } } // Prefer issue when linked to the PR for the same version. - const prVer = bestPRVer - ? new SemVer(bestPRVer) - : undefined; + const prVer = bestPRVer ? new SemVer(bestPRVer) : undefined; const issueVer = bestIssueVer ? new SemVer(bestIssueVer) : undefined; - if ( - prVer && issueVer && - prVer.compare(issueVer) === 0 - ) { + if (prVer && issueVer && prVer.compare(issueVer) === 0) { statusUrl = bestIssue!; } else if ( prVer && From 7acd42f57b7eca013512da1e3d3467e82ec86547 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Wed, 22 Jul 2026 03:37:43 +0800 Subject: [PATCH 09/14] =?UTF-8?q?refactor:=20rename=20wingetStatusIndex=20?= =?UTF-8?q?=E2=86=92=20wingetProgressIndex,=20button=20=E2=86=92=20View=20?= =?UTF-8?q?WinGet=20Progress?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/UpdatePowerShell.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index a154ab394e..21a31c74df 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -168,7 +168,7 @@ export class UpdatePowerShell { const options: IUpdateMessageItem[] = []; // eslint-disable-next-line no-useless-assignment let wingetIndex = -1; - let wingetStatusIndex = -1; + let wingetProgressIndex = -1; // Check WinGet availability and version on Windows. const isWindows = process.platform === "win32"; @@ -263,7 +263,7 @@ export class UpdatePowerShell { wingetVer && new SemVer(wingetVer).compare(releaseVersion.version) < 0 ) { - wingetStatusIndex = addButton("Check WinGet Status"); + wingetProgressIndex = addButton("View WinGet Progress"); } const [browserIndex, notNowIndex, dontShowIndex] = [ @@ -324,7 +324,7 @@ export class UpdatePowerShell { ); } break; - case wingetStatusIndex: { + case wingetProgressIndex: { // Find the open issue/PR mentioning the highest PowerShell version. let statusUrl = "https://github.com/microsoft/winget-pkgs/pulls?q=Microsoft.PowerShell+is:open"; From 8d7c0d4344059b8f1dcff7836f2d2956d3eb9ec3 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Wed, 22 Jul 2026 16:01:11 +0800 Subject: [PATCH 10/14] fix: proper fix for wingetIndex useless assignment (remove eslint-disable) --- src/features/UpdatePowerShell.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index 21a31c74df..6f2cd42007 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -166,8 +166,7 @@ export class UpdatePowerShell { // Dynamically build prompt options: add WinGet button if it has this version. const options: IUpdateMessageItem[] = []; - // eslint-disable-next-line no-useless-assignment - let wingetIndex = -1; + let wingetIndex: number; let wingetProgressIndex = -1; // Check WinGet availability and version on Windows. From d015f06c2ab826adab15758613194d3e418873bf Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Wed, 22 Jul 2026 16:22:23 +0800 Subject: [PATCH 11/14] fix: use const for wingetIndex (single assignment) --- src/features/UpdatePowerShell.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index 6f2cd42007..35d818f8e8 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -166,7 +166,6 @@ export class UpdatePowerShell { // Dynamically build prompt options: add WinGet button if it has this version. const options: IUpdateMessageItem[] = []; - let wingetIndex: number; let wingetProgressIndex = -1; // Check WinGet availability and version on Windows. @@ -252,7 +251,7 @@ export class UpdatePowerShell { } else if (!wingetInstalled && isWindows) { wingetAction = "install"; } - wingetIndex = addButton( + const wingetIndex = addButton( wingetAction === "install" ? "Install WinGet" : "Upgrade with WinGet", From c558f0d3daaac9c9597572c75ae3218c67a59a09 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Wed, 22 Jul 2026 16:38:35 +0800 Subject: [PATCH 12/14] Fix Prettier formatting in UpdatePowerShell.ts Adjust indentation of nested ternary operators to match Prettier config. --- src/features/UpdatePowerShell.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index 35d818f8e8..7e5596b6c9 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -118,8 +118,8 @@ export class UpdatePowerShell { process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "lts" ? ["lts"] : this.localVersion.prerelease.length > 0 - ? ["stable", "preview"] - : ["stable"]; + ? ["stable", "preview"] + : ["stable"]; this.logger.writeDebug( `Checking for ${suffixes.join(" and ")} update...`, ); @@ -193,10 +193,10 @@ export class UpdatePowerShell { error instanceof Error ? error : new Error( - typeof error === "string" - ? error - : "unknown", - ), + typeof error === "string" + ? error + : "unknown", + ), ); } else { resolve(String(stdout)); @@ -278,8 +278,8 @@ export class UpdatePowerShell { new SemVer(wingetVer!).compare(this.localVersion) <= 0 ? `\n(WinGet hasn't caught up yet — currently v${wingetVer}.)` : new SemVer(wingetVer!).compare(releaseVersion.version) < 0 - ? `\n(WinGet currently has v${wingetVer}.)` - : ""; + ? `\n(WinGet currently has v${wingetVer}.)` + : ""; } else if (isWindows) { message += wingetVer ? `\n(WinGet is not installed. It offers v${wingetVer}.)` From 2afebf92abfd9ee8a54bd64128de6c8173fe8551 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Thu, 23 Jul 2026 17:57:20 +0800 Subject: [PATCH 13/14] style: fix Prettier formatting --- src/features/UpdatePowerShell.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts index 7e5596b6c9..35d818f8e8 100644 --- a/src/features/UpdatePowerShell.ts +++ b/src/features/UpdatePowerShell.ts @@ -118,8 +118,8 @@ export class UpdatePowerShell { process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "lts" ? ["lts"] : this.localVersion.prerelease.length > 0 - ? ["stable", "preview"] - : ["stable"]; + ? ["stable", "preview"] + : ["stable"]; this.logger.writeDebug( `Checking for ${suffixes.join(" and ")} update...`, ); @@ -193,10 +193,10 @@ export class UpdatePowerShell { error instanceof Error ? error : new Error( - typeof error === "string" - ? error - : "unknown", - ), + typeof error === "string" + ? error + : "unknown", + ), ); } else { resolve(String(stdout)); @@ -278,8 +278,8 @@ export class UpdatePowerShell { new SemVer(wingetVer!).compare(this.localVersion) <= 0 ? `\n(WinGet hasn't caught up yet — currently v${wingetVer}.)` : new SemVer(wingetVer!).compare(releaseVersion.version) < 0 - ? `\n(WinGet currently has v${wingetVer}.)` - : ""; + ? `\n(WinGet currently has v${wingetVer}.)` + : ""; } else if (isWindows) { message += wingetVer ? `\n(WinGet is not installed. It offers v${wingetVer}.)` From ff9fa3eb6dc76b33f58770e01ce017104ff19127 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Thu, 23 Jul 2026 18:26:08 +0800 Subject: [PATCH 14/14] chore: add .vscode/settings.json with Prettier format-on-save --- .vscode/settings.json | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..c2f8f1e492 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,23 @@ +{ + // Format on save with Prettier + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.formatOnSaveMode": "file", + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit" + }, + + // Prettier settings matching project config + "prettier.requireConfig": true, + "prettier.useEditorConfig": false, + + // ESLint - check on save when available + "eslint.format.enable": false, + "eslint.validate": ["typescript"], + + // JavaScript / TypeScript + "javascript.format.enabled": false, + "javascript.validate.enabled": true, + "typescript.format.enabled": false, + "typescript.validate.enabled": true +}