index.js 6.3 KB

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