Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: properly load index.js ES modules (cont) #417

Merged
merged 11 commits into from May 18, 2022
50 changes: 41 additions & 9 deletions src/module-loader.ts
Expand Up @@ -139,16 +139,28 @@ export default class ModuleLoader {
} catch {
filePath = Config.tsPath(config.root, modulePath)

// Try all supported extensions.
if (!fs.existsSync(filePath)) {
// eslint-disable-next-line camelcase
for (const extension of s_EXTENSIONS) {
const testPath = `${filePath}${extension}`

if (fs.existsSync(testPath)) {
filePath = testPath
break
let fileExists = false
let isDirectory = false
if (fs.existsSync(filePath)) {
fileExists = true
try {
if (fs.lstatSync(filePath)?.isDirectory?.()) {
fileExists = false
isDirectory = true
}
} catch {}
}

if (!fileExists) {
// Try all supported extensions.
let foundPath = ModuleLoader.findFile(filePath)
if (!foundPath && isDirectory) {
// Since filePath is a directory, try looking for index.js file.
foundPath = ModuleLoader.findFile(path.join(filePath, 'index'))
}

if (foundPath) {
filePath = foundPath
}
}

Expand All @@ -157,4 +169,24 @@ export default class ModuleLoader {

return {isESM, filePath}
}

/**
* Try adding the different extensions from `s_EXTENSIONS` to find the file.
*
* @param {string} filePath - File path to load.
*
* @returns {string | null} Modified file path including extension or null if file is not found.
*/
static findFile(filePath: string) : string | null {
// eslint-disable-next-line camelcase
for (const extension of s_EXTENSIONS) {
const testPath = `${filePath}${extension}`

if (fs.existsSync(testPath)) {
return testPath
}
}

return null
}
}
3 changes: 3 additions & 0 deletions test/module-loader/fixtures/esm/index/js/index.js
@@ -0,0 +1,3 @@
export default 'SUCCESS'

export const namedExport = 'SUCCESS_NAMED'
3 changes: 3 additions & 0 deletions test/module-loader/fixtures/esm/index/mjs/index.mjs
@@ -0,0 +1,3 @@
export default 'SUCCESS'

export const namedExport = 'SUCCESS_NAMED'
17 changes: 17 additions & 0 deletions test/module-loader/module-loader.test.ts
Expand Up @@ -118,6 +118,23 @@ const data = {
isESM: false,
},

// Directory / ESM source file with .js extension. Loads package.json in './test/module-loader/fixtures/esm/' for getPackageType check.
{
path: './test/module-loader/fixtures/esm/index/js',
defaultModule: '{"default":"SUCCESS","namedExport":"SUCCESS_NAMED"}',
filePath: `${path.resolve('./test/module-loader/fixtures/esm/index/js/index.js')}`,
isESM: true,
isESMOverride: false, // With no extension `ModuleLoader.isPathModule` will return CJS
},
// Directory / ESM source file with .mjs extension. Loads package.json in './test/module-loader/fixtures/esm/' for getPackageType check.
{
path: './test/module-loader/fixtures/esm/index/mjs',
defaultModule: '{"default":"SUCCESS","namedExport":"SUCCESS_NAMED"}',
filePath: `${path.resolve('./test/module-loader/fixtures/esm/index/mjs/index.mjs')}`,
isESM: true,
isESMOverride: false, // With no extension `ModuleLoader.isPathModule` will return CJS
},

// CJS NPM module; just check that it loads as CJS.
{
path: 'eslint',
Expand Down