getModuleDependencies.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. Object.defineProperty(exports, "default", {
  6. enumerable: true,
  7. get: function() {
  8. return getModuleDependencies;
  9. }
  10. });
  11. const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
  12. const _path = /*#__PURE__*/ _interop_require_default(require("path"));
  13. function _interop_require_default(obj) {
  14. return obj && obj.__esModule ? obj : {
  15. default: obj
  16. };
  17. }
  18. let jsExtensions = [
  19. ".js",
  20. ".cjs",
  21. ".mjs"
  22. ];
  23. // Given the current file `a.ts`, we want to make sure that when importing `b` that we resolve
  24. // `b.ts` before `b.js`
  25. //
  26. // E.g.:
  27. //
  28. // a.ts
  29. // b // .ts
  30. // c // .ts
  31. // a.js
  32. // b // .js or .ts
  33. let jsResolutionOrder = [
  34. "",
  35. ".js",
  36. ".cjs",
  37. ".mjs",
  38. ".ts",
  39. ".cts",
  40. ".mts",
  41. ".jsx",
  42. ".tsx"
  43. ];
  44. let tsResolutionOrder = [
  45. "",
  46. ".ts",
  47. ".cts",
  48. ".mts",
  49. ".tsx",
  50. ".js",
  51. ".cjs",
  52. ".mjs",
  53. ".jsx"
  54. ];
  55. function resolveWithExtension(file, extensions) {
  56. // Try to find `./a.ts`, `./a.ts`, ... from `./a`
  57. for (let ext of extensions){
  58. let full = `${file}${ext}`;
  59. if (_fs.default.existsSync(full) && _fs.default.statSync(full).isFile()) {
  60. return full;
  61. }
  62. }
  63. // Try to find `./a/index.js` from `./a`
  64. for (let ext of extensions){
  65. let full = `${file}/index${ext}`;
  66. if (_fs.default.existsSync(full)) {
  67. return full;
  68. }
  69. }
  70. return null;
  71. }
  72. function* _getModuleDependencies(filename, base, seen, ext = _path.default.extname(filename)) {
  73. // Try to find the file
  74. let absoluteFile = resolveWithExtension(_path.default.resolve(base, filename), jsExtensions.includes(ext) ? jsResolutionOrder : tsResolutionOrder);
  75. if (absoluteFile === null) return; // File doesn't exist
  76. // Prevent infinite loops when there are circular dependencies
  77. if (seen.has(absoluteFile)) return; // Already seen
  78. seen.add(absoluteFile);
  79. // Mark the file as a dependency
  80. yield absoluteFile;
  81. // Resolve new base for new imports/requires
  82. base = _path.default.dirname(absoluteFile);
  83. ext = _path.default.extname(absoluteFile);
  84. let contents = _fs.default.readFileSync(absoluteFile, "utf-8");
  85. // Find imports/requires
  86. for (let match of [
  87. ...contents.matchAll(/import[\s\S]*?['"](.{3,}?)['"]/gi),
  88. ...contents.matchAll(/import[\s\S]*from[\s\S]*?['"](.{3,}?)['"]/gi),
  89. ...contents.matchAll(/require\(['"`](.+)['"`]\)/gi)
  90. ]){
  91. // Bail out if it's not a relative file
  92. if (!match[1].startsWith(".")) continue;
  93. yield* _getModuleDependencies(match[1], base, seen, ext);
  94. }
  95. }
  96. function getModuleDependencies(absoluteFilePath) {
  97. if (absoluteFilePath === null) return new Set();
  98. return new Set(_getModuleDependencies(absoluteFilePath, _path.default.dirname(absoluteFilePath), new Set()));
  99. }