ts-dev
Version:
Typescript development tools
100 lines • 4.39 kB
JavaScript
import url from 'node:url';
import { dirname, relative, resolve as resolvePath } from 'node:path';
import typescript from 'typescript';
import { inspect } from 'node:util';
const escapedAsterixRe = /\\\*/g;
/**
* @author https://github.com/sindresorhus/escape-string-regexp
*/
const escapeStringRegexp = (s) => s.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d');
const configFilePath = typescript.findConfigFile('.', typescript.sys.fileExists.bind(typescript.sys));
let paths = [];
let rootDirs = [];
let rootDirsRegs = [];
let outDir = '';
if (configFilePath) {
const readConfigFileResult = typescript.parseJsonSourceFileConfigFileContent(typescript.readJsonConfigFile(configFilePath, typescript.sys.readFile.bind(typescript.sys)), typescript.sys, './');
if (readConfigFileResult.errors.length) {
throw new Error(`Unable to read project config file [${configFilePath}]. ${inspect(readConfigFileResult.errors)}`);
}
const compilerOptions = readConfigFileResult.options;
compilerOptions['configFilePath'] = configFilePath;
const configFileDir = dirname(configFilePath);
if (compilerOptions.rootDir && compilerOptions.outDir) {
const rootDir = resolvePath(configFileDir, compilerOptions.rootDir);
outDir = resolvePath(configFileDir, compilerOptions.outDir);
const baseUrl = resolvePath(configFileDir, compilerOptions.baseUrl ?? './');
if (!compilerOptions.paths) {
compilerOptions.paths = {};
}
if (!compilerOptions.rootDirs) {
compilerOptions.rootDirs = [];
}
paths = Object.entries(compilerOptions.paths).map(([k, v]) => ({
re: new RegExp(`^${escapeStringRegexp(k).replace(escapedAsterixRe, '(.*)')}$`),
paths: v.map(p => url.pathToFileURL(resolvePath(outDir, relative(rootDir, resolvePath(baseUrl, p)))).href),
}));
rootDirs = compilerOptions.rootDirs.map(p => url.pathToFileURL(resolvePath(outDir, relative(rootDir, p))).href);
rootDirsRegs = rootDirs.map(rd => new RegExp(`^(${escapeStringRegexp(rd)})(.*)$`));
}
}
const asterixRe = /\*/g;
const notBareRe = /^[./]/;
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
const isModuleNotFoundException = (e) => e.code === 'ERR_MODULE_NOT_FOUND' || e.code === 'MODULE_NOT_FOUND';
export async function resolve(specifier, context, defaultResolver) {
if (notBareRe.test(specifier)) {
try {
return await defaultResolver(specifier, context);
}
catch (e) {
if (!isModuleNotFoundException(e)) {
throw e;
}
for (const rootDirRe of rootDirsRegs) {
const res = rootDirRe.exec(context.parentURL);
if (!res) {
continue;
}
const [, base, tail] = res;
for (const rootDir of rootDirs) {
if (rootDir === base) {
continue;
}
try {
return await defaultResolver(specifier, { parentURL: `${rootDir}${tail}`, conditions: context.conditions });
}
catch (e2) {
if (isModuleNotFoundException(e2)) {
continue;
}
throw e2;
}
}
}
throw e;
}
}
else {
for (const path of paths) {
const res = path.re.exec(specifier);
if (res) {
for (const subPath of path.paths) {
const parts = res.slice(1);
const href = subPath.replace(asterixRe, () => parts.shift());
try {
return await defaultResolver(href, context);
}
catch (e) {
if (isModuleNotFoundException(e)) {
continue;
}
throw e;
}
}
}
}
}
return defaultResolver(specifier, context);
}
//# sourceMappingURL=tsLoader.js.map