diff --git a/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts b/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts index b2b9308b..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'; @@ -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,32 @@ 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(); + // 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.split('.').slice(0, versionParts.length).join('.') === normalizedVersion + ); + 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}`); 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.' }); 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" +}