Skip to content

Commit 5a07725

Browse files
feat: add when condition to ExtraTool for template-based filtering (#96)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent bdbfc15 commit 5a07725

2 files changed

Lines changed: 81 additions & 5 deletions

File tree

src/index.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,22 @@ function logHelpMessage(
142142
async function getTools(
143143
{ tools, dir, template }: Argv,
144144
extraTools?: ExtraTool[],
145+
templateName?: string,
145146
) {
146147
// Check if tools are specified via CLI options
147148
const parsedTools = parseToolsOption(tools);
148149

150+
// Filter extraTools based on templateName
151+
const filteredExtraTools = extraTools?.filter((tool) => {
152+
const when = tool.when ?? (() => true);
153+
return templateName ? when(templateName) : true;
154+
});
155+
149156
if (parsedTools !== null) {
150157
const toolsArr = parsedTools.filter(
151158
(tool) =>
152159
BUILTIN_TOOLS.includes(tool) ||
153-
extraTools?.some((extraTool) => extraTool.value === tool),
160+
filteredExtraTools?.some((extraTool) => extraTool.value === tool),
154161
);
155162
return toolsArr;
156163
}
@@ -165,17 +172,21 @@ async function getTools(
165172
{ value: 'prettier', label: 'Prettier - formatting' },
166173
];
167174

168-
if (extraTools) {
175+
if (filteredExtraTools) {
169176
const normalize = (tool: ExtraTool) => ({
170177
value: tool.value,
171178
label: tool.label,
172179
hint: tool.command,
173180
});
174181
options.unshift(
175-
...extraTools.filter((tool) => tool.order === 'pre').map(normalize),
182+
...filteredExtraTools
183+
.filter((tool) => tool.order === 'pre')
184+
.map(normalize),
176185
);
177186
options.push(
178-
...extraTools.filter((tool) => tool.order !== 'pre').map(normalize),
187+
...filteredExtraTools
188+
.filter((tool) => tool.order !== 'pre')
189+
.map(normalize),
179190
);
180191
}
181192

@@ -252,6 +263,12 @@ type ExtraTool = {
252263
* If undefined, the tool will be displayed after built-in tools.
253264
*/
254265
order?: 'pre' | 'post';
266+
/**
267+
* Condition to determine whether this tool should be displayed.
268+
* If returns false, the tool will not be shown in the selection.
269+
* @default () => true
270+
*/
271+
when?: (templateName: string) => boolean;
255272
};
256273

257274
function runCommand(command: string, cwd: string, packageManager: string) {
@@ -385,7 +402,7 @@ export async function create({
385402
}
386403

387404
const templateName = await getTemplateName(argv);
388-
const tools = await getTools(argv, extraTools);
405+
const tools = await getTools(argv, extraTools, templateName);
389406

390407
const srcFolder = path.join(root, `template-${templateName}`);
391408
const commonFolder = path.join(root, 'template-common');

test/custom-tools.test.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,62 @@ test('should run extra tool command', async () => {
9090

9191
expect(fs.existsSync(testFile)).toBe(false);
9292
});
93+
94+
test('should filter extra tools based on template name', async () => {
95+
const projectDir = path.join(testDir, 'extra-tool-filter');
96+
let filteredToolCalled = false;
97+
let allowedToolCalled = false;
98+
let noFilterToolCalled = false;
99+
100+
await create({
101+
name: 'test',
102+
root: fixturesDir,
103+
templates: ['vanilla'],
104+
getTemplateName: async () => 'vanilla',
105+
extraTools: [
106+
{
107+
value: 'filtered-tool',
108+
label: 'Filtered Tool',
109+
// This tool should be filtered out for 'vanilla' template
110+
when: (templateName) => templateName !== 'vanilla',
111+
action: () => {
112+
filteredToolCalled = true;
113+
},
114+
},
115+
{
116+
value: 'allowed-tool',
117+
label: 'Allowed Tool',
118+
// This tool should be allowed for 'vanilla' template
119+
when: (templateName) => templateName === 'vanilla',
120+
action: () => {
121+
allowedToolCalled = true;
122+
},
123+
},
124+
{
125+
value: 'no-filter-tool',
126+
label: 'No Filter Tool',
127+
// No `when` property - should always be available
128+
action: () => {
129+
noFilterToolCalled = true;
130+
},
131+
},
132+
],
133+
argv: [
134+
'node',
135+
'test',
136+
'--dir',
137+
projectDir,
138+
'--template',
139+
'vanilla',
140+
'--tools',
141+
'filtered-tool,allowed-tool,no-filter-tool',
142+
],
143+
});
144+
145+
// filtered-tool should not run because `when` returns false
146+
expect(filteredToolCalled).toBe(false);
147+
// allowed-tool should run because `when` returns true
148+
expect(allowedToolCalled).toBe(true);
149+
// no-filter-tool should run because it has no `when`
150+
expect(noFilterToolCalled).toBe(true);
151+
});

0 commit comments

Comments
 (0)