resolveSilent.mjs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import fs from 'node:fs';
  2. import path from 'node:path';
  3. import { fileURLToPath, pathToFileURL } from 'node:url';
  4. // TODO: use pure ESM `import-meta-resolve` package in next major version
  5. import { resolve } from '@dual-bundle/import-meta-resolve';
  6. import resolveFrom from 'resolve-from';
  7. /**
  8. * TODO: These suffixes are here for commonjs compatibility reason, we should remove these codes after migrating to pure ESM, because in ESM accurate paths are required
  9. */
  10. const pathSuffixes = ['', '.js', '.json', `${path.sep}index.js`, `${path.sep}index.json`];
  11. const specifierSuffixes = ['', '.js', '.json', '/index.js', '/index.json'];
  12. /**
  13. * Checks whether the given file exists as a file.
  14. * @param {string} filename The file to check.
  15. * @returns {boolean} `true` if the file exists and is a file, otherwise `false`.
  16. */
  17. function existsFile(filename) {
  18. return fs.statSync(filename, { throwIfNoEntry: false })?.isFile() ?? false;
  19. }
  20. /**
  21. * @param {string} parent
  22. * @param {string} lookup
  23. * @returns {string | undefined}
  24. */
  25. export default function resolveSilent(parent, lookup) {
  26. if (path.isAbsolute(lookup)) {
  27. for (const suffix of pathSuffixes) {
  28. const filename = lookup + suffix;
  29. if (existsFile(filename)) {
  30. return filename;
  31. }
  32. }
  33. return;
  34. }
  35. const base = pathToFileURL(path.resolve(parent, 'noop.js')).toString();
  36. for (const suffix of specifierSuffixes) {
  37. try {
  38. const resolved = fileURLToPath(resolve(lookup + suffix, base));
  39. if (existsFile(resolved)) {
  40. return resolved;
  41. }
  42. } catch {
  43. //
  44. }
  45. }
  46. /**
  47. * Yarn P'n'P does not support pure ESM well by default, this is only a workaround for it
  48. * @see https://github.com/wooorm/import-meta-resolve/issues/23
  49. *
  50. * TODO: this workaround is still necessary before native `import.meta.resolve` replacement
  51. */
  52. return resolveFrom.silent(parent, lookup);
  53. }