diff --git a/index.js b/index.js index 7a14792..bf96e65 100644 --- a/index.js +++ b/index.js @@ -25,10 +25,8 @@ function resolveFile(source, file, config) { } let foundTsPath = null; - const extensions = Object.keys(require.extensions).concat( - '.ts', - '.tsx', - '.d.ts', + const extensions = ['.ts', '.tsx', '.d.ts'].concat( + Object.keys(require.extensions), ); // setup tsconfig-paths @@ -64,6 +62,25 @@ function resolveFile(source, file, config) { foundNodePath = null; } + // naive attempt at @types/* resolution, + // if path is neither absolute nor relative + if ( + (/\.jsx?$/.test(foundNodePath) || + (config.alwaysTryTypes && !foundNodePath)) && + !/^@types[/\\]/.test(source) && + !path.isAbsolute(source) && + source[0] !== '.' + ) { + const definitelyTyped = resolveFile( + '@types' + path.sep + mangleScopedPackage(source), + file, + config, + ); + if (definitelyTyped.found) { + return definitelyTyped; + } + } + if (foundNodePath) { log('matched node path:', foundNodePath); @@ -73,19 +90,35 @@ function resolveFile(source, file, config) { }; } - log('didnt find', source); + log("didn't find", source); return { found: false, }; } + function packageFilter(pkg) { - if (pkg['jsnext:main']) { - pkg['main'] = pkg['jsnext:main']; - } + pkg.main = + pkg.types || pkg.typings || pkg.module || pkg['jsnext:main'] || pkg.main; return pkg; } +/** + * For a scoped package, we must look in `@types/foo__bar` instead of `@types/@foo/bar`. + * + * @param {string} moduleName + * @returns {string} + */ +function mangleScopedPackage(moduleName) { + if (moduleName[0] === '@') { + const replaceSlash = moduleName.replace(path.sep, '__'); + if (replaceSlash !== moduleName) { + return replaceSlash.slice(1); // Take off the "@" + } + } + return moduleName; +} + module.exports = { interfaceVersion: 2, resolve: resolveFile, diff --git a/package-lock.json b/package-lock.json index c250156..6fd093d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "eslint-import-resolver-typescript", - "version": "1.1.0", + "version": "1.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -29,6 +29,12 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" }, + "@types/unist": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", + "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", + "dev": true + }, "acorn": { "version": "5.7.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", @@ -1111,6 +1117,12 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prettier": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", + "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", + "dev": true + }, "progress": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", diff --git a/package.json b/package.json index f0f471d..c239bac 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "eslint-plugin-import": "*" }, "devDependencies": { + "@types/unist": "^2.0.3", "dummy.js": "file:dummy.js", "eslint": "^5.6.1", "eslint-plugin-import": "^2.14.0", diff --git a/tests/baseEslintConfig.js b/tests/baseEslintConfig.js index d89d048..dc61b8d 100644 --- a/tests/baseEslintConfig.js +++ b/tests/baseEslintConfig.js @@ -26,6 +26,7 @@ module.exports = dirname => ({ 'import/resolver': { [path.resolve(`${__dirname}/../index.js`)]: { directory: dirname, + alwaysTryTypes: true }, }, }, diff --git a/tests/withoutPaths/dtsImportee.d.ts b/tests/withoutPaths/dtsImportee.d.ts new file mode 100644 index 0000000..dbca419 --- /dev/null +++ b/tests/withoutPaths/dtsImportee.d.ts @@ -0,0 +1,3 @@ +declare const content : 'yes'; + +export default content; diff --git a/tests/withoutPaths/index.ts b/tests/withoutPaths/index.ts index b050f75..e612f25 100644 --- a/tests/withoutPaths/index.ts +++ b/tests/withoutPaths/index.ts @@ -1,9 +1,17 @@ // import relative import './tsImportee' import './tsxImportee' +import './dtsImportee' +import './subfolder/dtsImportee' import './subfolder/tsImportee' import './subfolder/tsxImportee' // import from node_module import 'typescript' import 'dummy.js' + +// import from `@types/` +import 'json5' + +// enable alwaysTryTypes +import 'unist' diff --git a/tests/withoutPaths/subfolder/dtsImportee.d.ts b/tests/withoutPaths/subfolder/dtsImportee.d.ts new file mode 100644 index 0000000..dbca419 --- /dev/null +++ b/tests/withoutPaths/subfolder/dtsImportee.d.ts @@ -0,0 +1,3 @@ +declare const content : 'yes'; + +export default content;