@jsenv/node-esm-resolution 0.0.2 → 0.0.6

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.
package/main.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { applyNodeEsmResolution } from "./src/node_esm_resolution.js"
2
2
  export { determineModuleSystem } from "./src/determine_module_system.js"
3
3
  export { applyFileSystemMagicResolution } from "./src/filesystem_magic_resolution.js"
4
- export { lookupPackageScope } from "./src/lookup_package_scope.js"
5
- export { readPackageJson } from "./src/read_package_json.js"
4
+ export { defaultLookupPackageScope } from "./src/default_lookup_package_scope.js"
5
+ export { defaultReadPackageJson } from "./src/default_read_package_json.js"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/node-esm-resolution",
3
- "version": "0.0.2",
3
+ "version": "0.0.6",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -2,7 +2,7 @@ import { existsSync } from "node:fs"
2
2
 
3
3
  import { getParentUrl, asDirectoryUrl } from "./url_utils.js"
4
4
 
5
- export const lookupPackageScope = (url) => {
5
+ export const defaultLookupPackageScope = (url) => {
6
6
  let scopeUrl = asDirectoryUrl(url)
7
7
  while (scopeUrl !== "file:///") {
8
8
  if (scopeUrl.endsWith("node_modules/")) {
@@ -1,6 +1,6 @@
1
1
  import { readFileSync } from "node:fs"
2
2
 
3
- export const readPackageJson = (packageUrl) => {
3
+ export const defaultReadPackageJson = (packageUrl) => {
4
4
  const packageJsonUrl = new URL("package.json", packageUrl)
5
5
  const buffer = readFileSync(packageJsonUrl)
6
6
  const string = String(buffer)
@@ -1,5 +1,5 @@
1
- import { lookupPackageScope } from "./lookup_package_scope.js"
2
- import { readPackageJson } from "./read_package_json.js"
1
+ import { defaultLookupPackageScope } from "./default_lookup_package_scope.js"
2
+ import { defaultReadPackageJson } from "./default_read_package_json.js"
3
3
 
4
4
  // https://nodejs.org/dist/latest-v16.x/docs/api/packages.html#packages_determining_module_system)
5
5
  export const determineModuleSystem = (
@@ -26,20 +26,21 @@ export const determineModuleSystem = (
26
26
  return "commonjs"
27
27
  }
28
28
  if (extension === ".json") {
29
- return "json"
29
+ return "url"
30
30
  }
31
31
  if (ambiguousExtensions.includes(extension)) {
32
- const packageUrl = lookupPackageScope(url)
32
+ const packageUrl = defaultLookupPackageScope(url)
33
33
  if (!packageUrl) {
34
34
  return "commonjs"
35
35
  }
36
- const packageJson = readPackageJson(packageUrl)
36
+ const packageJson = defaultReadPackageJson(packageUrl)
37
37
  if (packageJson.type === "module") {
38
38
  return "module"
39
39
  }
40
40
  return "commonjs"
41
41
  }
42
- throw new Error("unsupported file extension")
42
+ return "url"
43
+ // throw new Error(`unsupported file extension (${extension})`)
43
44
  }
44
45
 
45
46
  const extensionFromUrl = (url) => {
@@ -12,8 +12,8 @@
12
12
  import { existsSync, readFileSync } from "node:fs"
13
13
 
14
14
  import { isSpecifierForNodeBuiltin } from "./node_builtin_specifiers.js"
15
- import { lookupPackageScope } from "./lookup_package_scope.js"
16
- import { readPackageJson } from "./read_package_json.js"
15
+ import { defaultLookupPackageScope } from "./default_lookup_package_scope.js"
16
+ import { defaultReadPackageJson } from "./default_read_package_json.js"
17
17
  import { getParentUrl, isValidUrl } from "./url_utils.js"
18
18
  import {
19
19
  createInvalidModuleSpecifierError,
@@ -27,11 +27,15 @@ export const applyNodeEsmResolution = ({
27
27
  conditions = ["node", "import"],
28
28
  parentUrl,
29
29
  specifier,
30
+ lookupPackageScope = defaultLookupPackageScope,
31
+ readPackageJson = defaultReadPackageJson,
30
32
  }) => {
31
33
  const resolution = applyPackageSpecifierResolution({
32
34
  conditions,
33
35
  parentUrl: String(parentUrl),
34
36
  specifier,
37
+ lookupPackageScope,
38
+ readPackageJson,
35
39
  })
36
40
  const { url } = resolution
37
41
  if (url.startsWith("file:")) {
@@ -51,6 +55,8 @@ const applyPackageSpecifierResolution = ({
51
55
  conditions,
52
56
  parentUrl,
53
57
  specifier,
58
+ lookupPackageScope,
59
+ readPackageJson,
54
60
  }) => {
55
61
  // relative specifier
56
62
  if (
@@ -63,6 +69,8 @@ const applyPackageSpecifierResolution = ({
63
69
  conditions,
64
70
  parentUrl,
65
71
  specifier,
72
+ lookupPackageScope,
73
+ readPackageJson,
66
74
  })
67
75
  if (browserFieldResolution) {
68
76
  return browserFieldResolution
@@ -78,6 +86,8 @@ const applyPackageSpecifierResolution = ({
78
86
  conditions,
79
87
  parentUrl,
80
88
  specifier,
89
+ lookupPackageScope,
90
+ readPackageJson,
81
91
  })
82
92
  }
83
93
  try {
@@ -92,6 +102,8 @@ const applyPackageSpecifierResolution = ({
92
102
  conditions,
93
103
  parentUrl,
94
104
  packageSpecifier: specifier,
105
+ lookupPackageScope,
106
+ readPackageJson,
95
107
  })
96
108
  if (browserFieldResolution) {
97
109
  return browserFieldResolution
@@ -100,11 +112,19 @@ const applyPackageSpecifierResolution = ({
100
112
  conditions,
101
113
  parentUrl,
102
114
  packageSpecifier: specifier,
115
+ lookupPackageScope,
116
+ readPackageJson,
103
117
  })
104
118
  }
105
119
  }
106
120
 
107
- const applyBrowserFieldResolution = ({ conditions, parentUrl, specifier }) => {
121
+ const applyBrowserFieldResolution = ({
122
+ conditions,
123
+ parentUrl,
124
+ packageSpecifier,
125
+ lookupPackageScope,
126
+ readPackageJson,
127
+ }) => {
108
128
  const browserCondition = conditions.includes("browser")
109
129
  if (!browserCondition) {
110
130
  return null
@@ -125,22 +145,24 @@ const applyBrowserFieldResolution = ({ conditions, parentUrl, specifier }) => {
125
145
  return null
126
146
  }
127
147
  let url
128
- if (specifier.startsWith(".")) {
129
- const specifierUrl = new URL(specifier, parentUrl).href
130
- const specifierRelativeToPackage = specifierUrl.slice(packageUrl.length)
131
- const specifierRelativeNotation = `./${specifierRelativeToPackage}`
132
- const browserMapping = browser[specifierRelativeNotation]
148
+ if (packageSpecifier.startsWith(".")) {
149
+ const packageSpecifierUrl = new URL(packageSpecifier, parentUrl).href
150
+ const packageSpecifierRelativeUrl = packageSpecifierUrl.slice(
151
+ packageUrl.length,
152
+ )
153
+ const packageSpecifierRelativeNotation = `./${packageSpecifierRelativeUrl}`
154
+ const browserMapping = browser[packageSpecifierRelativeNotation]
133
155
  if (typeof browserMapping === "string") {
134
156
  url = new URL(browserMapping, packageUrl).href
135
157
  } else if (browserMapping === false) {
136
- url = `file:///@ignore/${specifierUrl.slice("file:///")}`
158
+ url = `file:///@ignore/${packageSpecifierUrl.slice("file:///")}`
137
159
  }
138
160
  } else {
139
- const browserMapping = browser[specifier]
161
+ const browserMapping = browser[packageSpecifier]
140
162
  if (typeof browserMapping === "string") {
141
163
  url = new URL(browserMapping, packageUrl).href
142
164
  } else if (browserMapping === false) {
143
- url = `file:///@ignore/${specifier}`
165
+ url = `file:///@ignore/${packageSpecifier}`
144
166
  }
145
167
  }
146
168
  if (url) {
@@ -158,6 +180,8 @@ const applyPackageImportsResolution = ({
158
180
  conditions,
159
181
  parentUrl,
160
182
  specifier,
183
+ lookupPackageScope,
184
+ readPackageJson,
161
185
  }) => {
162
186
  if (!specifier.startsWith("#")) {
163
187
  throw createInvalidModuleSpecifierError({
@@ -186,6 +210,8 @@ const applyPackageImportsResolution = ({
186
210
  matchObject: imports,
187
211
  matchKey: specifier,
188
212
  isImports: true,
213
+ lookupPackageScope,
214
+ readPackageJson,
189
215
  })
190
216
  if (resolved) {
191
217
  return resolved
@@ -199,7 +225,13 @@ const applyPackageImportsResolution = ({
199
225
  })
200
226
  }
201
227
 
202
- const applyPackageResolve = ({ conditions, parentUrl, packageSpecifier }) => {
228
+ const applyPackageResolve = ({
229
+ conditions,
230
+ parentUrl,
231
+ packageSpecifier,
232
+ lookupPackageScope,
233
+ readPackageJson,
234
+ }) => {
203
235
  if (packageSpecifier === "") {
204
236
  throw new Error("invalid module specifier")
205
237
  }
@@ -233,6 +265,8 @@ const applyPackageResolve = ({ conditions, parentUrl, packageSpecifier }) => {
233
265
  parentUrl,
234
266
  packageName,
235
267
  packageSubpath,
268
+ lookupPackageScope,
269
+ readPackageJson,
236
270
  })
237
271
  if (selfResolution) {
238
272
  return selfResolution
@@ -255,6 +289,8 @@ const applyPackageResolve = ({ conditions, parentUrl, packageSpecifier }) => {
255
289
  packageJson,
256
290
  packageSubpath,
257
291
  exports,
292
+ lookupPackageScope,
293
+ readPackageJson,
258
294
  })
259
295
  }
260
296
  }
@@ -264,6 +300,8 @@ const applyPackageResolve = ({ conditions, parentUrl, packageSpecifier }) => {
264
300
  packageUrl,
265
301
  packageJson,
266
302
  packageSubpath,
303
+ lookupPackageScope,
304
+ readPackageJson,
267
305
  })
268
306
  }
269
307
  throw createModuleNotFoundError({
@@ -277,6 +315,8 @@ const applyPackageSelfResolution = ({
277
315
  parentUrl,
278
316
  packageName,
279
317
  packageSubpath,
318
+ lookupPackageScope,
319
+ readPackageJson,
280
320
  }) => {
281
321
  const packageUrl = lookupPackageScope(parentUrl)
282
322
  if (!packageUrl) {
@@ -297,6 +337,8 @@ const applyPackageSelfResolution = ({
297
337
  packageUrl,
298
338
  packageJson,
299
339
  packageSubpath,
340
+ lookupPackageScope,
341
+ readPackageJson,
300
342
  })
301
343
  if (subpathResolution && subpathResolution.type !== "subpath") {
302
344
  return subpathResolution
@@ -310,6 +352,8 @@ const applyPackageSelfResolution = ({
310
352
  packageJson,
311
353
  packageSubpath,
312
354
  exports,
355
+ lookupPackageScope,
356
+ readPackageJson,
313
357
  })
314
358
  }
315
359
 
@@ -321,6 +365,8 @@ const applyPackageExportsResolution = ({
321
365
  packageJson,
322
366
  packageSubpath,
323
367
  exports,
368
+ lookupPackageScope,
369
+ readPackageJson,
324
370
  }) => {
325
371
  const exportsInfo = readExports({ exports, packageUrl })
326
372
  if (packageSubpath === ".") {
@@ -339,6 +385,8 @@ const applyPackageExportsResolution = ({
339
385
  packageJson,
340
386
  key: ".",
341
387
  target: mainExport,
388
+ lookupPackageScope,
389
+ readPackageJson,
342
390
  })
343
391
  if (resolved) {
344
392
  return resolved
@@ -358,6 +406,8 @@ const applyPackageExportsResolution = ({
358
406
  matchObject: exports,
359
407
  matchKey: packageSubpath,
360
408
  isImports: false,
409
+ lookupPackageScope,
410
+ readPackageJson,
361
411
  })
362
412
  if (resolved) {
363
413
  return resolved
@@ -378,6 +428,8 @@ const applyPackageImportsExportsResolution = ({
378
428
  matchObject,
379
429
  matchKey,
380
430
  isImports,
431
+ lookupPackageScope,
432
+ readPackageJson,
381
433
  }) => {
382
434
  if (!matchKey.includes("*") && matchObject.hasOwnProperty(matchKey)) {
383
435
  const target = matchObject[matchKey]
@@ -389,6 +441,8 @@ const applyPackageImportsExportsResolution = ({
389
441
  key: matchKey,
390
442
  target,
391
443
  internal: isImports,
444
+ lookupPackageScope,
445
+ readPackageJson,
392
446
  })
393
447
  }
394
448
  const expansionKeys = Object.keys(matchObject)
@@ -417,6 +471,8 @@ const applyPackageImportsExportsResolution = ({
417
471
  subpath,
418
472
  pattern: true,
419
473
  internal: isImports,
474
+ lookupPackageScope,
475
+ readPackageJson,
420
476
  })
421
477
  }
422
478
  return null
@@ -432,6 +488,8 @@ const applyPackageTargetResolution = ({
432
488
  subpath = "",
433
489
  pattern = false,
434
490
  internal = false,
491
+ lookupPackageScope,
492
+ readPackageJson,
435
493
  }) => {
436
494
  if (typeof target === "string") {
437
495
  if (pattern === false && subpath !== "" && !target.endsWith("/")) {
@@ -474,6 +532,8 @@ const applyPackageTargetResolution = ({
474
532
  packageSpecifier: pattern
475
533
  ? target.replaceAll("*", subpath)
476
534
  : `${target}${subpath}`,
535
+ lookupPackageScope,
536
+ readPackageJson,
477
537
  })
478
538
  }
479
539
  if (Array.isArray(target)) {
@@ -496,6 +556,8 @@ const applyPackageTargetResolution = ({
496
556
  subpath,
497
557
  pattern,
498
558
  internal,
559
+ lookupPackageScope,
560
+ readPackageJson,
499
561
  })
500
562
  if (resolved) {
501
563
  return resolved
@@ -534,6 +596,8 @@ const applyPackageTargetResolution = ({
534
596
  subpath,
535
597
  pattern,
536
598
  internal,
599
+ lookupPackageScope,
600
+ readPackageJson,
537
601
  })
538
602
  if (resolved) {
539
603
  return resolved
@@ -652,6 +716,8 @@ const applyLegacySubpathResolution = ({
652
716
  packageUrl,
653
717
  packageJson,
654
718
  packageSubpath,
719
+ lookupPackageScope,
720
+ readPackageJson,
655
721
  }) => {
656
722
  if (packageSubpath === ".") {
657
723
  return applyLegacyMainResolution({
@@ -664,6 +730,8 @@ const applyLegacySubpathResolution = ({
664
730
  conditions,
665
731
  parentUrl,
666
732
  specifier: packageSubpath,
733
+ lookupPackageScope,
734
+ readPackageJson,
667
735
  })
668
736
  if (browserFieldResolution) {
669
737
  return browserFieldResolution
package/src/url_utils.js CHANGED
@@ -7,6 +7,28 @@ export const asDirectoryUrl = (url) => {
7
7
  }
8
8
 
9
9
  export const getParentUrl = (url) => {
10
+ if (url.startsWith("file://")) {
11
+ // With node.js new URL('../', 'file:///C:/').href
12
+ // returns "file:///C:/" instead of "file:///"
13
+ const ressource = url.slice("file://".length)
14
+ const slashLastIndex = ressource.lastIndexOf("/")
15
+ if (slashLastIndex === -1) {
16
+ return url
17
+ }
18
+ const lastCharIndex = ressource.length - 1
19
+ if (slashLastIndex === lastCharIndex) {
20
+ const slashBeforeLastIndex = ressource.lastIndexOf(
21
+ "/",
22
+ slashLastIndex - 1,
23
+ )
24
+ if (slashBeforeLastIndex === -1) {
25
+ return url
26
+ }
27
+ return `file://${ressource.slice(0, slashBeforeLastIndex + 1)}`
28
+ }
29
+
30
+ return `file://${ressource.slice(0, slashLastIndex + 1)}`
31
+ }
10
32
  return new URL(url.endsWith("/") ? "../" : "./", url).href
11
33
  }
12
34