(workspaceRoot: string, scanRoots: string[], libName: string)
| 54 | } |
| 55 | |
| 56 | function discoverSharedLibPath(workspaceRoot: string, scanRoots: string[], libName: string): string | undefined { |
| 57 | // 1. Direct child of a scan root |
| 58 | for (const root of scanRoots) { |
| 59 | const candidate = path.join(root, libName); |
| 60 | if (fs.existsSync(candidate)) return candidate; |
| 61 | } |
| 62 | |
| 63 | // 2. Sibling directory of the workspace (separate git checkout) |
| 64 | // e.g. workspace is ~/projects/my_app, look for ~/projects/valdi_widgets |
| 65 | const parentDir = path.dirname(workspaceRoot); |
| 66 | const siblingCandidates = [ |
| 67 | libName, |
| 68 | libName |
| 69 | .split('_') |
| 70 | .map(s => s.charAt(0).toUpperCase() + s.slice(1)) |
| 71 | .join('_'), |
| 72 | libName.replace(/_/g, '-'), |
| 73 | libName.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase()), |
| 74 | ]; |
| 75 | for (const name of siblingCandidates) { |
| 76 | const candidate = path.join(parentDir, name); |
| 77 | if (fs.existsSync(candidate)) return candidate; |
| 78 | } |
| 79 | |
| 80 | // 3. Bazel external deps (bzlmod: bazel-<workspace>/external/*+<name>*) |
| 81 | const bazelSymlinks = findBazelWorkspaceSymlinks(workspaceRoot); |
| 82 | for (const bazelDir of bazelSymlinks) { |
| 83 | const externalDir = path.join(bazelDir, 'external'); |
| 84 | if (!fs.existsSync(externalDir)) continue; |
| 85 | try { |
| 86 | const entries = fs.readdirSync(externalDir); |
| 87 | for (const entry of entries) { |
| 88 | if (entry.includes(libName)) { |
| 89 | const candidate = path.join(externalDir, entry); |
| 90 | if (fs.statSync(candidate).isDirectory()) return candidate; |
| 91 | } |
| 92 | } |
| 93 | } catch { |
| 94 | // permission or symlink errors |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | // 4. node_modules |
| 99 | const nodeModules = path.join(workspaceRoot, 'node_modules', libName); |
| 100 | if (fs.existsSync(nodeModules)) return nodeModules; |
| 101 | |
| 102 | return undefined; |
| 103 | } |
| 104 | |
| 105 | function findBazelWorkspaceSymlinks(workspaceRoot: string): string[] { |
| 106 | const results: string[] = []; |
no test coverage detected