Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,22 @@ function logHelpMessage(
async function getTools(
{ tools, dir, template }: Argv,
extraTools?: ExtraTool[],
templateName?: string,
) {
// Check if tools are specified via CLI options
const parsedTools = parseToolsOption(tools);

// Filter extraTools based on templateName
const filteredExtraTools = extraTools?.filter((tool) => {
const when = tool.when ?? (() => true);
return templateName ? when(templateName) : true;
});

if (parsedTools !== null) {
const toolsArr = parsedTools.filter(
(tool) =>
BUILTIN_TOOLS.includes(tool) ||
extraTools?.some((extraTool) => extraTool.value === tool),
filteredExtraTools?.some((extraTool) => extraTool.value === tool),
);
return toolsArr;
}
Expand All @@ -165,17 +172,21 @@ async function getTools(
{ value: 'prettier', label: 'Prettier - formatting' },
];

if (extraTools) {
if (filteredExtraTools) {
const normalize = (tool: ExtraTool) => ({
value: tool.value,
label: tool.label,
hint: tool.command,
});
options.unshift(
...extraTools.filter((tool) => tool.order === 'pre').map(normalize),
...filteredExtraTools
.filter((tool) => tool.order === 'pre')
.map(normalize),
);
options.push(
...extraTools.filter((tool) => tool.order !== 'pre').map(normalize),
...filteredExtraTools
.filter((tool) => tool.order !== 'pre')
.map(normalize),
);
}

Expand Down Expand Up @@ -252,6 +263,12 @@ type ExtraTool = {
* If undefined, the tool will be displayed after built-in tools.
*/
order?: 'pre' | 'post';
/**
* Condition to determine whether this tool should be displayed.
* If returns false, the tool will not be shown in the selection.
* @default () => true
*/
when?: (templateName: string) => boolean;
};

function runCommand(command: string, cwd: string, packageManager: string) {
Expand Down Expand Up @@ -385,7 +402,7 @@ export async function create({
}

const templateName = await getTemplateName(argv);
const tools = await getTools(argv, extraTools);
const tools = await getTools(argv, extraTools, templateName);

const srcFolder = path.join(root, `template-${templateName}`);
const commonFolder = path.join(root, 'template-common');
Expand Down
59 changes: 59 additions & 0 deletions test/custom-tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,62 @@ test('should run extra tool command', async () => {

expect(fs.existsSync(testFile)).toBe(false);
});

test('should filter extra tools based on template name', async () => {
const projectDir = path.join(testDir, 'extra-tool-filter');
let filteredToolCalled = false;
let allowedToolCalled = false;
let noFilterToolCalled = false;

await create({
name: 'test',
root: fixturesDir,
templates: ['vanilla'],
getTemplateName: async () => 'vanilla',
extraTools: [
{
value: 'filtered-tool',
label: 'Filtered Tool',
// This tool should be filtered out for 'vanilla' template
when: (templateName) => templateName !== 'vanilla',
action: () => {
filteredToolCalled = true;
},
},
{
value: 'allowed-tool',
label: 'Allowed Tool',
// This tool should be allowed for 'vanilla' template
when: (templateName) => templateName === 'vanilla',
action: () => {
allowedToolCalled = true;
},
},
{
value: 'no-filter-tool',
label: 'No Filter Tool',
// No `when` property - should always be available
action: () => {
noFilterToolCalled = true;
},
},
],
argv: [
'node',
'test',
'--dir',
projectDir,
'--template',
'vanilla',
'--tools',
'filtered-tool,allowed-tool,no-filter-tool',
],
});

// filtered-tool should not run because `when` returns false
expect(filteredToolCalled).toBe(false);
// allowed-tool should run because `when` returns true
expect(allowedToolCalled).toBe(true);
// no-filter-tool should run because it has no `when`
expect(noFilterToolCalled).toBe(true);
});