@flex-development/mlly 1.0.0-alpha.8 → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (332) hide show
  1. package/CHANGELOG.md +1128 -355
  2. package/README.md +1540 -12
  3. package/dist/index.d.mts +3 -4
  4. package/dist/index.mjs +5 -5
  5. package/dist/interfaces/aliases.d.mts +21 -0
  6. package/dist/interfaces/condition-map.d.mts +24 -0
  7. package/dist/interfaces/file-system.d.mts +29 -0
  8. package/dist/interfaces/get-source-context.d.mts +44 -0
  9. package/dist/interfaces/get-source-options.d.mts +48 -0
  10. package/dist/interfaces/index.d.mts +18 -21
  11. package/dist/interfaces/is-directory.d.mts +17 -0
  12. package/dist/interfaces/is-file.d.mts +17 -0
  13. package/dist/interfaces/main-field-map.d.mts +22 -0
  14. package/dist/interfaces/module-format-map.d.mts +26 -0
  15. package/dist/interfaces/pattern-key-comparison-map.d.mts +31 -0
  16. package/dist/interfaces/protocol-map.d.mts +44 -0
  17. package/dist/interfaces/read-file.d.mts +24 -0
  18. package/dist/interfaces/realpath.d.mts +26 -0
  19. package/dist/interfaces/resolve-alias-options.d.mts +43 -0
  20. package/dist/interfaces/resolve-module-options.d.mts +79 -0
  21. package/dist/interfaces/stat.d.mts +24 -0
  22. package/dist/interfaces/stats.d.mts +23 -0
  23. package/dist/internal/chain-or-call.mjs +34 -0
  24. package/dist/internal/chars.mjs +17 -0
  25. package/dist/internal/check-invalid-segments.mjs +49 -0
  26. package/dist/internal/constant.mjs +23 -0
  27. package/dist/internal/fs.browser.mjs +42 -0
  28. package/dist/internal/fs.node.mjs +16 -0
  29. package/dist/internal/identity.mjs +23 -0
  30. package/dist/internal/invalid-package-target.mjs +36 -0
  31. package/dist/internal/invalid-subpath.mjs +37 -0
  32. package/dist/internal/is-promise.mjs +26 -0
  33. package/dist/internal/process.browser.mjs +8 -0
  34. package/dist/lib/can-parse-url.d.mts +23 -0
  35. package/dist/lib/can-parse-url.mjs +31 -0
  36. package/dist/lib/cwd.d.mts +14 -0
  37. package/dist/lib/cwd.mjs +17 -0
  38. package/dist/lib/default-conditions.d.mts +15 -0
  39. package/dist/lib/default-conditions.mjs +14 -0
  40. package/dist/lib/default-extensions.d.mts +14 -0
  41. package/dist/lib/default-extensions.mjs +29 -0
  42. package/dist/lib/default-main-fields.d.mts +14 -0
  43. package/dist/lib/default-main-fields.mjs +13 -0
  44. package/dist/lib/extension-format-map.d.mts +16 -0
  45. package/dist/lib/extension-format-map.mjs +31 -0
  46. package/dist/lib/formats.d.mts +21 -0
  47. package/dist/lib/formats.mjs +22 -0
  48. package/dist/lib/get-source.d.mts +46 -0
  49. package/dist/lib/get-source.mjs +156 -0
  50. package/dist/lib/index.d.mts +41 -0
  51. package/dist/lib/index.mjs +41 -0
  52. package/dist/lib/is-absolute-specifier.d.mts +23 -0
  53. package/dist/lib/is-absolute-specifier.mjs +34 -0
  54. package/dist/lib/is-array-index.d.mts +19 -0
  55. package/dist/lib/is-array-index.mjs +28 -0
  56. package/dist/lib/is-bare-specifier.d.mts +23 -0
  57. package/dist/lib/is-bare-specifier.mjs +33 -0
  58. package/dist/lib/is-directory.d.mts +27 -0
  59. package/dist/lib/is-directory.mjs +54 -0
  60. package/dist/lib/is-file.d.mts +27 -0
  61. package/dist/lib/is-file.mjs +54 -0
  62. package/dist/lib/is-imports-subpath.d.mts +26 -0
  63. package/dist/lib/is-imports-subpath.mjs +28 -0
  64. package/dist/lib/is-module-id.d.mts +23 -0
  65. package/dist/lib/is-module-id.mjs +24 -0
  66. package/dist/lib/is-relative-specifier.d.mts +23 -0
  67. package/dist/lib/is-relative-specifier.mjs +36 -0
  68. package/dist/lib/lookup-package-scope.d.mts +49 -0
  69. package/dist/lib/lookup-package-scope.mjs +102 -0
  70. package/dist/lib/pattern-key-compare.d.mts +28 -0
  71. package/dist/lib/pattern-key-compare.mjs +71 -0
  72. package/dist/lib/pattern-match.d.mts +22 -0
  73. package/dist/lib/pattern-match.mjs +85 -0
  74. package/dist/lib/read-package-json.d.mts +63 -0
  75. package/dist/lib/read-package-json.mjs +115 -0
  76. package/dist/lib/resolve-alias.d.mts +21 -0
  77. package/dist/lib/resolve-alias.mjs +102 -0
  78. package/dist/lib/resolve-module.d.mts +43 -0
  79. package/dist/lib/resolve-module.mjs +186 -0
  80. package/dist/lib/resolver.d.mts +346 -0
  81. package/dist/lib/resolver.mjs +1015 -0
  82. package/dist/lib/root.d.mts +11 -0
  83. package/dist/lib/root.mjs +12 -0
  84. package/dist/lib/to-relative-specifier.d.mts +27 -0
  85. package/dist/lib/to-relative-specifier.mjs +63 -0
  86. package/dist/lib/to-url.d.mts +26 -0
  87. package/dist/lib/to-url.mjs +34 -0
  88. package/dist/types/awaitable.d.mts +12 -0
  89. package/dist/types/change-ext-fn.d.mts +29 -0
  90. package/dist/types/condition.d.mts +13 -0
  91. package/dist/types/dot.d.mts +9 -0
  92. package/dist/types/empty-array.d.mts +9 -0
  93. package/dist/types/empty-object.d.mts +19 -0
  94. package/dist/types/empty-string.d.mts +9 -0
  95. package/dist/types/ext.d.mts +12 -0
  96. package/dist/types/get-source-handler.d.mts +22 -0
  97. package/dist/types/get-source-handlers.d.mts +15 -0
  98. package/dist/types/index.d.mts +19 -10
  99. package/dist/types/list.d.mts +12 -0
  100. package/dist/types/main-field.d.mts +13 -0
  101. package/dist/types/module-format.d.mts +13 -0
  102. package/dist/types/module-id.d.mts +3 -4
  103. package/dist/types/numeric.d.mts +9 -0
  104. package/dist/types/pattern-key-comparison.d.mts +14 -0
  105. package/dist/types/pattern-match.d.mts +10 -0
  106. package/dist/types/protocol.d.mts +6 -7
  107. package/package.json +151 -154
  108. package/changelog.config.ts +0 -404
  109. package/dist/enums/assert-type.d.mts +0 -21
  110. package/dist/enums/assert-type.mjs +0 -10
  111. package/dist/enums/assert-type.mjs.map +0 -6
  112. package/dist/enums/format.d.mts +0 -17
  113. package/dist/enums/format.mjs +0 -13
  114. package/dist/enums/format.mjs.map +0 -6
  115. package/dist/enums/index.d.mts +0 -10
  116. package/dist/enums/index.mjs +0 -15
  117. package/dist/enums/index.mjs.map +0 -6
  118. package/dist/enums/kind-specifier-syntax.d.mts +0 -14
  119. package/dist/enums/kind-specifier-syntax.mjs +0 -10
  120. package/dist/enums/kind-specifier-syntax.mjs.map +0 -6
  121. package/dist/enums/kind-specifier.d.mts +0 -17
  122. package/dist/enums/kind-specifier.mjs +0 -11
  123. package/dist/enums/kind-specifier.mjs.map +0 -6
  124. package/dist/enums/kind-statement-syntax.d.mts +0 -22
  125. package/dist/enums/kind-statement-syntax.mjs +0 -18
  126. package/dist/enums/kind-statement-syntax.mjs.map +0 -6
  127. package/dist/enums/kind-statement.d.mts +0 -15
  128. package/dist/enums/kind-statement.mjs +0 -11
  129. package/dist/enums/kind-statement.mjs.map +0 -6
  130. package/dist/index.mjs.map +0 -6
  131. package/dist/interfaces/import-assertions.d.mts +0 -20
  132. package/dist/interfaces/import-dynamic.d.mts +0 -43
  133. package/dist/interfaces/import-static.d.mts +0 -37
  134. package/dist/interfaces/index.mjs +0 -1
  135. package/dist/interfaces/index.mjs.map +0 -6
  136. package/dist/interfaces/options-fill-module.d.mts +0 -23
  137. package/dist/interfaces/options-find-subpath.d.mts +0 -49
  138. package/dist/interfaces/options-get-format.d.mts +0 -83
  139. package/dist/interfaces/options-get-source.d.mts +0 -63
  140. package/dist/interfaces/options-parse-module-id.d.mts +0 -33
  141. package/dist/interfaces/options-parse-subpath.d.mts +0 -31
  142. package/dist/interfaces/options-resolve-alias.d.mts +0 -53
  143. package/dist/interfaces/options-resolve-module.d.mts +0 -64
  144. package/dist/interfaces/options-resolve.d.mts +0 -15
  145. package/dist/interfaces/package-scope.d.mts +0 -25
  146. package/dist/interfaces/parsed-data-url.d.mts +0 -56
  147. package/dist/interfaces/parsed-module-id.d.mts +0 -80
  148. package/dist/interfaces/parsed-subpath.d.mts +0 -40
  149. package/dist/interfaces/statement-export.d.mts +0 -44
  150. package/dist/interfaces/statement-import.d.mts +0 -38
  151. package/dist/interfaces/statement-require.d.mts +0 -38
  152. package/dist/interfaces/statement.d.mts +0 -49
  153. package/dist/internal/escape-reg-exp.d.mts +0 -16
  154. package/dist/internal/escape-reg-exp.mjs +0 -10
  155. package/dist/internal/escape-reg-exp.mjs.map +0 -6
  156. package/dist/internal/format-type-map.d.mts +0 -17
  157. package/dist/internal/format-type-map.mjs +0 -13
  158. package/dist/internal/format-type-map.mjs.map +0 -6
  159. package/dist/internal/get-specifier-kind.d.mts +0 -17
  160. package/dist/internal/get-specifier-kind.mjs +0 -14
  161. package/dist/internal/get-specifier-kind.mjs.map +0 -6
  162. package/dist/internal/get-subpaths.d.mts +0 -25
  163. package/dist/internal/get-subpaths.mjs +0 -10
  164. package/dist/internal/get-subpaths.mjs.map +0 -6
  165. package/dist/internal/is-array-index.d.mts +0 -15
  166. package/dist/internal/is-array-index.mjs +0 -9
  167. package/dist/internal/is-array-index.mjs.map +0 -6
  168. package/dist/internal/is-directory.d.mts +0 -13
  169. package/dist/internal/is-directory.mjs +0 -16
  170. package/dist/internal/is-directory.mjs.map +0 -6
  171. package/dist/internal/is-file.d.mts +0 -13
  172. package/dist/internal/is-file.mjs +0 -16
  173. package/dist/internal/is-file.mjs.map +0 -6
  174. package/dist/internal/is-function.d.mts +0 -12
  175. package/dist/internal/is-function.mjs +0 -8
  176. package/dist/internal/is-function.mjs.map +0 -6
  177. package/dist/internal/regex-encoded-sep.d.mts +0 -13
  178. package/dist/internal/regex-encoded-sep.mjs +0 -6
  179. package/dist/internal/regex-encoded-sep.mjs.map +0 -6
  180. package/dist/internal/regex-internal-specifier.d.mts +0 -14
  181. package/dist/internal/regex-internal-specifier.mjs +0 -6
  182. package/dist/internal/regex-internal-specifier.mjs.map +0 -6
  183. package/dist/internal/regex-package-name.d.mts +0 -13
  184. package/dist/internal/regex-package-name.mjs +0 -6
  185. package/dist/internal/regex-package-name.mjs.map +0 -6
  186. package/dist/internal/regex-package-path.d.mts +0 -15
  187. package/dist/internal/regex-package-path.mjs +0 -6
  188. package/dist/internal/regex-package-path.mjs.map +0 -6
  189. package/dist/internal/resolver.d.mts +0 -130
  190. package/dist/internal/resolver.mjs +0 -486
  191. package/dist/internal/resolver.mjs.map +0 -6
  192. package/dist/internal/validate-boolean.d.mts +0 -20
  193. package/dist/internal/validate-boolean.mjs +0 -11
  194. package/dist/internal/validate-boolean.mjs.map +0 -6
  195. package/dist/internal/validate-object.d.mts +0 -23
  196. package/dist/internal/validate-object.mjs +0 -11
  197. package/dist/internal/validate-object.mjs.map +0 -6
  198. package/dist/internal/validate-set.d.mts +0 -23
  199. package/dist/internal/validate-set.mjs +0 -11
  200. package/dist/internal/validate-set.mjs.map +0 -6
  201. package/dist/internal/validate-string.d.mts +0 -20
  202. package/dist/internal/validate-string.mjs +0 -11
  203. package/dist/internal/validate-string.mjs.map +0 -6
  204. package/dist/internal/validate-url-string.d.mts +0 -22
  205. package/dist/internal/validate-url-string.mjs +0 -12
  206. package/dist/internal/validate-url-string.mjs.map +0 -6
  207. package/dist/types/declaration.d.mts +0 -9
  208. package/dist/types/fn-change-ext.d.mts +0 -28
  209. package/dist/types/index.mjs +0 -1
  210. package/dist/types/index.mjs.map +0 -6
  211. package/dist/types/mime-type.d.mts +0 -13
  212. package/dist/types/module-specifier-type.d.mts +0 -11
  213. package/dist/types/syntax-kind-export.d.mts +0 -12
  214. package/dist/types/syntax-kind-import.d.mts +0 -12
  215. package/dist/types/syntax-kind-require.d.mts +0 -12
  216. package/dist/utils/compare-subpaths.d.mts +0 -25
  217. package/dist/utils/compare-subpaths.mjs +0 -24
  218. package/dist/utils/compare-subpaths.mjs.map +0 -6
  219. package/dist/utils/conditions.d.mts +0 -13
  220. package/dist/utils/conditions.mjs +0 -6
  221. package/dist/utils/conditions.mjs.map +0 -6
  222. package/dist/utils/detect-syntax.d.mts +0 -21
  223. package/dist/utils/detect-syntax.mjs +0 -12
  224. package/dist/utils/detect-syntax.mjs.map +0 -6
  225. package/dist/utils/extension-format-map.d.mts +0 -16
  226. package/dist/utils/extension-format-map.mjs +0 -22
  227. package/dist/utils/extension-format-map.mjs.map +0 -6
  228. package/dist/utils/extract-statements.d.mts +0 -21
  229. package/dist/utils/extract-statements.mjs +0 -21
  230. package/dist/utils/extract-statements.mjs.map +0 -6
  231. package/dist/utils/fill-modules.d.mts +0 -23
  232. package/dist/utils/fill-modules.mjs +0 -62
  233. package/dist/utils/fill-modules.mjs.map +0 -6
  234. package/dist/utils/find-dynamic-imports.d.mts +0 -18
  235. package/dist/utils/find-dynamic-imports.mjs +0 -39
  236. package/dist/utils/find-dynamic-imports.mjs.map +0 -6
  237. package/dist/utils/find-exports.d.mts +0 -21
  238. package/dist/utils/find-exports.mjs +0 -95
  239. package/dist/utils/find-exports.mjs.map +0 -6
  240. package/dist/utils/find-requires.d.mts +0 -18
  241. package/dist/utils/find-requires.mjs +0 -32
  242. package/dist/utils/find-requires.mjs.map +0 -6
  243. package/dist/utils/find-static-imports.d.mts +0 -18
  244. package/dist/utils/find-static-imports.mjs +0 -34
  245. package/dist/utils/find-static-imports.mjs.map +0 -6
  246. package/dist/utils/find-subpath.d.mts +0 -30
  247. package/dist/utils/find-subpath.mjs +0 -106
  248. package/dist/utils/find-subpath.mjs.map +0 -6
  249. package/dist/utils/get-format.d.mts +0 -24
  250. package/dist/utils/get-format.mjs +0 -111
  251. package/dist/utils/get-format.mjs.map +0 -6
  252. package/dist/utils/get-source.d.mts +0 -22
  253. package/dist/utils/get-source.mjs +0 -63
  254. package/dist/utils/get-source.mjs.map +0 -6
  255. package/dist/utils/has-cjs-syntax.d.mts +0 -25
  256. package/dist/utils/has-cjs-syntax.mjs +0 -11
  257. package/dist/utils/has-cjs-syntax.mjs.map +0 -6
  258. package/dist/utils/has-esm-syntax.d.mts +0 -21
  259. package/dist/utils/has-esm-syntax.mjs +0 -11
  260. package/dist/utils/has-esm-syntax.mjs.map +0 -6
  261. package/dist/utils/index.d.mts +0 -42
  262. package/dist/utils/index.mjs +0 -79
  263. package/dist/utils/index.mjs.map +0 -6
  264. package/dist/utils/is-absolute-specifier.d.mts +0 -19
  265. package/dist/utils/is-absolute-specifier.mjs +0 -25
  266. package/dist/utils/is-absolute-specifier.mjs.map +0 -6
  267. package/dist/utils/is-bare-specifier.d.mts +0 -19
  268. package/dist/utils/is-bare-specifier.mjs +0 -10
  269. package/dist/utils/is-bare-specifier.mjs.map +0 -6
  270. package/dist/utils/is-exports-sugar.d.mts +0 -25
  271. package/dist/utils/is-exports-sugar.mjs +0 -26
  272. package/dist/utils/is-exports-sugar.mjs.map +0 -6
  273. package/dist/utils/is-relative-specifier.d.mts +0 -20
  274. package/dist/utils/is-relative-specifier.mjs +0 -11
  275. package/dist/utils/is-relative-specifier.mjs.map +0 -6
  276. package/dist/utils/lookup-package-scope.d.mts +0 -24
  277. package/dist/utils/lookup-package-scope.mjs +0 -34
  278. package/dist/utils/lookup-package-scope.mjs.map +0 -6
  279. package/dist/utils/parse-data-url.d.mts +0 -25
  280. package/dist/utils/parse-data-url.mjs +0 -25
  281. package/dist/utils/parse-data-url.mjs.map +0 -6
  282. package/dist/utils/parse-module-id.d.mts +0 -22
  283. package/dist/utils/parse-module-id.mjs +0 -122
  284. package/dist/utils/parse-module-id.mjs.map +0 -6
  285. package/dist/utils/parse-subpath.d.mts +0 -35
  286. package/dist/utils/parse-subpath.mjs +0 -54
  287. package/dist/utils/parse-subpath.mjs.map +0 -6
  288. package/dist/utils/pattern-character.d.mts +0 -11
  289. package/dist/utils/pattern-character.mjs +0 -6
  290. package/dist/utils/pattern-character.mjs.map +0 -6
  291. package/dist/utils/read-package-json.d.mts +0 -26
  292. package/dist/utils/read-package-json.mjs +0 -43
  293. package/dist/utils/read-package-json.mjs.map +0 -6
  294. package/dist/utils/resolve-alias.d.mts +0 -20
  295. package/dist/utils/resolve-alias.mjs +0 -106
  296. package/dist/utils/resolve-alias.mjs.map +0 -6
  297. package/dist/utils/resolve-aliases.d.mts +0 -19
  298. package/dist/utils/resolve-aliases.mjs +0 -28
  299. package/dist/utils/resolve-aliases.mjs.map +0 -6
  300. package/dist/utils/resolve-extensions.d.mts +0 -14
  301. package/dist/utils/resolve-extensions.mjs +0 -22
  302. package/dist/utils/resolve-extensions.mjs.map +0 -6
  303. package/dist/utils/resolve-module.d.mts +0 -39
  304. package/dist/utils/resolve-module.mjs +0 -64
  305. package/dist/utils/resolve-module.mjs.map +0 -6
  306. package/dist/utils/resolve-modules.d.mts +0 -25
  307. package/dist/utils/resolve-modules.mjs +0 -26
  308. package/dist/utils/resolve-modules.mjs.map +0 -6
  309. package/dist/utils/to-absolute-specifier.d.mts +0 -22
  310. package/dist/utils/to-absolute-specifier.mjs +0 -8
  311. package/dist/utils/to-absolute-specifier.mjs.map +0 -6
  312. package/dist/utils/to-bare-specifier.d.mts +0 -42
  313. package/dist/utils/to-bare-specifier.mjs +0 -90
  314. package/dist/utils/to-bare-specifier.mjs.map +0 -6
  315. package/dist/utils/to-data-url.d.mts +0 -30
  316. package/dist/utils/to-data-url.mjs +0 -11
  317. package/dist/utils/to-data-url.mjs.map +0 -6
  318. package/dist/utils/to-node-url.d.mts +0 -19
  319. package/dist/utils/to-node-url.mjs +0 -10
  320. package/dist/utils/to-node-url.mjs.map +0 -6
  321. package/dist/utils/to-relative-specifier.d.mts +0 -22
  322. package/dist/utils/to-relative-specifier.mjs +0 -21
  323. package/dist/utils/to-relative-specifier.mjs.map +0 -6
  324. package/dist/utils/to-url.d.mts +0 -22
  325. package/dist/utils/to-url.mjs +0 -12
  326. package/dist/utils/to-url.mjs.map +0 -6
  327. package/dist/utils/validate-assertions.d.mts +0 -23
  328. package/dist/utils/validate-assertions.mjs +0 -52
  329. package/dist/utils/validate-assertions.mjs.map +0 -6
  330. package/dist/utils/validate-exports.d.mts +0 -24
  331. package/dist/utils/validate-exports.mjs +0 -72
  332. package/dist/utils/validate-exports.mjs.map +0 -6
