Skip to content

Instantly share code, notes, and snippets.

@danielweck
Last active November 11, 2022 08:38
Show Gist options
  • Save danielweck/cd63af8e9a8b3492abacc312af9f28fd to your computer and use it in GitHub Desktop.
Save danielweck/cd63af8e9a8b3492abacc312af9f28fd to your computer and use it in GitHub Desktop.
ESLint import resolver for ESM modules via package.json exports map
module.exports = {
settings: {
// optionally, if TypeScript project:
// 'import/parsers': {
// '@typescript-eslint/parser': ['.ts', '.tsx'],
// },
'import/resolver': {
// optionally, if TypeScript project:
// https://github.com/alexgorbatchev/eslint-import-resolver-typescript
// typescript: {
// alwaysTryTypes: false,
// project: ['./PATH/TO/tsconfig.json'],
// },
[path.resolve('./eslint-plugin-import-resolver.js')]: { someConfig: 1 },
},
},
},
const path = require('path');
const { resolve: resolveExports } = require('resolve.exports');
// optionally handle NodeJS built-ins just in case not handled by another ESLint module resolver in the chain
const { builtinModules } = require('module');
const builtins = new Set(builtinModules);
/**
* @param {string} source source
* @param {string} file file
* @param {Object} _config config
*/
const resolve = (source, file, _config) => {
if (builtins.has(source)) {
// return { found: false }; // this also works?
return { found: true, path: null };
}
try {
const moduleId = require.resolve(source, { paths: [path.dirname(file)] });
return { found: true, path: moduleId };
} catch (/** @type {any} */ err) {
if (err.code === 'MODULE_NOT_FOUND' && err.path?.endsWith('/package.json')) {
const { name, module, main, exports } = require(err.path);
const resolved = resolveExports({ name, module, main, exports }, source);
const moduleId = path.join(path.dirname(err.path), resolved);
return { found: true, path: moduleId };
}
return { found: false };
}
};
module.exports = {
interfaceVersion: 2,
resolve,
};
@k7sleeper
Copy link

Thanks for that solution.

I had to change the following line:

const possibleBuildinModuleId = moduleId.startsWith('node:') ? moduleId.slice(5) : moduleId;
if (builtinModules.includes(possibleBuildinModuleId)) {
   return { found: false };
}

@k7sleeper
Copy link

Nevertheless, I get the following error:

 build-scripts\create-run-env\index.js:25:8
  ✖  25:8  Relative imports from parent directories are not allowed. Please either pass what you're importing through at runtime (dependency injection), move index.js to same directory as #build-scripts/constants.js or consider making #build-scripts/constants.js a package.  import/no-relative-parent-imports

  1 error

So, this solution does not cooperate with rule import/no-relative-parent-imports

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment