( inputPath: string, trustedRootPath?: string )
| 189 | } |
| 190 | |
| 191 | export async function findNearestProjectBoundary( |
| 192 | inputPath: string, |
| 193 | trustedRootPath?: string |
| 194 | ): Promise<DiscoveredProjectCandidate | undefined> { |
| 195 | const resolvedTrustedRootPath = trustedRootPath ? path.resolve(trustedRootPath) : undefined; |
| 196 | let currentPath = path.resolve(inputPath); |
| 197 | |
| 198 | for (;;) { |
| 199 | if (resolvedTrustedRootPath && !isPathWithin(resolvedTrustedRootPath, currentPath)) { |
| 200 | return undefined; |
| 201 | } |
| 202 | |
| 203 | let stats; |
| 204 | try { |
| 205 | stats = await fs.stat(currentPath); |
| 206 | } catch { |
| 207 | return undefined; |
| 208 | } |
| 209 | |
| 210 | const directoryPath = stats.isDirectory() ? currentPath : path.dirname(currentPath); |
| 211 | let entries: Dirent[]; |
| 212 | try { |
| 213 | entries = await fs.readdir(directoryPath, { withFileTypes: true }); |
| 214 | } catch { |
| 215 | entries = []; |
| 216 | } |
| 217 | |
| 218 | const fileNames = new Set(entries.filter((entry) => entry.isFile()).map((entry) => entry.name)); |
| 219 | const directoryNames = new Set( |
| 220 | entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name) |
| 221 | ); |
| 222 | const classification = await classifyDirectory(directoryPath, fileNames, directoryNames); |
| 223 | if (classification.candidate) { |
| 224 | return classification.candidate; |
| 225 | } |
| 226 | |
| 227 | if ( |
| 228 | resolvedTrustedRootPath && |
| 229 | normalizePathKey(directoryPath) === normalizePathKey(resolvedTrustedRootPath) |
| 230 | ) { |
| 231 | return undefined; |
| 232 | } |
| 233 | |
| 234 | const parentPath = path.dirname(directoryPath); |
| 235 | if (parentPath === directoryPath) { |
| 236 | return undefined; |
| 237 | } |
| 238 | |
| 239 | currentPath = parentPath; |
| 240 | } |
| 241 | } |
no test coverage detected