1515 */
1616
1717import { readdir } from 'node:fs/promises' ;
18+ import { readdirSync } from 'node:fs' ;
1819import { basename , join , relative } from 'node:path' ;
1920import { Interfaces } from '@oclif/core' ;
2021import { Flags } from '@salesforce/sf-plugins-core' ;
21- import { Connection , Messages , SfError } from '@salesforce/core' ;
22+ import { Connection , Messages , SfError , SfProject } from '@salesforce/core' ;
2223import { camelCaseToTitleCase } from '@salesforce/kit' ;
2324import { select , input as inquirerInput } from '@inquirer/prompts' ;
2425import autocomplete from 'inquirer-autocomplete-standalone' ;
@@ -102,18 +103,25 @@ export async function getHiddenDirs(projectRoot?: string): Promise<string[]> {
102103 }
103104}
104105
105- export async function traverseForFiles ( dir : string , suffixes : string [ ] , excludeDirs ?: string [ ] ) : Promise < string [ ] > {
106- const files = await readdir ( dir , { withFileTypes : true } ) ;
106+ export function traverseForFiles ( dir : string , suffixes : string [ ] , excludeDirs ?: string [ ] ) : string [ ] ;
107+ // eslint-disable-next-line @typescript-eslint/unified-signatures
108+ export function traverseForFiles ( dirs : string [ ] , suffixes : string [ ] , excludeDirs ?: string [ ] ) : string [ ] ;
109+
110+ export function traverseForFiles ( dirOrDirs : string | string [ ] , suffixes : string [ ] , excludeDirs ?: string [ ] ) : string [ ] {
111+ const dirs = Array . isArray ( dirOrDirs ) ? dirOrDirs : [ dirOrDirs ] ;
107112 const results : string [ ] = [ ] ;
108113
109- for ( const file of files ) {
110- const fullPath = join ( dir , file . name ) ;
114+ for ( const dir of dirs ) {
115+ const files = readdirSync ( dir , { withFileTypes : true } ) ;
116+
117+ for ( const file of files ) {
118+ const fullPath = join ( dir , file . name ) ;
111119
112- if ( file . isDirectory ( ) && ! excludeDirs ?. includes ( file . name ) ) {
113- // eslint-disable-next-line no-await-in-loop
114- results . push ( ... ( await traverseForFiles ( fullPath , suffixes , excludeDirs ) ) ) ;
115- } else if ( suffixes . some ( ( suffix ) => file . name . endsWith ( suffix ) ) ) {
116- results . push ( fullPath ) ;
120+ if ( file . isDirectory ( ) && ! excludeDirs ?. includes ( file . name ) ) {
121+ results . push ( ... traverseForFiles ( fullPath , suffixes , excludeDirs ) ) ;
122+ } else if ( suffixes . some ( ( suffix ) => file . name . endsWith ( suffix ) ) ) {
123+ results . push ( fullPath ) ;
124+ }
117125 }
118126 }
119127
@@ -135,7 +143,7 @@ export const promptForAiEvaluationDefinitionApiName = async (
135143
136144 return Promise . race ( [
137145 autocomplete ( {
138- message : flagDef . message ,
146+ message : flagDef . promptMessage ?? flagDef . message ,
139147 // eslint-disable-next-line @typescript-eslint/require-await
140148 source : async ( input ) => {
141149 const arr = aiDefFiles . map ( ( o ) => ( { name : o . fullName , value : o . fullName } ) ) ;
@@ -154,10 +162,12 @@ export const promptForAiEvaluationDefinitionApiName = async (
154162export const promptForFileByExtensions = async (
155163 flagDef : FlaggablePrompt ,
156164 extensions : string [ ] ,
157- fileNameOnly = false
165+ fileNameOnly = false ,
166+ dirs ?: string [ ]
158167) : Promise < string > => {
159168 const hiddenDirs = await getHiddenDirs ( ) ;
160- const files = await traverseForFiles ( process . cwd ( ) , extensions , [ 'node_modules' , ...hiddenDirs ] ) ;
169+ const dirsToTraverse = dirs ?? [ process . cwd ( ) ] ;
170+ const files = traverseForFiles ( dirsToTraverse , extensions , [ 'node_modules' , ...hiddenDirs ] ) ;
161171 return autocomplete ( {
162172 message : flagDef . promptMessage ?? flagDef . message . replace ( / \. $ / , '' ) ,
163173 // eslint-disable-next-line @typescript-eslint/require-await
@@ -194,6 +204,11 @@ export const promptForFlag = async (flagDef: FlaggablePrompt): Promise<string> =
194204 } ) ;
195205} ;
196206
207+ export const promptForAgentFiles = ( project : SfProject , flagDef : FlaggablePrompt ) : Promise < string > => {
208+ const dirs = project . getPackageDirectories ( ) . map ( ( dir ) => dir . fullPath ) ;
209+ return promptForFileByExtensions ( flagDef , [ '.bundle-meta.xml' ] , true , dirs ) ;
210+ } ;
211+
197212export const validateAgentType = ( agentType ?: string , required = false ) : string | undefined => {
198213 if ( required && ! agentType ) {
199214 throw messages . createError ( 'error.invalidAgentType' , [ agentType ] ) ;
0 commit comments