index.mjs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import fs from 'node:fs';
  2. import { createRequire } from 'node:module';
  3. import path, { dirname, join, win32 } from 'node:path';
  4. import process from 'node:process';
  5. import fsPromises from 'node:fs/promises';
  6. import { fileURLToPath } from 'node:url';
  7. import { resolvePathSync, interopDefault } from 'mlly';
  8. import { quansync } from 'quansync/macro';
  9. const toPath = urlOrPath => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
  10. async function findUp$1(name, {
  11. cwd = process.cwd(),
  12. type = 'file',
  13. stopAt,
  14. } = {}) {
  15. let directory = path.resolve(toPath(cwd) ?? '');
  16. const {root} = path.parse(directory);
  17. stopAt = path.resolve(directory, toPath(stopAt ?? root));
  18. const isAbsoluteName = path.isAbsolute(name);
  19. while (directory) {
  20. const filePath = isAbsoluteName ? name : path.join(directory, name);
  21. try {
  22. const stats = await fsPromises.stat(filePath); // eslint-disable-line no-await-in-loop
  23. if ((type === 'file' && stats.isFile()) || (type === 'directory' && stats.isDirectory())) {
  24. return filePath;
  25. }
  26. } catch {}
  27. if (directory === stopAt || directory === root) {
  28. break;
  29. }
  30. directory = path.dirname(directory);
  31. }
  32. }
  33. function findUpSync(name, {
  34. cwd = process.cwd(),
  35. type = 'file',
  36. stopAt,
  37. } = {}) {
  38. let directory = path.resolve(toPath(cwd) ?? '');
  39. const {root} = path.parse(directory);
  40. stopAt = path.resolve(directory, toPath(stopAt) ?? root);
  41. const isAbsoluteName = path.isAbsolute(name);
  42. while (directory) {
  43. const filePath = isAbsoluteName ? name : path.join(directory, name);
  44. try {
  45. const stats = fs.statSync(filePath, {throwIfNoEntry: false});
  46. if ((type === 'file' && stats?.isFile()) || (type === 'directory' && stats?.isDirectory())) {
  47. return filePath;
  48. }
  49. } catch {}
  50. if (directory === stopAt || directory === root) {
  51. break;
  52. }
  53. directory = path.dirname(directory);
  54. }
  55. }
  56. function _resolve(path, options = {}) {
  57. if (options.platform === "auto" || !options.platform)
  58. options.platform = process.platform === "win32" ? "win32" : "posix";
  59. if (process.versions.pnp) {
  60. const paths = options.paths || [];
  61. if (paths.length === 0)
  62. paths.push(process.cwd());
  63. const targetRequire = createRequire(import.meta.url);
  64. try {
  65. return targetRequire.resolve(path, { paths });
  66. } catch {
  67. }
  68. }
  69. const modulePath = resolvePathSync(path, {
  70. url: options.paths
  71. });
  72. if (options.platform === "win32")
  73. return win32.normalize(modulePath);
  74. return modulePath;
  75. }
  76. function resolveModule(name, options = {}) {
  77. try {
  78. return _resolve(name, options);
  79. } catch {
  80. return void 0;
  81. }
  82. }
  83. async function importModule(path) {
  84. const i = await import(path);
  85. if (i)
  86. return interopDefault(i);
  87. return i;
  88. }
  89. function isPackageExists(name, options = {}) {
  90. return !!resolvePackage(name, options);
  91. }
  92. function getPackageJsonPath(name, options = {}) {
  93. const entry = resolvePackage(name, options);
  94. if (!entry)
  95. return;
  96. return searchPackageJSON(entry);
  97. }
  98. const readFile = quansync({
  99. async: (id) => fs.promises.readFile(id, "utf8"),
  100. sync: (id) => fs.readFileSync(id, "utf8")
  101. });
  102. const getPackageInfo = quansync(function* (name, options = {}) {
  103. const packageJsonPath = getPackageJsonPath(name, options);
  104. if (!packageJsonPath)
  105. return;
  106. const packageJson = JSON.parse(yield readFile(packageJsonPath));
  107. return {
  108. name,
  109. version: packageJson.version,
  110. rootPath: dirname(packageJsonPath),
  111. packageJsonPath,
  112. packageJson
  113. };
  114. });
  115. const getPackageInfoSync = getPackageInfo.sync;
  116. function resolvePackage(name, options = {}) {
  117. try {
  118. return _resolve(`${name}/package.json`, options);
  119. } catch {
  120. }
  121. try {
  122. return _resolve(name, options);
  123. } catch (e) {
  124. if (e.code !== "MODULE_NOT_FOUND" && e.code !== "ERR_MODULE_NOT_FOUND")
  125. console.error(e);
  126. return false;
  127. }
  128. }
  129. function searchPackageJSON(dir) {
  130. let packageJsonPath;
  131. while (true) {
  132. if (!dir)
  133. return;
  134. const newDir = dirname(dir);
  135. if (newDir === dir)
  136. return;
  137. dir = newDir;
  138. packageJsonPath = join(dir, "package.json");
  139. if (fs.existsSync(packageJsonPath))
  140. break;
  141. }
  142. return packageJsonPath;
  143. }
  144. const findUp = quansync({
  145. sync: findUpSync,
  146. async: findUp$1
  147. });
  148. const loadPackageJSON = quansync(function* (cwd = process.cwd()) {
  149. const path = yield findUp("package.json", { cwd });
  150. if (!path || !fs.existsSync(path))
  151. return null;
  152. return JSON.parse(yield readFile(path));
  153. });
  154. const loadPackageJSONSync = loadPackageJSON.sync;
  155. const isPackageListed = quansync(function* (name, cwd) {
  156. const pkg = (yield loadPackageJSON(cwd)) || {};
  157. return name in (pkg.dependencies || {}) || name in (pkg.devDependencies || {});
  158. });
  159. const isPackageListedSync = isPackageListed.sync;
  160. export { getPackageInfo, getPackageInfoSync, importModule, isPackageExists, isPackageListed, isPackageListedSync, loadPackageJSON, loadPackageJSONSync, resolveModule };