@@ -0,0 +1,1015 @@
1
+ /**
2
+ * @file resolver
3
+ * @module mlly/lib/resolver
4
+ */
5
+ import chainOrCall from '#internal/chain-or-call';
6
+ import chars from '#internal/chars';
7
+ import checkInvalidSegments from '#internal/check-invalid-segments';
8
+ import constant from '#internal/constant';
9
+ import dfs from '#internal/fs';
10
+ import identity from '#internal/identity';
11
+ import invalidPackageTarget from '#internal/invalid-package-target';
12
+ import invalidSubpath from '#internal/invalid-subpath';
13
+ import isPromise from '#internal/is-promise';
14
+ import canParseUrl from '#lib/can-parse-url';
15
+ import defaultConditions from '#lib/default-conditions';
16
+ import defaultMainFields from '#lib/default-main-fields';
17
+ import isArrayIndex from '#lib/is-array-index';
18
+ import isDirectory from '#lib/is-directory';
19
+ import isFile from '#lib/is-file';
20
+ import isImportsSubpath from '#lib/is-imports-subpath';
21
+ import isModuleId from '#lib/is-module-id';
22
+ import isRelativeSpecifier from '#lib/is-relative-specifier';
23
+ import lookupPackageScope from '#lib/lookup-package-scope';
24
+ import patternMatch from '#lib/pattern-match';
25
+ import readPackageJson from '#lib/read-package-json';
26
+ import root from '#lib/root';
27
+ import toUrl from '#lib/to-url';
28
+ import { codes, ERR_INVALID_MODULE_SPECIFIER, ERR_INVALID_PACKAGE_CONFIG, ERR_MODULE_NOT_FOUND, ERR_PACKAGE_IMPORT_NOT_DEFINED, ERR_PACKAGE_PATH_NOT_EXPORTED, ERR_UNSUPPORTED_DIR_IMPORT, ERR_UNSUPPORTED_RESOLVE_REQUEST } from '@flex-development/errnode';
29
+ import { isBuiltin } from '@flex-development/is-builtin';
30
+ import pathe from '@flex-development/pathe';
31
+ import { ok } from 'devlop';
32
+ export { legacyMainResolve, moduleResolve, packageExportsResolve, packageImportsExportsResolve, packageImportsResolve, packageResolve, packageSelfResolve, packageTargetResolve };
33
+ /**
34
+ * Resolve a [`main`][main]-like package entry point.
35
+ *
36
+ * Implements the `LEGACY_MAIN_RESOLVE` algorithm.
37
+ *
38
+ * > 👉 **Note**: Returns a promise if `fs.stat` is async.
39
+ *
40
+ * [main]: https://github.com/nodejs/node/blob/v22.9.0/doc/api/packages.md#main
41
+ *
42
+ * @see {@linkcode Awaitable}
43
+ * @see {@linkcode ErrModuleNotFound}
44
+ * @see {@linkcode FileSystem}
45
+ * @see {@linkcode List}
46
+ * @see {@linkcode MainField}
47
+ * @see {@linkcode ModuleId}
48
+ * @see {@linkcode PackageJson}
49
+ *
50
+ * @this {void}
51
+ *
52
+ * @param {ModuleId} packageUrl
53
+ * The URL of the package directory, the `package.json` file,
54
+ * or a module in the same directory as a `package.json`
55
+ * @param {PackageJson | null | undefined} [manifest]
56
+ * The package manifest
57
+ * @param {List<MainField> | null | undefined} [mainFields]
58
+ * The list of legacy main fields
59
+ * @param {ModuleId | null | undefined} [parent]
60
+ * The URL of the parent module
61
+ * @param {FileSystem | null | undefined} [fs]
62
+ * The file system API
63
+ * @return {Awaitable<URL>}
64
+ * The resolved entry point URL
65
+ * @throws {ErrModuleNotFound}
66
+ * If the entry point cannot be resolved
67
+ */
68
+ function legacyMainResolve(packageUrl, manifest, mainFields, parent, fs) {
69
+ if (manifest) {
70
+ /**
71
+ * The promise context.
72
+ *
73
+ * > 👉 **Note**: Only used if {@linkcode isFile} returns a promise.
74
+ *
75
+ * @const {{ scope: URL | null }} context
76
+ */
77
+ const context = { url: null };
78
+ /**
79
+ * The promises to resolve.
80
+ *
81
+ * > 👉 **Note**: Only used if {@linkcode isFile} returns a promise.
82
+ *
83
+ * @const {Awaitable<undefined>[]} promises
84
+ */
85
+ const promises = [];
86
+ for (const mainField of mainFields ?? defaultMainFields) {
87
+ /**
88
+ * The main field value.
89
+ *
90
+ * @const {JsonValue | undefined} value
91
+ */
92
+ const mainFieldValue = manifest[mainField];
93
+ /**
94
+ * Possible inputs for the entry point URL.
95
+ *
96
+ * @const {string[]} tries
97
+ */
98
+ const tries = [];
99
+ /**
100
+ * Whether the current try exists.
101
+ *
102
+ * @var {Awaitable<boolean>} exists
103
+ */
104
+ let exists;
105
+ if (typeof mainFieldValue === 'string') {
106
+ tries.push(mainFieldValue, `./${mainFieldValue}.js`, `./${mainFieldValue}.json`, `./${mainFieldValue}.node`, `./${mainFieldValue}/index.js`, `./${mainFieldValue}/index.json`, `./${mainFieldValue}/index.node`);
107
+ }
108
+ tries.push('./index.js', './index.json', './index.node');
109
+ for (const url of tries.map(input => new URL(input, packageUrl))) {
110
+ exists = isFile(url, fs); // check if entry point exists.
111
+ // collect promises, or return url if entry point exists.
112
+ if (isPromise(exists)) {
113
+ promises.push(exists.then(isFile => {
114
+ if (!isFile || context.url)
115
+ return;
116
+ return context.url = url, void 0;
117
+ }));
118
+ }
119
+ else if (exists && !promises.length) {
120
+ return url;
121
+ }
122
+ }
123
+ }
124
+ // resolve entry point url.
125
+ if (promises.length) {
126
+ return Promise.all(promises).then(() => check(context.url));
127
+ }
128
+ }
129
+ return check(null);
130
+ /**
131
+ * @this {void}
132
+ *
133
+ * @param {URL | null} url
134
+ * The url to check
135
+ * @return {URL}
136
+ * The resolved entry point URL
137
+ * @throws {ErrModuleNotFound}
138
+ */
139
+ function check(url) {
140
+ if (url)
141
+ return url;
142
+ throw new ERR_MODULE_NOT_FOUND(pathe.fileURLToPath(packageUrl), parent && pathe.fileURLToPath(parent));
143
+ }
144
+ }
145
+ /**
146
+ * Resolve a module `specifier`.
147
+ *
148
+ * Implements the `ESM_RESOLVE` algorithm.
149
+ *
150
+ * > 👉 **Note**: Returns a promise if `fs.realpath` or `fs.stat` is async,
151
+ * > or one of the following methods returns a promise:
152
+ * > {@linkcode packageImportsResolve}, {@linkcode packageResolve}.
153
+ *
154
+ * @see {@linkcode Awaitable}
155
+ * @see {@linkcode Condition}
156
+ * @see {@linkcode ErrInvalidModuleSpecifier}
157
+ * @see {@linkcode ErrModuleNotFound}
158
+ * @see {@linkcode ErrUnsupportedDirImport}
159
+ * @see {@linkcode FileSystem}
160
+ * @see {@linkcode List}
161
+ * @see {@linkcode ModuleId}
162
+ *
163
+ * @this {void}
164
+ *
165
+ * @param {string} specifier
166
+ * The module specifier to resolve
167
+ * @param {ModuleId} parent
168
+ * The URL of the parent module
169
+ * @param {List<Condition> | null | undefined} [conditions]
170
+ * The list of export/import conditions
171
+ * @param {List<MainField> | null | undefined} [mainFields]
172
+ * The list of legacy main fields
173
+ * @param {boolean | null | undefined} [preserveSymlinks]
174
+ * Whether to keep symlinks instead of resolving them
175
+ * @param {FileSystem | null | undefined} [fs]
176
+ * The file system API
177
+ * @return {Awaitable<URL>}
178
+ * The resolved URL
179
+ * @throws {ErrInvalidModuleSpecifier}
180
+ * @throws {ErrModuleNotFound}
181
+ * @throws {ErrUnsupportedDirImport}
182
+ */
183
+ function moduleResolve(specifier, parent, conditions, mainFields, preserveSymlinks, fs) {
184
+ /**
185
+ * The URL protocol of the parent module.
186
+ *
187
+ * @const {string} parentProtocol
188
+ */
189
+ const parentProtocol = typeof parent === 'string'
190
+ ? parent.slice(0, parent.indexOf(':') + 1)
191
+ : parent.protocol;
192
+ /**
193
+ * The resolved URL.
194
+ *
195
+ * @var {Awaitable<URL>} resolved
196
+ */
197
+ let resolved;
198
+ if (pathe.isAbsolute(specifier) || isRelativeSpecifier(specifier)) {
199
+ try {
200
+ resolved = new URL(specifier, parent);
201
+ }
202
+ catch (e) {
203
+ /**
204
+ * The node error.
205
+ *
206
+ * @var {ErrUnsupportedResolveRequest} error
207
+ */
208
+ let error;
209
+ error = new ERR_UNSUPPORTED_RESOLVE_REQUEST(specifier, parent);
210
+ error.cause = e;
211
+ throw error;
212
+ }
213
+ }
214
+ else if (parentProtocol === 'file:' && isImportsSubpath(specifier)) {
215
+ resolved = packageImportsResolve(specifier, parent, conditions, mainFields, fs);
216
+ }
217
+ else {
218
+ try {
219
+ resolved = new URL(specifier);
220
+ }
221
+ catch (e) {
222
+ if (parentProtocol === 'data:' && !isBuiltin(specifier)) {
223
+ /**
224
+ * The node error.
225
+ *
226
+ * @var {ErrUnsupportedResolveRequest} error
227
+ */
228
+ let error;
229
+ error = new ERR_UNSUPPORTED_RESOLVE_REQUEST(String(specifier), parent);
230
+ error.cause = e;
231
+ throw error;
232
+ }
233
+ resolved = packageResolve(specifier, parent, conditions, mainFields, fs);
234
+ }
235
+ }
236
+ if (isPromise(resolved)) {
237
+ void resolved.then(url => (resolved = url), constant(null));
238
+ }
239
+ return chainOrCall(resolved, () => {
240
+ ok(isModuleId(resolved), 'expected `resolved` to be a URL');
241
+ if (resolved.protocol !== 'file:')
242
+ return resolved;
243
+ /**
244
+ * The path to the parent module.
245
+ *
246
+ * @const {string} parentPath
247
+ */
248
+ const parentPath = pathe.fileURLToPath(parent);
249
+ /**
250
+ * The resolved URL.
251
+ *
252
+ * @var {URL} url
253
+ */
254
+ let url = resolved;
255
+ // check for encoded separators.
256
+ if (/%2f|%5c/i.test(url.pathname)) {
257
+ /**
258
+ * The reason for the invalid module specifier error.
259
+ *
260
+ * @const {string} reason
261
+ */
262
+ const reason = 'must not include encoded "/" or "\\" characters';
263
+ throw new ERR_INVALID_MODULE_SPECIFIER(url.pathname, reason, parentPath);
264
+ }
265
+ /**
266
+ * Whether the resolved URL points to a directory.
267
+ *
268
+ * @const {Awaitable<boolean>} directory
269
+ */
270
+ const directory = isDirectory(url, fs);
271
+ return chainOrCall(directory, (isDirectory) => {
272
+ if (isDirectory ?? directory) {
273
+ /**
274
+ * The node error.
275
+ *
276
+ * @var {ErrUnsupportedDirImport} error
277
+ */
278
+ let error;
279
+ error = new ERR_UNSUPPORTED_DIR_IMPORT(url.pathname, parentPath);
280
+ error.url = String(url);
281
+ throw error;
282
+ }
283
+ /**
284
+ * Whether the resolved URL points to a file.
285
+ *
286
+ * @const {Awaitable<boolean>} file
287
+ */
288
+ const file = isFile(url, fs);
289
+ return chainOrCall(file, (isFile) => {
290
+ if (isFile ?? file) {
291
+ if (preserveSymlinks)
292
+ return url;
293
+ /**
294
+ * The canonical pathname of the resolved URL.
295
+ *
296
+ * @const {Awaitable<string>} canonical
297
+ */
298
+ const canonical = (fs ?? dfs).realpath(url);
299
+ return chainOrCall(canonical, (realpath) => {
300
+ const { hash, search } = url;
301
+ url = new URL(pathe.pathToFileURL(realpath ?? canonical));
302
+ return url.hash = hash, url.search = search, url;
303
+ });
304
+ }
305
+ throw new ERR_MODULE_NOT_FOUND(url.pathname, parentPath, url);
306
+ });
307
+ });
308
+ });
309
+ }
310
+ /**
311
+ * Resolve a package export.
312
+ *
313
+ * Implements the `PACKAGE_EXPORTS_RESOLVE` algorithm.
314
+ *
315
+ * > 👉 **Note**: Never returns a promise.
316
+ *
317
+ * @see {@linkcode Awaitable}
318
+ * @see {@linkcode Condition}
319
+ * @see {@linkcode ErrInvalidPackageConfig}
320
+ * @see {@linkcode ErrPackagePathNotExported}
321
+ * @see {@linkcode Exports}
322
+ * @see {@linkcode FileSystem}
323
+ * @see {@linkcode Imports}
324
+ * @see {@linkcode List}
325
+ * @see {@linkcode ModuleId}
326
+ *
327
+ * @this {void}
328
+ *
329
+ * @param {ModuleId} packageUrl
330
+ * The URL of the package directory, the `package.json` file,
331
+ * or a module in the same directory as a `package.json`
332
+ * @param {string} subpath
333
+ * The package subpath
334
+ * @param {Exports | undefined} exports
335
+ * The package exports
336
+ * @param {List<Condition> | null | undefined} [conditions]
337
+ * The list of export/import conditions
338
+ * @param {ModuleId | null | undefined} [parent]
339
+ * The URL of the parent module
340
+ * @param {FileSystem | null | undefined} [fs]
341
+ * The file system API
342
+ * @return {Awaitable<URL>}
343
+ * The resolved package export URL
344
+ * @throws {ErrInvalidPackageConfig}
345
+ * @throws {ErrPackagePathNotExported}
346
+ */
347
+ function packageExportsResolve(packageUrl, subpath, exports, conditions, parent, fs) {
348
+ if (exports) {
349
+ /**
350
+ * Whether all keys in {@linkcode exports} must begin with a dot (`'.'`).
351
+ *
352
+ * @var {boolean} dot
353
+ */
354
+ let dot = false;
355
+ if (!Array.isArray(exports) && typeof exports === 'object') {
356
+ for (const [i, key] of Object.getOwnPropertyNames(exports).entries()) {
357
+ /**
358
+ * Whether the current {@linkcode exports} object key
359
+ * begins with a dot (`'.'`).
360
+ *
361
+ * @var {boolean} dotStart
362
+ */
363
+ let dotStart = key[0] === pathe.dot;
364
+ if (i === 0) {
365
+ dot = dotStart;
366
+ continue;
367
+ }
368
+ // `exports` can contain all conditions or subpaths, but not both.
369
+ if (dot !== dotStart) {
370
+ throw new ERR_INVALID_PACKAGE_CONFIG(pathe.fileURLToPath(new URL('package.json', packageUrl)), parent, `"exports" cannot contain some keys starting with '.' and some not. The exports object must either be an object of package subpath keys or an object of main entry condition name keys only.`);
371
+ }
372
+ }
373
+ }
374
+ /**
375
+ * The resolved URL.
376
+ *
377
+ * > 👉 **Note**: {@linkcode packageTargetResolve}, called both
378
+ * > directly and indirectly below, only only returns a promise
379
+ * > if {@linkcode packageResolve} also returns a promise.
380
+ * > `packageResolve` is only called, however, when resolving imports.
381
+ *
382
+ * @var {URL | null | undefined} resolved
383
+ */
384
+ let resolved = null;
385
+ // resolve main entry point or package subpath.
386
+ if (subpath === pathe.dot) {
387
+ /**
388
+ * The main export.
389
+ *
390
+ * @var {Exports | undefined} mainExport
391
+ */
392
+ let mainExport;
393
+ if (Array.isArray(exports) || typeof exports === 'string' || !dot) {
394
+ mainExport = exports;
395
+ }
396
+ else if (Object.prototype.hasOwnProperty.call(exports, subpath)) {
397
+ mainExport = exports[subpath];
398
+ }
399
+ if (mainExport !== undefined) {
400
+ resolved = packageTargetResolve(packageUrl, mainExport, subpath, null, false, conditions, null, parent, fs);
401
+ }
402
+ }
403
+ else if (!Array.isArray(exports) && typeof exports === 'object' && dot) {
404
+ ok(subpath.startsWith('./'), 'expected `subpath` to start with "./"');
405
+ resolved = packageImportsExportsResolve(subpath, exports, packageUrl, false, conditions, null, parent, fs);
406
+ }
407
+ ok(!isPromise(resolved), 'expected `resolved` not to be a promise');
408
+ if (resolved)
409
+ return resolved;
410
+ }
411
+ throw new ERR_PACKAGE_PATH_NOT_EXPORTED(pathe.fileURLToPath(packageUrl), subpath, parent && pathe.fileURLToPath(parent));
412
+ }
413
+ /**
414
+ * Resolve a package export or import.
415
+ *
416
+ * Implements the `PACKAGE_IMPORTS_EXPORTS_RESOLVE` algorithm.
417
+ *
418
+ * > 👉 **Note**: Returns a promise if {@linkcode packageTargetResolve}
419
+ * > returns a promise.
420
+ *
421
+ * @see {@linkcode Awaitable}
422
+ * @see {@linkcode Condition}
423
+ * @see {@linkcode ExportsObject}
424
+ * @see {@linkcode FileSystem}
425
+ * @see {@linkcode Imports}
426
+ * @see {@linkcode List}
427
+ * @see {@linkcode ModuleId}
428
+ *
429
+ * @this {void}
430
+ *
431
+ * @param {string} matchKey
432
+ * The package subpath extracted from a module specifier,
433
+ * or a dot character (`.`)
434
+ * @param {ExportsObject | Imports | null | undefined} matchObject
435
+ * The package exports or imports
436
+ * @param {ModuleId} packageUrl
437
+ * The URL of the directory containing the `package.json` file
438
+ * @param {boolean | null | undefined} [isImports]
439
+ * Whether `matchObject` is internal to the package
440
+ * @param {List<Condition> | null | undefined} [conditions]
441
+ * The list of export/import conditions
442
+ * @param {List<MainField> | null | undefined} [mainFields]
443
+ * The list of legacy main fields
444
+ * @param {ModuleId | null | undefined} [parent]
445
+ * The URL of the parent module
446
+ * @param {FileSystem | null | undefined} [fs]
447
+ * The file system API
448
+ * @return {Awaitable<URL | null | undefined>}
449
+ * The resolved package export or import URL
450
+ */
451
+ function packageImportsExportsResolve(matchKey, matchObject, packageUrl, isImports, conditions, mainFields, parent, fs) {
452
+ /**
453
+ * The expansion key and subpath pattern match.
454
+ *
455
+ * @const {PatternMatch | null} match
456
+ */
457
+ const match = patternMatch(matchKey, matchObject);
458
+ if (!match)
459
+ return match;
460
+ ok(matchObject, 'expected `matchObject`');
461
+ return packageTargetResolve(packageUrl, matchObject[match[0]], ...match, isImports, conditions, mainFields, parent, fs);
462
+ }
463
+ /**
464
+ * Resolve a package import.
465
+ *
466
+ * Implements the `PACKAGE_IMPORTS_RESOLVE` algorithm.
467
+ *
468
+ * > 👉 **Note**: Returns a promise if {@linkcode lookupPackageScope},
469
+ * > {@linkcode packageImportsExportsResolve}, or {@linkcode readPackageJson}
470
+ * > returns a promise.
471
+ *
472
+ * @see {@linkcode Awaitable}
473
+ * @see {@linkcode Condition}
474
+ * @see {@linkcode ErrInvalidModuleSpecifier}
475
+ * @see {@linkcode ErrPackageImportNotDefined}
476
+ * @see {@linkcode FileSystem}
477
+ * @see {@linkcode List}
478
+ * @see {@linkcode ModuleId}
479
+ *
480
+ * @this {void}
481
+ *
482
+ * @param {string} specifier
483
+ * The import specifier to resolve
484
+ * @param {ModuleId} parent
485
+ * The URL of the parent module
486
+ * @param {List<Condition> | null | undefined} [conditions]
487
+ * The list of export/import conditions
488
+ * @param {List<MainField> | null | undefined} [mainFields]
489
+ * The list of legacy main fields
490
+ * @param {FileSystem | null | undefined} [fs]
491
+ * The file system API
492
+ * @return {Awaitable<URL>}
493
+ * The resolved package import URL
494
+ * @throws {ErrInvalidModuleSpecifier}
495
+ * @throws {ErrPackageImportNotDefined}
496
+ */
497
+ function packageImportsResolve(specifier, parent, conditions, mainFields, fs) {
498
+ if (!specifier.startsWith(chars.hash) ||
499
+ specifier === chars.hash ||
500
+ specifier.startsWith(chars.hash + pathe.sep)) {
501
+ throw new ERR_INVALID_MODULE_SPECIFIER(specifier, 'is not a valid internal imports specifier name', pathe.fileURLToPath(parent));
502
+ }
503
+ /**
504
+ * The package scope URL.
505
+ *
506
+ * @var {Awaitable<URL | null>} scope
507
+ */
508
+ let scope = lookupPackageScope(parent, null, fs);
509
+ // capture resolved scope url.
510
+ if (isPromise(scope)) {
511
+ void scope.then(resolved => (scope = resolved), constant(null));
512
+ }
513
+ return chainOrCall(scope, () => {
514
+ ok(!isPromise(scope), 'expected `scope` to be resolved');
515
+ /**
516
+ * The package manifest.
517
+ *
518
+ * @const {Awaitable<PackageJson | null>} pjson
519
+ */
520
+ const pjson = readPackageJson(scope, specifier, parent, fs);
521
+ return chainOrCall(pjson, (pkg) => {
522
+ if ((pkg = pkg === undefined ? pjson : pkg)) {
523
+ ok(scope instanceof URL, 'expected `scope` to be a URL');
524
+ /**
525
+ * The resolved URL.
526
+ *
527
+ * @var {Awaitable<URL | null | undefined>} url
528
+ */
529
+ let url;
530
+ url = packageImportsExportsResolve(specifier, pkg.imports, scope, true, conditions, mainFields, parent, fs);
531
+ if (isPromise(url))
532
+ return url.then(check);
533
+ if (url)
534
+ return url;
535
+ }
536
+ return check(null);
537
+ });
538
+ /**
539
+ * @this {void}
540
+ *
541
+ * @param {URL | null | undefined} url
542
+ * The url to check
543
+ * @return {URL}
544
+ * The resolved URL
545
+ * @throws {ErrPackagePathNotExported}
546
+ */
547
+ function check(url) {
548
+ ok(!isPromise(scope), 'expected `scope` to be resolved');
549
+ if (url)
550
+ return url;
551
+ throw new ERR_PACKAGE_IMPORT_NOT_DEFINED(specifier, scope && pathe.fileURLToPath(scope), parent && pathe.fileURLToPath(parent));
552
+ }
553
+ });
554
+ }
555
+ /**
556
+ * Resolve a *bare specifier*.
557
+ *
558
+ * Implements the `PACKAGE_RESOLVE` algorithm.
559
+ *
560
+ * > *Bare specifiers* like `'some-package'` or `'some-package/shuffle'` refer
561
+ * > to the main entry point of a package by package name, or a specific feature
562
+ * > module within a package prefixed by the package name. Including the file
563
+ * > extension is only necessary for packages without an [`"exports"`][exports]
564
+ * > field.
565
+ *
566
+ * > 👉 **Note**: Returns a promise if `fs.stat` is async or one of the
567
+ * > following methods returns a promise: {@linkcode legacyMainResolve},
568
+ * > {@linkcode packageExportsResolve}, {@linkcode packageSelfResolve},
569
+ * > {@linkcode readPackageJson}.
570
+ *
571
+ * [exports]: https://nodejs.org/api/packages.html#exports
572
+ *
573
+ * @see {@linkcode Awaitable}
574
+ * @see {@linkcode Condition}
575
+ * @see {@linkcode ErrInvalidModuleSpecifier}
576
+ * @see {@linkcode ErrModuleNotFound}
577
+ * @see {@linkcode FileSystem}
578
+ * @see {@linkcode List}
579
+ * @see {@linkcode MainField}
580
+ * @see {@linkcode ModuleId}
581
+ *
582
+ * @this {void}
583
+ *
584
+ * @param {string} specifier
585
+ * The package specifier
586
+ * @param {ModuleId} parent
587
+ * The URL of the parent module
588
+ * @param {List<Condition> | null | undefined} [conditions]
589
+ * The list of export conditions
590
+ * @param {List<MainField> | null | undefined} [mainFields]
591
+ * The list of legacy main fields
592
+ * @param {FileSystem | null | undefined} [fs]
593
+ * The file system API
594
+ * @return {Awaitable<URL>}
595
+ * The resolved package URL
596
+ * @throws {ErrInvalidModuleSpecifier}
597
+ * @throws {ErrModuleNotFound}
598
+ */
599
+ function packageResolve(specifier, parent, conditions, mainFields, fs) {
600
+ if (isBuiltin(specifier))
601
+ return toUrl(specifier);
602
+ /**
603
+ * Index of separator in {@linkcode specifier}.
604
+ *
605
+ * @var {number} separatorIndex
606
+ */
607
+ let separatorIndex = specifier.indexOf(pathe.sep);
608
+ /**
609
+ * Whether the package name is valid.
610
+ *
611
+ * @var {boolean} validPackageName
612
+ */
613
+ let validPackageName = !!specifier;
614
+ if (specifier[0] === chars.at) {
615
+ if (separatorIndex === -1) {
616
+ validPackageName = false;
617
+ }
618
+ else {
619
+ separatorIndex = specifier.indexOf(pathe.sep, separatorIndex + 1);
620
+ }
621
+ }
622
+ /**
623
+ * The package name.
624
+ *
625
+ * @const {string} packageName
626
+ */
627
+ const packageName = separatorIndex === -1
628
+ ? specifier
629
+ : specifier.slice(0, separatorIndex);
630
+ // package names cannot start with dot characters.
631
+ // they also cannot contain percent-encoded or \\ (`\`) separators.
632
+ if (/^\.|%|\\/.exec(packageName) !== null)
633
+ validPackageName = false;
634
+ // throw on invalid package name.
635
+ if (!validPackageName) {
636
+ /**
637
+ * The reason for the invalid specifier error.
638
+ *
639
+ * @const {string} reason
640
+ */
641
+ const reason = 'is not a valid package name';
642
+ throw new ERR_INVALID_MODULE_SPECIFIER(specifier, reason, parent);
643
+ }
644
+ /**
645
+ * The package subpath.
646
+ *
647
+ * @const {string} packageSubpath
648
+ */
649
+ const packageSubpath = pathe.dot + (separatorIndex === -1
650
+ ? chars.empty
651
+ : specifier.slice(separatorIndex));
652
+ /**
653
+ * The resolved self-import URL.
654
+ *
655
+ * @var {Awaitable<URL | undefined>} self
656
+ */
657
+ let self = packageSelfResolve(packageName, packageSubpath, parent, conditions, fs);
658
+ // capture resolved self-import url.
659
+ if (isPromise(self)) {
660
+ void self.then(resolved => (self = resolved), constant(null));
661
+ }
662
+ return chainOrCall(self, () => {
663
+ ok(!isPromise(self), 'expected `self` to be resolved');
664
+ if (self)
665
+ return self;
666
+ /**
667
+ * The promise context.
668
+ *
669
+ * > 👉 **Note**: Only used if {@linkcode isDirectory} returns a promise.
670
+ *
671
+ * @const {{ url: Awaitable<URL | null> }} context
672
+ */
673
+ const context = { url: null };
674
+ /**
675
+ * The promises to resolve.
676
+ *
677
+ * > 👉 **Note**: Only used if {@linkcode isDirectory} returns a promise.
678
+ *
679
+ * @const {Awaitable<undefined>[]} promises
680
+ */
681
+ const promises = [];
682
+ /**
683
+ * Whether the current package directory exists.
684
+ *
685
+ * @var {Awaitable<boolean>} exists
686
+ */
687
+ let exists;
688
+ /**
689
+ * The URL of the parent module.
690
+ *
691
+ * @var {URL} parentUrl
692
+ */
693
+ let parentUrl = new URL(parent);
694
+ while (String(parentUrl) !== String(root)) {
695
+ /**
696
+ * The URL of the package directory.
697
+ *
698
+ * @const {URL} scope
699
+ */
700
+ const scope = new URL(`node_modules/${packageName}/`, parentUrl);
701
+ // check if package directory exists.
702
+ exists = isDirectory(scope, fs);
703
+ // chain `isDirectory` promises,
704
+ // or return resolved url if package directory exists.
705
+ if (isPromise(exists)) {
706
+ promises.push(exists.then(isDirectory => {
707
+ if (!isDirectory || context.url)
708
+ return;
709
+ return context.url = resolve(scope), void 0;
710
+ }));
711
+ }
712
+ else if (exists) {
713
+ return resolve(scope);
714
+ }
715
+ // move onto next package directory.
716
+ parentUrl = new URL(pathe.dirname(parentUrl.href));
717
+ }
718
+ if (promises.length) {
719
+ return chainOrCall(Promise.all(promises), () => {
720
+ if (isPromise(context.url))
721
+ return context.url.then(check);
722
+ return check(context.url);
723
+ });
724
+ }
725
+ return check(null);
726
+ });
727
+ /**
728
+ * @this {void}
729
+ *
730
+ * @param {URL | null} url
731
+ * The url to check
732
+ * @return {URL}
733
+ * The resolved URL
734
+ * @throws {ErrModuleNotFound}
735
+ */
736
+ function check(url) {
737
+ if (url)
738
+ return url;
739
+ throw new ERR_MODULE_NOT_FOUND(packageName, parent && pathe.fileURLToPath(parent));
740
+ }
741
+ /**
742
+ * @this {void}
743
+ *
744
+ * @param {URL} packageUrl
745
+ * The URL of the package directory
746
+ * @return {Awaitable<URL>}
747
+ * The resolved URL
748
+ */
749
+ function resolve(packageUrl) {
750
+ /**
751
+ * The package manifest.
752
+ *
753
+ * @var {Awaitable<PackageJson | null>} pjson
754
+ */
755
+ let pjson = readPackageJson(packageUrl, null, parent, fs);
756
+ if (isPromise(pjson)) {
757
+ void pjson.then(resolved => (pjson = resolved), constant(null));
758
+ }
759
+ return chainOrCall(pjson, () => {
760
+ ok(!isPromise(pjson), 'expected `pjson` to be resolved');
761
+ if (pjson?.exports) {
762
+ return packageExportsResolve(packageUrl, packageSubpath, pjson.exports, conditions, parent, fs);
763
+ }
764
+ if (packageSubpath !== pathe.dot) {
765
+ return new URL(packageSubpath, packageUrl);
766
+ }
767
+ return legacyMainResolve(packageUrl, pjson, mainFields, parent, fs);
768
+ });
769
+ }
770
+ }
771
+ /**
772
+ * Resolve the self-import of a package.
773
+ *
774
+ * Implements the `PACKAGE_SELF_RESOLVE` algorithm.
775
+ *
776
+ * > 👉 **Note**: Returns a promise if {@linkcode lookupPackageScope},
777
+ * > {@linkcode packageExportsResolve}, or {@linkcode readPackageJson}
778
+ * > returns a promise.
779
+ *
780
+ * @see {@linkcode Awaitable}
781
+ * @see {@linkcode Condition}
782
+ * @see {@linkcode FileSystem}
783
+ * @see {@linkcode List}
784
+ * @see {@linkcode ModuleId}
785
+ *
786
+ * @this {void}
787
+ *
788
+ * @param {string} name
789
+ * The package name
790
+ * @param {string} subpath
791
+ * The package subpath
792
+ * @param {ModuleId} parent
793
+ * The URL of the parent module
794
+ * @param {List<Condition> | null | undefined} [conditions]
795
+ * The list of export conditions
796
+ * @param {FileSystem | null | undefined} [fs]
797
+ * The file system API
798
+ * @return {Awaitable<URL | undefined>}
799
+ * The resolved package URL
800
+ */
801
+ function packageSelfResolve(name, subpath, parent, conditions, fs) {
802
+ /**
803
+ * The URL of the package directory.
804
+ *
805
+ * @const {Awaitable<URL | null>} packageUrl
806
+ */
807
+ const packageUrl = lookupPackageScope(parent, null, fs);
808
+ return chainOrCall(packageUrl, scope => {
809
+ /**
810
+ * The package manifest.
811
+ *
812
+ * @const {Awaitable<PackageJson | null>} pjson
813
+ */
814
+ const pjson = readPackageJson(scope = scope === undefined ? packageUrl : scope, null, parent, fs);
815
+ return chainOrCall(pjson, pkg => {
816
+ if (pkg === undefined)
817
+ pkg = pjson;
818
+ if (pkg?.exports && name === pkg.name) {
819
+ return ok(scope, 'expected `scope`'), packageExportsResolve(scope, subpath, pkg.exports, conditions, parent, fs);
820
+ }
821
+ return undefined;
822
+ });
823
+ });
824
+ }
825
+ /**
826
+ * Resolve a package target.
827
+ *
828
+ * Implements the `PACKAGE_TARGET_RESOLVE` algorithm.
829
+ *
830
+ * > 👉 **Note**: Returns a promise if `target` is internal to the package and
831
+ * > {@linkcode packageResolve} returns a promise.
832
+ *
833
+ * @see {@linkcode Awaitable}
834
+ * @see {@linkcode Condition}
835
+ * @see {@linkcode ErrInvalidPackageConfig}
836
+ * @see {@linkcode ErrInvalidPackageTarget}
837
+ * @see {@linkcode FileSystem}
838
+ * @see {@linkcode List}
839
+ * @see {@linkcode ModuleId}
840
+ * @see {@linkcode Target}
841
+ *
842
+ * @this {void}
843
+ *
844
+ * @param {ModuleId} packageUrl
845
+ * The URL of the directory containing the `package.json` file
846
+ * @param {unknown} target
847
+ * The package target (i.e. a `exports`/`imports` value)
848
+ * @param {string} subpath
849
+ * The package subpath (i.e. a `exports`/`imports` key)
850
+ * @param {string | null | undefined} [patternMatch]
851
+ * The `subpath` pattern match
852
+ * @param {boolean | null | undefined} [isImports]
853
+ * Whether `target` is internal to the package
854
+ * @param {List<Condition> | null | undefined} [conditions]
855
+ * The list of export/import conditions
856
+ * @param {List<MainField> | null | undefined} [mainFields]
857
+ * The list of legacy main fields
858
+ * @param {ModuleId | null | undefined} [parent]
859
+ * The URL of the parent module
860
+ * @param {FileSystem | null | undefined} [fs]
861
+ * The file system API
862
+ * @return {Awaitable<URL | null | undefined>}
863
+ * The resolved package target URL
864
+ * @throws {ErrInvalidPackageConfig}
865
+ * @throws {ErrInvalidPackageTarget}
866
+ */
867
+ function packageTargetResolve(packageUrl, target, subpath, patternMatch, isImports, conditions, mainFields, parent, fs) {
868
+ if (target === null)
869
+ return target;
870
+ if (Array.isArray(target)) {
871
+ /**
872
+ * The promises to resolve.
873
+ *
874
+ * > 👉 **Note**: Only used if {@linkcode packageResolve} return a promise.
875
+ *
876
+ * @const {Awaitable<NodeError | URL | null | undefined>[]} promises
877
+ */
878
+ const promises = [];
879
+ /**
880
+ * The last node error.
881
+ *
882
+ * @var {NodeError | null} error
883
+ */
884
+ let error;
885
+ /**
886
+ * The resolved URL.
887
+ *
888
+ * @var {Awaitable<URL | null | undefined>} resolved
889
+ */
890
+ let resolved;
891
+ for (const targetValue of target) {
892
+ try {
893
+ resolved = packageTargetResolve(packageUrl, targetValue, subpath, patternMatch, isImports, conditions, mainFields, parent, fs);
894
+ }
895
+ catch (e) {
896
+ error = e;
897
+ if (error.code !== codes.ERR_INVALID_PACKAGE_TARGET)
898
+ throw error;
899
+ }
900
+ // collect promises, or return resolved url.
901
+ if (isPromise(resolved)) {
902
+ // no need to check for `ERR_INVALID_PACKAGE_TARGET`.
903
+ // the only resolver method that throws it is `packageTargetResolve`.
904
+ // `packageResolve` is the only resolver method that can reach here,
905
+ // and it throws a different error when a url cannot be resolved.
906
+ promises.push(resolved.then(identity, identity));
907
+ }
908
+ else if (resolved && !promises.length) {
909
+ return resolved;
910
+ }
911
+ }
912
+ // resolve package target url.
913
+ if (promises.length) {
914
+ return error = null, Promise.all(promises).then(resolved => {
915
+ // `packageResolve` is the only resolver method that can reach here.
916
+ // it throws when a url cannot be resolved, so this function will
917
+ // always return a url or throw an error.
918
+ for (const url of resolved) {
919
+ if (isModuleId(url))
920
+ return url; // resolved package target.
921
+ /* v8 ignore else -- @preserve */ if (url)
922
+ error = url;
923
+ }
924
+ /* v8 ignore else -- @preserve */ if (error)
925
+ throw error;
926
+ /* v8 ignore next -- @preserve */ return null;
927
+ });
928
+ }
929
+ if (error)
930
+ throw error;
931
+ return null;
932
+ }
933
+ if (typeof target === 'object') {
934
+ // ensure `target` does not contain any numeric property keys.
935
+ for (const key of Object.getOwnPropertyNames(target)) {
936
+ if (isArrayIndex(key)) {
937
+ throw new ERR_INVALID_PACKAGE_CONFIG(pathe.fileURLToPath(new URL('package.json', packageUrl)), parent, '"exports" cannot contain numeric property keys');
938
+ }
939
+ }
940
+ conditions ??= defaultConditions;
941
+ if (Array.isArray(conditions))
942
+ conditions = new Set(conditions);
943
+ /**
944
+ * The promises to resolve.
945
+ *
946
+ * > 👉 **Note**: Only used if any function calls return a promise.
947
+ *
948
+ * @const {Awaitable<URL | null | undefined>[]} promises
949
+ */
950
+ const promises = [];
951
+ /**
952
+ * The resolved URL.
953
+ *
954
+ * @var {Awaitable<URL | null | undefined>} resolved
955
+ */
956
+ let resolved;
957
+ // try resolving conditional target.
958
+ for (const key of Object.getOwnPropertyNames(target)) {
959
+ if (conditions.has(key) || key === 'default') {
960
+ resolved = packageTargetResolve(packageUrl, target[key], subpath, patternMatch, isImports, conditions, mainFields, parent, fs);
961
+ // collect promises, or return resolved url.
962
+ if (isPromise(resolved)) {
963
+ promises.push(resolved.then(identity));
964
+ }
965
+ else if (resolved !== undefined && !promises.length) {
966
+ return resolved;
967
+ }
968
+ }
969
+ }
970
+ // resolve package target url.
971
+ if (promises.length) {
972
+ return Promise.all(promises).then(resolved => resolved.find(url => !!url));
973
+ }
974
+ return undefined;
975
+ }
976
+ if (typeof target === 'string') {
977
+ if (!target.startsWith('./')) {
978
+ if (!isImports || // not internal import
979
+ target.startsWith('../') || // out of bounds
980
+ target.startsWith(pathe.sep) || // absolute path
981
+ canParseUrl(target) // url
982
+ ) {
983
+ throw invalidPackageTarget(packageUrl, subpath, target, isImports, parent);
984
+ }
985
+ return packageResolve(typeof patternMatch === 'string'
986
+ ? target.replace(chars.asterisk, patternMatch)
987
+ : target, packageUrl, conditions, mainFields, fs);
988
+ }
989
+ ok(target.startsWith('./'), 'expected `target` to start with "./"');
990
+ if (checkInvalidSegments(target)) {
991
+ throw invalidPackageTarget(packageUrl, subpath, target, isImports, parent);
992
+ }
993
+ /**
994
+ * The resolved URL.
995
+ *
996
+ * @var {URL} resolved
997
+ */
998
+ let resolved = new URL(target, packageUrl);
999
+ // throw if `target` resolves to module outside of package directory.
1000
+ if (!resolved.href.startsWith(String(packageUrl))) {
1001
+ throw invalidPackageTarget(packageUrl, subpath, target, isImports, parent);
1002
+ }
1003
+ // replace `chars.asterisk` in `resolved` with `patternMatch`.
1004
+ if (typeof patternMatch === 'string') {
1005
+ if (patternMatch && checkInvalidSegments(patternMatch)) {
1006
+ throw invalidSubpath(subpath, patternMatch, packageUrl, isImports, parent);
1007
+ }
1008
+ target = target.replace(chars.asterisk, patternMatch);
1009
+ ok(typeof target === 'string', 'expected string `target`');
1010
+ resolved = new URL(target, packageUrl);
1011
+ }
1012
+ return resolved;
1013
+ }
1014
+ throw invalidPackageTarget(packageUrl, subpath, target, isImports, parent);
1015
+ }