index.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const memoize = require("./util/memoize");
  7. /** @typedef {import("./CachedInputFileSystem").BaseFileSystem} BaseFileSystem */
  8. /** @typedef {import("./PnpPlugin").PnpApiImpl} PnpApi */
  9. /** @typedef {import("./Resolver")} Resolver */
  10. /** @typedef {import("./Resolver").Context} Context */
  11. /** @typedef {import("./Resolver").FileSystem} FileSystem */
  12. /** @typedef {import("./Resolver").ResolveCallback} ResolveCallback */
  13. /** @typedef {import("./Resolver").ResolveContext} ResolveContext */
  14. /** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
  15. /** @typedef {import("./Resolver").SyncFileSystem} SyncFileSystem */
  16. /** @typedef {import("./ResolverFactory").Plugin} Plugin */
  17. /** @typedef {import("./ResolverFactory").UserResolveOptions} ResolveOptions */
  18. /**
  19. * @typedef {{
  20. * (context: Context, path: string, request: string, resolveContext: ResolveContext, callback: ResolveCallback): void,
  21. * (context: Context, path: string, request: string, callback: ResolveCallback): void,
  22. * (path: string, request: string, resolveContext: ResolveContext, callback: ResolveCallback): void,
  23. * (path: string, request: string, callback: ResolveCallback): void,
  24. * }} ResolveFunctionAsync
  25. */
  26. /**
  27. * @typedef {{
  28. * (context: Context, path: string, request: string): string | false,
  29. * (path: string, request: string): string | false,
  30. * }} ResolveFunction
  31. */
  32. const getCachedFileSystem = memoize(() => require("./CachedInputFileSystem"));
  33. const getNodeFileSystem = memoize(() => {
  34. const fs = require("graceful-fs");
  35. const CachedInputFileSystem = getCachedFileSystem();
  36. return new CachedInputFileSystem(fs, 4000);
  37. });
  38. const getNodeContext = memoize(() => ({
  39. environments: ["node+es3+es5+process+native"],
  40. }));
  41. const getResolverFactory = memoize(() => require("./ResolverFactory"));
  42. const getAsyncResolver = memoize(() =>
  43. getResolverFactory().createResolver({
  44. conditionNames: ["node"],
  45. extensions: [".js", ".json", ".node"],
  46. fileSystem: getNodeFileSystem(),
  47. }),
  48. );
  49. /**
  50. * @type {ResolveFunctionAsync}
  51. */
  52. const resolve =
  53. /**
  54. * @param {object | string} context context
  55. * @param {string} path path
  56. * @param {string | ResolveContext | ResolveCallback} request request
  57. * @param {ResolveContext | ResolveCallback=} resolveContext resolve context
  58. * @param {ResolveCallback=} callback callback
  59. */
  60. (context, path, request, resolveContext, callback) => {
  61. if (typeof context === "string") {
  62. callback = /** @type {ResolveCallback} */ (resolveContext);
  63. resolveContext = /** @type {ResolveContext} */ (request);
  64. request = path;
  65. path = context;
  66. context = getNodeContext();
  67. }
  68. if (typeof callback !== "function") {
  69. callback = /** @type {ResolveCallback} */ (resolveContext);
  70. }
  71. getAsyncResolver().resolve(
  72. context,
  73. path,
  74. /** @type {string} */ (request),
  75. /** @type {ResolveContext} */ (resolveContext),
  76. /** @type {ResolveCallback} */ (callback),
  77. );
  78. };
  79. const getSyncResolver = memoize(() =>
  80. getResolverFactory().createResolver({
  81. conditionNames: ["node"],
  82. extensions: [".js", ".json", ".node"],
  83. useSyncFileSystemCalls: true,
  84. fileSystem: getNodeFileSystem(),
  85. }),
  86. );
  87. /**
  88. * @type {ResolveFunction}
  89. */
  90. const resolveSync =
  91. /**
  92. * @param {object | string} context context
  93. * @param {string} path path
  94. * @param {string=} request request
  95. * @returns {string | false} result
  96. */
  97. (context, path, request) => {
  98. if (typeof context === "string") {
  99. request = path;
  100. path = context;
  101. context = getNodeContext();
  102. }
  103. return getSyncResolver().resolveSync(
  104. context,
  105. path,
  106. /** @type {string} */ (request),
  107. );
  108. };
  109. /** @typedef {Omit<ResolveOptions, "fileSystem"> & Partial<Pick<ResolveOptions, "fileSystem">>} ResolveOptionsOptionalFS */
  110. /**
  111. * @param {ResolveOptionsOptionalFS} options Resolver options
  112. * @returns {ResolveFunctionAsync} Resolver function
  113. */
  114. function create(options) {
  115. const resolver = getResolverFactory().createResolver({
  116. fileSystem: getNodeFileSystem(),
  117. ...options,
  118. });
  119. /**
  120. * @param {object | string} context Custom context
  121. * @param {string} path Base path
  122. * @param {string | ResolveContext | ResolveCallback} request String to resolve
  123. * @param {ResolveContext | ResolveCallback=} resolveContext Resolve context
  124. * @param {ResolveCallback=} callback Result callback
  125. */
  126. return function create(context, path, request, resolveContext, callback) {
  127. if (typeof context === "string") {
  128. callback = /** @type {ResolveCallback} */ (resolveContext);
  129. resolveContext = /** @type {ResolveContext} */ (request);
  130. request = path;
  131. path = context;
  132. context = getNodeContext();
  133. }
  134. if (typeof callback !== "function") {
  135. callback = /** @type {ResolveCallback} */ (resolveContext);
  136. }
  137. resolver.resolve(
  138. context,
  139. path,
  140. /** @type {string} */ (request),
  141. /** @type {ResolveContext} */ (resolveContext),
  142. callback,
  143. );
  144. };
  145. }
  146. /**
  147. * @param {ResolveOptionsOptionalFS} options Resolver options
  148. * @returns {ResolveFunction} Resolver function
  149. */
  150. function createSync(options) {
  151. const resolver = getResolverFactory().createResolver({
  152. useSyncFileSystemCalls: true,
  153. fileSystem: getNodeFileSystem(),
  154. ...options,
  155. });
  156. /**
  157. * @param {object | string} context custom context
  158. * @param {string} path base path
  159. * @param {string=} request request to resolve
  160. * @returns {string | false} Resolved path or false
  161. */
  162. return function createSync(context, path, request) {
  163. if (typeof context === "string") {
  164. request = path;
  165. path = context;
  166. context = getNodeContext();
  167. }
  168. return resolver.resolveSync(context, path, /** @type {string} */ (request));
  169. };
  170. }
  171. /**
  172. * @template A
  173. * @template B
  174. * @param {A} obj input a
  175. * @param {B} exports input b
  176. * @returns {A & B} merged
  177. */
  178. const mergeExports = (obj, exports) => {
  179. const descriptors = Object.getOwnPropertyDescriptors(exports);
  180. Object.defineProperties(obj, descriptors);
  181. return /** @type {A & B} */ (Object.freeze(obj));
  182. };
  183. module.exports = mergeExports(resolve, {
  184. get sync() {
  185. return resolveSync;
  186. },
  187. create: mergeExports(create, {
  188. get sync() {
  189. return createSync;
  190. },
  191. }),
  192. get ResolverFactory() {
  193. return getResolverFactory();
  194. },
  195. get CachedInputFileSystem() {
  196. return getCachedFileSystem();
  197. },
  198. get CloneBasenamePlugin() {
  199. return require("./CloneBasenamePlugin");
  200. },
  201. get LogInfoPlugin() {
  202. return require("./LogInfoPlugin");
  203. },
  204. get TsconfigPathsPlugin() {
  205. return require("./TsconfigPathsPlugin");
  206. },
  207. get forEachBail() {
  208. return require("./forEachBail");
  209. },
  210. });