* Resolve a TypeScript path alias (tsconfig compilerOptions.paths) to an absolute file path. * Also supports non-relative imports resolved via compilerOptions.baseUrl. * Returns undefined when no mapping matches or the tsconfig is unavailable.
(moduleSpecifier: string)
| 1335 | * Returns undefined when no mapping matches or the tsconfig is unavailable. |
| 1336 | */ |
| 1337 | private resolvePathAlias(moduleSpecifier: string): string | undefined { |
| 1338 | try { |
| 1339 | const tsconfigPath = Configuration.mainData.tsconfig; |
| 1340 | if (!tsconfigPath) return undefined; |
| 1341 | |
| 1342 | const tsconfig = readConfig(tsconfigPath); |
| 1343 | const compilerOptions = tsconfig?.compilerOptions; |
| 1344 | if (!compilerOptions) return undefined; |
| 1345 | |
| 1346 | const baseUrl = compilerOptions.baseUrl |
| 1347 | ? path.resolve(path.dirname(tsconfigPath), compilerOptions.baseUrl) |
| 1348 | : path.dirname(tsconfigPath); |
| 1349 | |
| 1350 | if (compilerOptions.paths) { |
| 1351 | for (const [pattern, replacements] of Object.entries( |
| 1352 | compilerOptions.paths as Record<string, string[]> |
| 1353 | )) { |
| 1354 | if (!Array.isArray(replacements) || replacements.length === 0) continue; |
| 1355 | |
| 1356 | // Convert glob pattern to regex: "@shared/*" → /^@shared\/(.*)$/ |
| 1357 | const regexStr = pattern |
| 1358 | .replace(/[-[\]{}()+?.,\\^$|#\s]/g, '\\$&') |
| 1359 | .replace(/\*/g, '(.*)'); |
| 1360 | const regex = new RegExp('^' + regexStr + '$'); |
| 1361 | const match = moduleSpecifier.match(regex); |
| 1362 | |
| 1363 | if (match) { |
| 1364 | const resolved = (replacements[0] as string).replace(/\*/g, match[1] ?? ''); |
| 1365 | return path.resolve(baseUrl, resolved); |
| 1366 | } |
| 1367 | } |
| 1368 | } |
| 1369 | |
| 1370 | const isNonRelative = |
| 1371 | !moduleSpecifier.startsWith('./') && |
| 1372 | !moduleSpecifier.startsWith('../') && |
| 1373 | !path.isAbsolute(moduleSpecifier); |
| 1374 | if (isNonRelative) { |
| 1375 | return path.resolve(baseUrl, moduleSpecifier); |
| 1376 | } |
| 1377 | } catch (_e) { |
| 1378 | // silently skip — tsconfig may not be readable at this point |
| 1379 | } |
| 1380 | return undefined; |
| 1381 | } |
| 1382 | |
| 1383 | public cleanFileSpreads(sourceFile: SourceFile): SourceFile { |
| 1384 | const file = sourceFile; |
no test coverage detected