Skip to content

Commit 48c0830

Browse files
committed
Add paths support
1 parent 42e5c19 commit 48c0830

File tree

1 file changed

+63
-1
lines changed

1 file changed

+63
-1
lines changed

src/index.ts

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { relative, basename, extname, resolve, dirname, join } from 'path'
2-
import { readdirSync, writeFileSync, readFileSync, statSync } from 'fs'
2+
import { readdirSync, writeFileSync, readFileSync, statSync, existsSync } from 'fs'
33
import { EOL, tmpdir } from 'os'
44
import sourceMapSupport = require('source-map-support')
55
import extend = require('xtend')
@@ -186,6 +186,11 @@ export function register (options: Options = {}): () => Register {
186186
const configDiagnostics = filterDiagnostics(config.errors, ignoreWarnings, disableWarnings)
187187
const extensions = ['.ts', '.tsx']
188188

189+
// Augment loading of node modules according to paths in tsconfig
190+
if (config.options.baseUrl && config.options.paths) {
191+
installModuleLoadForPaths(config.options.baseUrl, config.options.paths)
192+
}
193+
189194
const cachedir = join(
190195
resolve(cwd, cacheDirectory),
191196
getCompilerDigest({ version: ts.version, fast, ignoreWarnings, disableWarnings, config, compiler })
@@ -650,3 +655,60 @@ export class TSError extends BaseError {
650655
}
651656

652657
}
658+
659+
/**
660+
* Matches pattern with a single star against search.
661+
* Star must match at least one character to be considered a match.
662+
* @returns the part of search that * matches, or undefined if no match.
663+
*/
664+
function matchStar(pattern: string, search: string): string | undefined {
665+
if (search.length < pattern.length) { return undefined }
666+
if (pattern === '*') { return search }
667+
const star = pattern.indexOf('*')
668+
if (star === -1) { return undefined }
669+
const part1 = pattern.substring(0, star)
670+
const part2 = pattern.substring(star + 1)
671+
if (search.substr(0, star) !== part1) { return undefined }
672+
if (search.substr(search.length - part2.length) !== part2) { return undefined }
673+
return search.substr(star, search.length - part2.length)
674+
}
675+
676+
/**
677+
* Finds a path from tsconfig that matches a module load request.
678+
* @returns the found path, or undefined if no path was found.
679+
*/
680+
function findConfigPath(request: string, baseUrl: string, paths: {[key: string]: Array<string>}) {
681+
682+
if (request[0] !== '.' && request[0] !== '/') {
683+
for (const key of Object.keys(paths)) {
684+
const starReplace = key === request ? '' : matchStar(key, request)
685+
if (starReplace !== undefined) {
686+
for (const pathToTry of paths[key]) {
687+
const file = pathToTry.replace('*', starReplace)
688+
if (existsSync(join(baseUrl, file))
689+
|| existsSync(join(baseUrl, file + '.ts'))
690+
|| existsSync(join(baseUrl, file + '.tsx'))) {
691+
return file
692+
}
693+
}
694+
}
695+
}
696+
}
697+
return undefined
698+
699+
}
700+
701+
/**
702+
* Installs a custom module load function that can adhere to paths in tsconfig.
703+
*/
704+
function installModuleLoadForPaths(baseUrl: string, paths: {[key: string]: Array<string>}): void {
705+
706+
const Module = require('module')
707+
const originalLoader = Module._load
708+
Module._load = function (request: string, parent: any) {
709+
const found = findConfigPath(request, baseUrl, paths)
710+
if (found) { arguments[0] = found }
711+
return originalLoader.apply(this, arguments)
712+
}
713+
714+
}

0 commit comments

Comments
 (0)