From 9a97e3877f36679830e302f788ffe42c43933f1b Mon Sep 17 00:00:00 2001 From: Vilius Vystartas Date: Fri, 10 Jul 2026 22:33:24 +0100 Subject: [PATCH 1/4] fix(list-templates): treat --spfx-version as output filter instead of branch selector The --spfx-version option was previously used only for branch selection in the template repository, causing errors when the corresponding branch didn't exist. Users naturally expect it to filter the listed templates by SPFx version. - After fetching all templates, filter by spfxVersion field when --spfx-version is provided (using startsWith so '1.22' matches '1.22.0' and '1.22.1') - Show a helpful message when no templates match, suggesting the user run without --spfx-version to see all available versions - Update documentation to describe the filter behavior Fixes #236 --- .../src/cli/actions/ListTemplatesAction.ts | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts b/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts index b2b9308b..7de9d409 100644 --- a/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts +++ b/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts @@ -14,7 +14,8 @@ export class ListTemplatesAction extends SPFxActionBase { summary: 'Lists available SPFx templates from configured sources', documentation: 'This command lists all available templates from the default GitHub source ' + - 'and any additional sources specified with --local-source or --remote-source.' + 'and any additional sources specified with --local-source or --remote-source. ' + + 'Use --spfx-version to filter templates by version (e.g., "--spfx-version 1.22").' }, terminal ); @@ -37,8 +38,26 @@ export class ListTemplatesAction extends SPFxActionBase { const templates: SPFxTemplateCollection = await this._fetchTemplatesAsync(manager); - const formattedTable: string = await templates.toFormattedStringAsync(); - terminal.writeLine(formattedTable); + // Apply --spfx-version filter if provided (user expects filter, not just branch selection) + const spfxVersion: string | undefined = this._spfxVersionParameter.value?.trim(); + if (spfxVersion) { + const filteredTemplates = [...templates.values()].filter( + (t) => t.spfxVersion && t.spfxVersion.startsWith(spfxVersion) + ); + if (filteredTemplates.length === 0) { + terminal.writeLine( + `No templates found for SPFx version "${spfxVersion}". ` + + `Use "spfx list-templates" (without --spfx-version) to see all available versions.` + ); + return; + } + const displayCollection: SPFxTemplateCollection = new SPFxTemplateCollection(filteredTemplates); + const formattedTable: string = await displayCollection.toFormattedStringAsync(); + terminal.writeLine(formattedTable); + } else { + const formattedTable: string = await templates.toFormattedStringAsync(); + terminal.writeLine(formattedTable); + } } catch (error: unknown) { const message: string = error instanceof Error ? error.message : String(error); terminal.writeErrorLine(`Error listing templates: ${message}`); From ab63fb9cf6a3329c8f37bdc8b95e624f8d8bfae3 Mon Sep 17 00:00:00 2001 From: Vilius Vystartas Date: Sat, 11 Jul 2026 22:19:07 +0100 Subject: [PATCH 2/4] fix: normalize version matching in --spfx-version filter - Split version string to prevent '1.2' matching '1.20.0' - Handle 'version/1.22' prefix and '-rc.X' suffix normalization - Update parameter description to reflect filter behavior --- apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts | 10 ++++++++-- apps/spfx-cli/src/cli/actions/SPFxActionBase.ts | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts b/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts index 7de9d409..52ca907e 100644 --- a/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts +++ b/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts @@ -40,9 +40,15 @@ export class ListTemplatesAction extends SPFxActionBase { // Apply --spfx-version filter if provided (user expects filter, not just branch selection) const spfxVersion: string | undefined = this._spfxVersionParameter.value?.trim(); - if (spfxVersion) { + // Normalize version prefix: "version/1.22" -> "1.22", "1.22-rc.0" -> "1.22" + const normalizedVersion: string | undefined = spfxVersion + ? spfxVersion.replace(/^version\//, '').replace(/-.*$/, '') + : undefined; + if (normalizedVersion) { + // Split into parts and compare major.minor so "1.2" doesn't match "1.20.0" + const versionParts: string[] = normalizedVersion.split('.'); const filteredTemplates = [...templates.values()].filter( - (t) => t.spfxVersion && t.spfxVersion.startsWith(spfxVersion) + (t) => t.spfxVersion && t.spfxVersion.split('.').slice(0, versionParts.length).join('.') === normalizedVersion ); if (filteredTemplates.length === 0) { terminal.writeLine( diff --git a/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts b/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts index d6ca0250..701296f3 100644 --- a/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts +++ b/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts @@ -52,7 +52,7 @@ export abstract class SPFxActionBase extends CommandLineAction { parameterLongName: '--spfx-version', argumentName: 'VERSION', description: - 'The SPFx version to use (e.g., "1.22", "1.23-rc.0"). Resolves to the "version/" branch ' + + 'The SPFx version to filter by (e.g., "1.22"). Also selects a corresponding "version/" branch ' + 'in the template repository. Defaults to the "version/latest" branch.' }); From e3b63a3a17c906a06a2a0b8bf6064204a90e0b44 Mon Sep 17 00:00:00 2001 From: Vilius Vystartas Date: Mon, 13 Jul 2026 15:31:38 +0100 Subject: [PATCH 3/4] fix: change SPFxTemplateCollection from type-only to value import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The --spfx-version filter uses SPFxTemplateCollection as a constructor (new SPFxTemplateCollection()), which requires a value import — a type-only import won't compile with noImplicitOverride enabled. --- apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts b/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts index 52ca907e..65c6a74f 100644 --- a/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts +++ b/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts @@ -2,7 +2,7 @@ // See LICENSE in the project root for license information. import type { Terminal } from '@rushstack/terminal'; -import { type SPFxTemplateCollection, SPFxTemplateRepositoryManager } from '@microsoft/spfx-template-api'; +import { SPFxTemplateCollection, SPFxTemplateRepositoryManager } from '@microsoft/spfx-template-api'; import { SPFxActionBase } from './SPFxActionBase'; From 769d322a6826da6c32db87de2f30d6160121f6ca Mon Sep 17 00:00:00 2001 From: Vilius Vystartas Date: Mon, 13 Jul 2026 15:31:46 +0100 Subject: [PATCH 4/4] chore: add change file for --spfx-version filter --- .../spfx-cli/spfx-version-filter_2026-07-13.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 common/changes/@microsoft/spfx-cli/spfx-version-filter_2026-07-13.json diff --git a/common/changes/@microsoft/spfx-cli/spfx-version-filter_2026-07-13.json b/common/changes/@microsoft/spfx-cli/spfx-version-filter_2026-07-13.json new file mode 100644 index 00000000..a0a328ef --- /dev/null +++ b/common/changes/@microsoft/spfx-cli/spfx-version-filter_2026-07-13.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/spfx-cli", + "comment": "", + "type": "none" + } + ], + "packageName": "@microsoft/spfx-cli" +}