From 794ab3f2231d158260ed552a657f7223317a1294 Mon Sep 17 00:00:00 2001 From: Nick Pape Date: Tue, 24 Mar 2026 13:53:07 -0500 Subject: [PATCH 1/4] Add --remote-source flag to create command (closes #90) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a repeatable --remote-source URL flag to the create command, letting users point at custom public GitHub repos containing SPFx templates. Remote sources are additive — they work alongside both the default GitHub source and --local-template sources. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- apps/spfx-cli/README.md | 11 ++++ apps/spfx-cli/src/cli/actions/CreateAction.ts | 18 ++++++ .../cli/actions/tests/CreateAction.test.ts | 59 +++++++++++++++++++ .../__snapshots__/CreateAction.test.ts.snap | 49 +++++++++++++++ .../CommandLineHelp.test.ts.snap | 6 +- .../spfx-cli/remote-source_2026-03-24.json | 10 ++++ 6 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 common/changes/@microsoft/spfx-cli/remote-source_2026-03-24.json diff --git a/apps/spfx-cli/README.md b/apps/spfx-cli/README.md index 7220d039..12f26a14 100644 --- a/apps/spfx-cli/README.md +++ b/apps/spfx-cli/README.md @@ -48,6 +48,7 @@ Scaffolds a new SPFx component. Templates are pulled from the [SharePoint/spfx]( | `--spfx-version VERSION` | repo default branch | SPFx version to use; resolves to the `version/` branch (e.g. `1.22`, `1.23-rc.0`) | | `--template-url URL` | `https://github.com/SharePoint/spfx` | Custom GitHub template repository | | `--local-template PATH` | — | Path to a local template folder (repeatable; bypasses GitHub) | +| `--remote-source URL` | — | Public GitHub repo to include as an additional template source (repeatable) | ### Environment variables @@ -133,6 +134,16 @@ spfx create \ --local-template ./path/to/templates ``` +Use templates from a custom GitHub repository: + +```bash +spfx create \ + --template my-custom-template \ + --library-name my-spfx-library \ + --component-name "My Web Part" \ + --remote-source https://github.com/my-org/my-templates +``` + --- ## License diff --git a/apps/spfx-cli/src/cli/actions/CreateAction.ts b/apps/spfx-cli/src/cli/actions/CreateAction.ts index 5d650765..c5bd008b 100644 --- a/apps/spfx-cli/src/cli/actions/CreateAction.ts +++ b/apps/spfx-cli/src/cli/actions/CreateAction.ts @@ -56,6 +56,7 @@ export class CreateAction extends CommandLineAction { private readonly _targetDirParameter: IRequiredCommandLineStringParameter; private readonly _templateParameter: IRequiredCommandLineStringParameter; private readonly _localTemplateSourcesParameter: CommandLineStringListParameter; + private readonly _remoteSourcesParameter: CommandLineStringListParameter; private readonly _libraryNameParameter: IRequiredCommandLineStringParameter; private readonly _componentNameParameter: IRequiredCommandLineStringParameter; private readonly _componentAliasParameter: CommandLineStringParameter; @@ -87,6 +88,12 @@ export class CreateAction extends CommandLineAction { description: 'Path to a local template folder' }); + this._remoteSourcesParameter = this.defineStringListParameter({ + parameterLongName: '--remote-source', + argumentName: 'URL', + description: 'Public GitHub repository URL to use as an additional template source (repeatable)' + }); + this._templateParameter = this.defineStringParameter({ parameterLongName: '--template', argumentName: 'TEMPLATE_NAME', @@ -207,6 +214,17 @@ export class CreateAction extends CommandLineAction { manager.addSource(new PublicGitHubRepositorySource(repoUrl, ref, this._terminal)); } + // Always process --remote-source URLs (additive with either local or default sources) + for (const remoteUrl of this._remoteSourcesParameter.values) { + const { repoUrl: additionalRepoUrl, urlBranch: additionalUrlBranch } = + parseGitHubUrlAndRef(remoteUrl); + terminal.writeLine( + `Adding remote template source: ${additionalRepoUrl}` + + `${additionalUrlBranch ? ` (branch: ${additionalUrlBranch})` : ''}` + ); + manager.addSource(new PublicGitHubRepositorySource(additionalRepoUrl, additionalUrlBranch, terminal)); + } + let templates: SPFxTemplateCollection; try { templates = await manager.getTemplatesAsync(); diff --git a/apps/spfx-cli/src/cli/actions/tests/CreateAction.test.ts b/apps/spfx-cli/src/cli/actions/tests/CreateAction.test.ts index 87844c7e..0c439a2f 100644 --- a/apps/spfx-cli/src/cli/actions/tests/CreateAction.test.ts +++ b/apps/spfx-cli/src/cli/actions/tests/CreateAction.test.ts @@ -167,6 +167,65 @@ describe('CreateAction', () => { expect(MockedLocal).toHaveBeenNthCalledWith(2, '/b'); }); }); + + describe('with --remote-source', () => { + it('adds an extra PublicGitHubRepositorySource alongside the default', async () => { + await runCreateAsync(['--remote-source', 'https://github.com/my-org/my-templates']); + expect(MockedGitHub).toHaveBeenCalledTimes(2); + // First call: default source + expect(MockedGitHub).toHaveBeenNthCalledWith( + 1, + 'https://github.com/SharePoint/spfx', + undefined, + expect.anything() + ); + // Second call: remote source + expect(MockedGitHub).toHaveBeenNthCalledWith( + 2, + 'https://github.com/my-org/my-templates', + undefined, + expect.anything() + ); + }); + + it('adds multiple remote sources for multiple --remote-source flags', async () => { + await runCreateAsync([ + '--remote-source', + 'https://github.com/org1/repo1', + '--remote-source', + 'https://github.com/org2/repo2' + ]); + // default + 2 remote = 3 total + expect(MockedGitHub).toHaveBeenCalledTimes(3); + }); + + it('extracts branch from /tree/ in --remote-source URL', async () => { + await runCreateAsync(['--remote-source', 'https://github.com/my-org/my-templates/tree/my-branch']); + expect(MockedGitHub).toHaveBeenNthCalledWith( + 2, + 'https://github.com/my-org/my-templates', + 'my-branch', + expect.anything() + ); + }); + + it('works alongside --local-template without adding the default GitHub source', async () => { + await runCreateAsync([ + '--local-template', + '/path/to/templates', + '--remote-source', + 'https://github.com/my-org/my-templates' + ]); + expect(MockedLocal).toHaveBeenCalledWith('/path/to/templates'); + // Only the remote source — no default GitHub + expect(MockedGitHub).toHaveBeenCalledTimes(1); + expect(MockedGitHub).toHaveBeenCalledWith( + 'https://github.com/my-org/my-templates', + undefined, + expect.anything() + ); + }); + }); }); describe('URL normalization', () => { diff --git a/apps/spfx-cli/src/cli/actions/tests/__snapshots__/CreateAction.test.ts.snap b/apps/spfx-cli/src/cli/actions/tests/__snapshots__/CreateAction.test.ts.snap index 674ffb16..2e41db44 100644 --- a/apps/spfx-cli/src/cli/actions/tests/__snapshots__/CreateAction.test.ts.snap +++ b/apps/spfx-cli/src/cli/actions/tests/__snapshots__/CreateAction.test.ts.snap @@ -277,6 +277,55 @@ Array [ ] `; +exports[`CreateAction source selection with --remote-source adds an extra PublicGitHubRepositorySource alongside the default 1`] = ` +Array [ + "[ log] Using GitHub template source: https://github.com/SharePoint/spfx[n]", + "[ log] Adding remote template source: https://github.com/my-org/my-templates[n]", + "[ log] [Mocked SPFxTemplateCollection][n]", + "[ log] targetDir: /tmp/test[n]", + "[ log] [n]", + "[ log] The following files will be modified:[n]", + "[ log] [n]", +] +`; + +exports[`CreateAction source selection with --remote-source adds multiple remote sources for multiple --remote-source flags 1`] = ` +Array [ + "[ log] Using GitHub template source: https://github.com/SharePoint/spfx[n]", + "[ log] Adding remote template source: https://github.com/org1/repo1[n]", + "[ log] Adding remote template source: https://github.com/org2/repo2[n]", + "[ log] [Mocked SPFxTemplateCollection][n]", + "[ log] targetDir: /tmp/test[n]", + "[ log] [n]", + "[ log] The following files will be modified:[n]", + "[ log] [n]", +] +`; + +exports[`CreateAction source selection with --remote-source extracts branch from /tree/ in --remote-source URL 1`] = ` +Array [ + "[ log] Using GitHub template source: https://github.com/SharePoint/spfx[n]", + "[ log] Adding remote template source: https://github.com/my-org/my-templates (branch: my-branch)[n]", + "[ log] [Mocked SPFxTemplateCollection][n]", + "[ log] targetDir: /tmp/test[n]", + "[ log] [n]", + "[ log] The following files will be modified:[n]", + "[ log] [n]", +] +`; + +exports[`CreateAction source selection with --remote-source works alongside --local-template without adding the default GitHub source 1`] = ` +Array [ + "[ log] Adding local template source: /path/to/templates[n]", + "[ log] Adding remote template source: https://github.com/my-org/my-templates[n]", + "[ log] [Mocked SPFxTemplateCollection][n]", + "[ log] targetDir: /tmp/test[n]", + "[ log] [n]", + "[ log] The following files will be modified:[n]", + "[ log] [n]", +] +`; + exports[`CreateAction source selection without --local-template should add a PublicGitHubRepositorySource with the default URL 1`] = ` Array [ "[ log] Using GitHub template source: https://github.com/SharePoint/spfx[n]", diff --git a/apps/spfx-cli/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap b/apps/spfx-cli/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap index 5eefb3a3..5b0c1118 100644 --- a/apps/spfx-cli/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap +++ b/apps/spfx-cli/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap @@ -2,8 +2,8 @@ exports[`CommandLineHelp prints the help: create 1`] = ` "usage: spfx-cli create [-h] [--target-dir TARGET_DIR] - [--local-template TEMPLATE_PATH] --template - TEMPLATE_NAME --library-name LIBRARY_NAME + [--local-template TEMPLATE_PATH] [--remote-source URL] + --template TEMPLATE_NAME --library-name LIBRARY_NAME --component-name COMPONENT_NAME [--component-alias COMPONENT_ALIAS] [--component-description COMPONENT_DESCRIPTION] @@ -21,6 +21,8 @@ Optional arguments: solution already exists) The default value is \\"\\". --local-template TEMPLATE_PATH Path to a local template folder + --remote-source URL Public GitHub repository URL to use as an additional + template source (repeatable) --template TEMPLATE_NAME The template to use for scaffolding --library-name LIBRARY_NAME diff --git a/common/changes/@microsoft/spfx-cli/remote-source_2026-03-24.json b/common/changes/@microsoft/spfx-cli/remote-source_2026-03-24.json new file mode 100644 index 00000000..a0a328ef --- /dev/null +++ b/common/changes/@microsoft/spfx-cli/remote-source_2026-03-24.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/spfx-cli", + "comment": "", + "type": "none" + } + ], + "packageName": "@microsoft/spfx-cli" +} From a05cdfe0ee8772973b9b508b0cc8a5419a852217 Mon Sep 17 00:00:00 2001 From: Nick Pape Date: Tue, 24 Mar 2026 14:59:13 -0500 Subject: [PATCH 2/4] Fix PublicGitHubRepositorySource constructor after #180 merge #180 changed the constructor to take an options object. Updated the --remote-source call site in CreateAction to use { repoUrl, branch, terminal }. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- apps/spfx-cli/src/cli/actions/CreateAction.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/spfx-cli/src/cli/actions/CreateAction.ts b/apps/spfx-cli/src/cli/actions/CreateAction.ts index 0bffa4eb..9dc195ad 100644 --- a/apps/spfx-cli/src/cli/actions/CreateAction.ts +++ b/apps/spfx-cli/src/cli/actions/CreateAction.ts @@ -179,7 +179,13 @@ export class CreateAction extends SPFxActionBase { `Adding remote template source: ${additionalRepoUrl}` + `${additionalUrlBranch ? ` (branch: ${additionalUrlBranch})` : ''}` ); - manager.addSource(new PublicGitHubRepositorySource(additionalRepoUrl, additionalUrlBranch, terminal)); + manager.addSource( + new PublicGitHubRepositorySource({ + repoUrl: additionalRepoUrl, + branch: additionalUrlBranch, + terminal + }) + ); } let templates: SPFxTemplateCollection; From c262cc1f3fb23d500e6cf0a6535a228910ee0910 Mon Sep 17 00:00:00 2001 From: Nick Pape Date: Wed, 25 Mar 2026 10:23:58 -0500 Subject: [PATCH 3/4] Move --remote-source param and loop into SPFxActionBase Addresses review feedback: deduplicate --remote-source handling between CreateAction and ListTemplatesAction by moving the parameter definition and _addRemoteSources() helper into the shared base class. Also fixes test assertions to use options-object constructor shape after #180 changed PublicGitHubRepositorySource to take { repoUrl, branch, terminal }. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- apps/spfx-cli/src/cli/actions/CreateAction.ts | 26 +---------- .../src/cli/actions/ListTemplatesAction.ts | 25 +---------- .../src/cli/actions/SPFxActionBase.ts | 27 +++++++++++- .../cli/actions/tests/CreateAction.test.ts | 43 +++++++++---------- .../CommandLineHelp.test.ts.snap | 14 +++--- 5 files changed, 54 insertions(+), 81 deletions(-) diff --git a/apps/spfx-cli/src/cli/actions/CreateAction.ts b/apps/spfx-cli/src/cli/actions/CreateAction.ts index 9dc195ad..74a431a4 100644 --- a/apps/spfx-cli/src/cli/actions/CreateAction.ts +++ b/apps/spfx-cli/src/cli/actions/CreateAction.ts @@ -20,14 +20,12 @@ import type { } from '@rushstack/ts-command-line'; import { LocalFileSystemRepositorySource, - PublicGitHubRepositorySource, type SPFxTemplateCollection, SPFxTemplateRepositoryManager, type SPFxTemplate, SPFxTemplateWriter } from '@microsoft/spfx-template-api'; -import { parseGitHubUrlAndRef } from '../../utilities/github'; import { SOLUTION_NAME_PATTERN } from '../../utilities/validation'; import { SPFxActionBase } from './SPFxActionBase'; @@ -52,7 +50,6 @@ export class CreateAction extends SPFxActionBase { private readonly _targetDirParameter: IRequiredCommandLineStringParameter; private readonly _templateParameter: IRequiredCommandLineStringParameter; private readonly _localTemplateSourcesParameter: CommandLineStringListParameter; - private readonly _remoteSourcesParameter: CommandLineStringListParameter; private readonly _libraryNameParameter: IRequiredCommandLineStringParameter; private readonly _componentNameParameter: IRequiredCommandLineStringParameter; private readonly _componentAliasParameter: CommandLineStringParameter; @@ -83,12 +80,6 @@ export class CreateAction extends SPFxActionBase { description: 'Path to a local template folder' }); - this._remoteSourcesParameter = this.defineStringListParameter({ - parameterLongName: '--remote-source', - argumentName: 'URL', - description: 'Public GitHub repository URL to use as an additional template source (repeatable)' - }); - this._templateParameter = this.defineStringParameter({ parameterLongName: '--template', argumentName: 'TEMPLATE_NAME', @@ -171,22 +162,7 @@ export class CreateAction extends SPFxActionBase { this._addGitHubTemplateSource(manager); } - // Always process --remote-source URLs (additive with either local or default sources) - for (const remoteUrl of this._remoteSourcesParameter.values) { - const { repoUrl: additionalRepoUrl, urlBranch: additionalUrlBranch } = - parseGitHubUrlAndRef(remoteUrl); - terminal.writeLine( - `Adding remote template source: ${additionalRepoUrl}` + - `${additionalUrlBranch ? ` (branch: ${additionalUrlBranch})` : ''}` - ); - manager.addSource( - new PublicGitHubRepositorySource({ - repoUrl: additionalRepoUrl, - branch: additionalUrlBranch, - terminal - }) - ); - } + this._addRemoteSources(manager); let templates: SPFxTemplateCollection; try { diff --git a/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts b/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts index 222fd266..314b68bb 100644 --- a/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts +++ b/apps/spfx-cli/src/cli/actions/ListTemplatesAction.ts @@ -5,17 +5,14 @@ import type { CommandLineStringListParameter } from '@rushstack/ts-command-line' import type { Terminal } from '@rushstack/terminal'; import { LocalFileSystemRepositorySource, - PublicGitHubRepositorySource, type SPFxTemplateCollection, SPFxTemplateRepositoryManager } from '@microsoft/spfx-template-api'; -import { parseGitHubUrlAndRef } from '../../utilities/github'; import { SPFxActionBase } from './SPFxActionBase'; export class ListTemplatesAction extends SPFxActionBase { private readonly _localSourcesParameter: CommandLineStringListParameter; - private readonly _remoteSourcesParameter: CommandLineStringListParameter; public constructor(terminal: Terminal) { super( @@ -34,12 +31,6 @@ export class ListTemplatesAction extends SPFxActionBase { argumentName: 'PATH', description: 'Path to a local template folder to include (repeatable)' }); - - this._remoteSourcesParameter = this.defineStringListParameter({ - parameterLongName: '--remote-source', - argumentName: 'URL', - description: 'Public GitHub repository URL to include as an additional template source (repeatable)' - }); } protected override async onExecuteAsync(): Promise { @@ -58,21 +49,7 @@ export class ListTemplatesAction extends SPFxActionBase { } // Additive: also include any --remote-source URLs - for (const remoteUrl of this._remoteSourcesParameter.values) { - const { repoUrl: additionalRepoUrl, urlBranch: additionalUrlBranch } = - parseGitHubUrlAndRef(remoteUrl); - terminal.writeLine( - `Adding remote template source: ${additionalRepoUrl}` + - `${additionalUrlBranch ? ` (branch: ${additionalUrlBranch})` : ''}` - ); - manager.addSource( - new PublicGitHubRepositorySource({ - repoUrl: additionalRepoUrl, - branch: additionalUrlBranch, - terminal - }) - ); - } + this._addRemoteSources(manager); let templates: SPFxTemplateCollection; try { diff --git a/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts b/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts index 012c8114..0c37dd19 100644 --- a/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts +++ b/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts @@ -4,6 +4,7 @@ import type { Terminal } from '@rushstack/terminal'; import { CommandLineAction, + type CommandLineStringListParameter, type CommandLineStringParameter, type ICommandLineActionOptions } from '@rushstack/ts-command-line'; @@ -20,13 +21,14 @@ import { /** * Base class for SPFx CLI actions that work with template sources. - * Defines the shared `--template-url` and `--spfx-version` parameters and provides - * a helper to register a GitHub template source on a repository manager. + * Defines the shared `--template-url`, `--spfx-version`, and `--remote-source` parameters + * and provides helpers to register template sources on a repository manager. */ export abstract class SPFxActionBase extends CommandLineAction { protected readonly _terminal: Terminal; protected readonly _templateUrlParameter: CommandLineStringParameter; protected readonly _spfxVersionParameter: CommandLineStringParameter; + protected readonly _remoteSourcesParameter: CommandLineStringListParameter; protected constructor(options: ICommandLineActionOptions, terminal: Terminal) { super(options); @@ -47,6 +49,12 @@ export abstract class SPFxActionBase extends CommandLineAction { 'The SPFx version to use (e.g., "1.22", "1.23-rc.0"). Resolves to the "version/" branch ' + "in the template repository. Defaults to the repository's default branch (main)." }); + + this._remoteSourcesParameter = this.defineStringListParameter({ + parameterLongName: '--remote-source', + argumentName: 'URL', + description: 'Public GitHub repository URL to use as an additional template source (repeatable)' + }); } /** @@ -80,4 +88,19 @@ export abstract class SPFxActionBase extends CommandLineAction { terminal.writeLine(`Using GitHub template source: ${repoUrl}${ref ? ` (branch: ${ref})` : ''}`); manager.addSource(new PublicGitHubRepositorySource({ repoUrl, branch: ref, terminal })); } + + /** + * Processes all `--remote-source` URLs and registers a {@link PublicGitHubRepositorySource} + * for each on the given manager. Additive with any other sources already registered. + */ + protected _addRemoteSources(manager: SPFxTemplateRepositoryManager): void { + const terminal: Terminal = this._terminal; + for (const remoteUrl of this._remoteSourcesParameter.values) { + const { repoUrl, urlBranch } = parseGitHubUrlAndRef(remoteUrl); + terminal.writeLine( + `Adding remote template source: ${repoUrl}` + `${urlBranch ? ` (branch: ${urlBranch})` : ''}` + ); + manager.addSource(new PublicGitHubRepositorySource({ repoUrl, branch: urlBranch, terminal })); + } + } } diff --git a/apps/spfx-cli/src/cli/actions/tests/CreateAction.test.ts b/apps/spfx-cli/src/cli/actions/tests/CreateAction.test.ts index ec6cba81..0cc3ec56 100644 --- a/apps/spfx-cli/src/cli/actions/tests/CreateAction.test.ts +++ b/apps/spfx-cli/src/cli/actions/tests/CreateAction.test.ts @@ -177,19 +177,17 @@ describe('CreateAction', () => { await runCreateAsync(['--remote-source', 'https://github.com/my-org/my-templates']); expect(MockedGitHub).toHaveBeenCalledTimes(2); // First call: default source - expect(MockedGitHub).toHaveBeenNthCalledWith( - 1, - 'https://github.com/SharePoint/spfx', - undefined, - expect.anything() - ); + expect(MockedGitHub).toHaveBeenNthCalledWith(1, { + repoUrl: 'https://github.com/SharePoint/spfx', + branch: undefined, + terminal: expect.anything() + }); // Second call: remote source - expect(MockedGitHub).toHaveBeenNthCalledWith( - 2, - 'https://github.com/my-org/my-templates', - undefined, - expect.anything() - ); + expect(MockedGitHub).toHaveBeenNthCalledWith(2, { + repoUrl: 'https://github.com/my-org/my-templates', + branch: undefined, + terminal: expect.anything() + }); }); it('adds multiple remote sources for multiple --remote-source flags', async () => { @@ -205,12 +203,11 @@ describe('CreateAction', () => { it('extracts branch from /tree/ in --remote-source URL', async () => { await runCreateAsync(['--remote-source', 'https://github.com/my-org/my-templates/tree/my-branch']); - expect(MockedGitHub).toHaveBeenNthCalledWith( - 2, - 'https://github.com/my-org/my-templates', - 'my-branch', - expect.anything() - ); + expect(MockedGitHub).toHaveBeenNthCalledWith(2, { + repoUrl: 'https://github.com/my-org/my-templates', + branch: 'my-branch', + terminal: expect.anything() + }); }); it('works alongside --local-template without adding the default GitHub source', async () => { @@ -223,11 +220,11 @@ describe('CreateAction', () => { expect(MockedLocal).toHaveBeenCalledWith('/path/to/templates'); // Only the remote source — no default GitHub expect(MockedGitHub).toHaveBeenCalledTimes(1); - expect(MockedGitHub).toHaveBeenCalledWith( - 'https://github.com/my-org/my-templates', - undefined, - expect.anything() - ); + expect(MockedGitHub).toHaveBeenCalledWith({ + repoUrl: 'https://github.com/my-org/my-templates', + branch: undefined, + terminal: expect.anything() + }); }); }); }); diff --git a/apps/spfx-cli/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap b/apps/spfx-cli/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap index 9051887c..a8a78c26 100644 --- a/apps/spfx-cli/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap +++ b/apps/spfx-cli/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap @@ -2,8 +2,8 @@ exports[`CommandLineHelp prints the help: create 1`] = ` "usage: spfx create [-h] [--template-url URL] [--spfx-version VERSION] - [--target-dir TARGET_DIR] [--local-template TEMPLATE_PATH] - [--remote-source URL] --template TEMPLATE_NAME + [--remote-source URL] [--target-dir TARGET_DIR] + [--local-template TEMPLATE_PATH] --template TEMPLATE_NAME --library-name LIBRARY_NAME --component-name COMPONENT_NAME [--component-alias COMPONENT_ALIAS] [--component-description COMPONENT_DESCRIPTION] @@ -24,13 +24,13 @@ Optional arguments: Resolves to the \\"version/\\" branch in the template repository. Defaults to the repository's default branch (main). + --remote-source URL Public GitHub repository URL to use as an additional + template source (repeatable) --target-dir TARGET_DIR The directory to create the solution (or where the solution already exists) The default value is \\"\\". --local-template TEMPLATE_PATH Path to a local template folder - --remote-source URL Public GitHub repository URL to use as an additional - template source (repeatable) --template TEMPLATE_NAME The template to use for scaffolding --library-name LIBRARY_NAME @@ -73,7 +73,7 @@ Optional arguments: exports[`CommandLineHelp prints the help: list-templates 1`] = ` "usage: spfx list-templates [-h] [--template-url URL] [--spfx-version VERSION] - [--local-source PATH] [--remote-source URL] + [--remote-source URL] [--local-source PATH] This command lists all available templates from the default GitHub source and @@ -90,9 +90,9 @@ Optional arguments: Resolves to the \\"version/\\" branch in the template repository. Defaults to the repository's default branch (main). + --remote-source URL Public GitHub repository URL to use as an additional + template source (repeatable) --local-source PATH Path to a local template folder to include (repeatable) - --remote-source URL Public GitHub repository URL to include as an - additional template source (repeatable) " `; From c2beafbad9e71b15311661c7794bf36d53864cd4 Mon Sep 17 00:00:00 2001 From: Nick Pape Date: Wed, 25 Mar 2026 10:27:55 -0500 Subject: [PATCH 4/4] Fix no-useless-concat lint error in SPFxActionBase Co-Authored-By: Claude Sonnet 4.6 (1M context) --- apps/spfx-cli/src/cli/actions/SPFxActionBase.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts b/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts index 0c37dd19..6a5cf479 100644 --- a/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts +++ b/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts @@ -98,7 +98,7 @@ export abstract class SPFxActionBase extends CommandLineAction { for (const remoteUrl of this._remoteSourcesParameter.values) { const { repoUrl, urlBranch } = parseGitHubUrlAndRef(remoteUrl); terminal.writeLine( - `Adding remote template source: ${repoUrl}` + `${urlBranch ? ` (branch: ${urlBranch})` : ''}` + `Adding remote template source: ${repoUrl}${urlBranch ? ` (branch: ${urlBranch})` : ''}` ); manager.addSource(new PublicGitHubRepositorySource({ repoUrl, branch: urlBranch, terminal })); }