MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / execute

Method execute

src/tools/frontend/design-tools.ts:215–287  ·  view source on GitHub ↗
(args: z.infer<typeof FindUiComponentsArgs>, ctx: ToolContext)

Source from the content-addressed store, hash-verified

213 argsSchema = FindUiComponentsArgs;
214
215 async execute(args: z.infer<typeof FindUiComponentsArgs>, ctx: ToolContext): Promise<ToolResult> {
216 const root = args.path ? path.join(ctx.cwd, args.path) : ctx.cwd;
217 const maxFiles = args.max_files ?? 5000;
218 const files = await walkFiles(root, new Set(['.tsx', '.jsx', '.vue', '.svelte', '.astro']), maxFiles);
219
220 interface Comp { name: string; file: string; props: string[]; usage: number }
221 const comps = new Map<string, Comp>();
222
223 // Pass 1: extract component declarations from each file
224 for (const f of files) {
225 const isReact = f.rel.endsWith('.tsx') || f.rel.endsWith('.jsx');
226 if (isReact) {
227 // export default function X / export function X / const X = () => / const X: FC<...> =
228 const re = /(?:export\s+(?:default\s+)?(?:function|const)\s+([A-Z][A-Za-z0-9_]*)|(?:^|\n)const\s+([A-Z][A-Za-z0-9_]*)\s*=)/g;
229 const seen = new Set<string>();
230 let m;
231 while ((m = re.exec(f.content)) !== null) {
232 const name = m[1] || m[2]!;
233 if (seen.has(name)) continue;
234 seen.add(name);
235 // Extract props from immediate interface or type alias above the function
236 const propsRe = new RegExp(`(?:interface|type)\\s+${name}Props\\s*=?\\s*\\{([\\s\\S]*?)\\n\\}`);
237 const pm = propsRe.exec(f.content);
238 const props: string[] = [];
239 if (pm) {
240 const lines = pm[1]!.split('\n').slice(0, 20);
241 for (const l of lines) {
242 const pl = l.trim();
243 if (!pl || pl.startsWith('//') || pl.startsWith('*')) continue;
244 const propName = pl.split(/[:?]/)[0]?.trim();
245 if (propName && /^[a-zA-Z_$]/.test(propName)) props.push(propName);
246 }
247 }
248 if (!comps.has(name)) comps.set(name, { name, file: f.rel, props, usage: 0 });
249 }
250 } else if (f.rel.endsWith('.vue') || f.rel.endsWith('.svelte') || f.rel.endsWith('.astro')) {
251 const base = path.basename(f.rel).replace(/\.(vue|svelte|astro)$/, '');
252 if (/^[A-Z]/.test(base) && !comps.has(base)) {
253 comps.set(base, { name: base, file: f.rel, props: [], usage: 0 });
254 }
255 }
256 }
257
258 // Pass 2: count usage — `<ComponentName` in each file
259 for (const f of files) {
260 for (const [name, c] of comps) {
261 if (f.rel === c.file) continue;
262 const re = new RegExp(`<${name}[\\s/>]`, 'g');
263 const matches = f.content.match(re);
264 if (matches) c.usage += matches.length;
265 }
266 }
267
268 const arr = Array.from(comps.values()).sort((a, b) => b.usage - a.usage);
269 const out: string[] = [];
270 out.push(`# UI Components (${arr.length})`);
271 out.push('');
272 out.push(`## Most used (top 30)`);

Callers

nothing calls this directly

Calls 5

walkFilesFunction · 0.85
addMethod · 0.80
hasMethod · 0.45
pushMethod · 0.45
setMethod · 0.45

Tested by

no test coverage detected