import-in-the-middle 1.14.4 → 1.15.0
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/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +7 -0
- package/lib/get-exports.js +66 -3
- package/package.json +1 -1
- package/test/fixtures/nested-folder/specifier.js +1 -0
- package/test/fixtures/package.json +17 -0
- package/test/fixtures/specifier-external.js +1 -0
- package/test/fixtures/specifier-string.js +1 -0
- package/test/fixtures/specifier.mjs +1 -0
- package/test/hook/specifier-external-imports.mjs +11 -0
- package/test/hook/specifier-imports-mjs.mjs +10 -0
- package/test/hook/specifier-imports.mjs +11 -0
- package/test/hook/specifier-string-imports.mjs +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.15.0](https://github.com/nodejs/import-in-the-middle/compare/import-in-the-middle-v1.14.4...import-in-the-middle-v1.15.0) (2025-10-09)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* Compatibility with specifier imports ([#211](https://github.com/nodejs/import-in-the-middle/issues/211)) ([83d662a](https://github.com/nodejs/import-in-the-middle/commit/83d662a8e1f9a7b8632bc78f7499ccc0ab4d12c2))
|
|
9
|
+
|
|
3
10
|
## [1.14.4](https://github.com/nodejs/import-in-the-middle/compare/import-in-the-middle-v1.14.3...import-in-the-middle-v1.14.4) (2025-09-25)
|
|
4
11
|
|
|
5
12
|
|
package/lib/get-exports.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
const getEsmExports = require('./get-esm-exports.js')
|
|
4
4
|
const { parse: parseCjs } = require('cjs-module-lexer')
|
|
5
|
-
const { readFileSync } = require('fs')
|
|
5
|
+
const { readFileSync, existsSync } = require('fs')
|
|
6
6
|
const { builtinModules } = require('module')
|
|
7
7
|
const { fileURLToPath, pathToFileURL } = require('url')
|
|
8
|
-
const { dirname } = require('path')
|
|
8
|
+
const { dirname, join } = require('path')
|
|
9
9
|
|
|
10
10
|
function addDefault (arr) {
|
|
11
11
|
return new Set(['default', ...arr])
|
|
@@ -27,6 +27,62 @@ function getExportsForNodeBuiltIn (name) {
|
|
|
27
27
|
|
|
28
28
|
const urlsBeingProcessed = new Set() // Guard against circular imports.
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* This function looks for the package.json which contains the specifier trying to resolve.
|
|
32
|
+
* Once the package.json file has been found, we extract the file path from the specifier
|
|
33
|
+
* @param {string} specifier The specifier that is being search for inside the imports object
|
|
34
|
+
* @param {URL|string} fromUrl The url from which the search starts from
|
|
35
|
+
* @returns array with url and resolvedExport
|
|
36
|
+
*/
|
|
37
|
+
function resolvePackageImports (specifier, fromUrl) {
|
|
38
|
+
try {
|
|
39
|
+
const fromPath = fileURLToPath(fromUrl)
|
|
40
|
+
let currentDir = dirname(fromPath)
|
|
41
|
+
|
|
42
|
+
// search for package.json file which has the real url to export
|
|
43
|
+
while (currentDir !== dirname(currentDir)) {
|
|
44
|
+
const packageJsonPath = join(currentDir, 'package.json')
|
|
45
|
+
|
|
46
|
+
if (existsSync(packageJsonPath)) {
|
|
47
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'))
|
|
48
|
+
if (packageJson.imports && packageJson.imports[specifier]) {
|
|
49
|
+
const imports = packageJson.imports[specifier]
|
|
50
|
+
|
|
51
|
+
// Look for path inside packageJson
|
|
52
|
+
let resolvedExport
|
|
53
|
+
if (imports && typeof imports === 'object') {
|
|
54
|
+
const requireExport = imports.require
|
|
55
|
+
const importExport = imports.import
|
|
56
|
+
// look for the possibility of require and import which is standard for CJS/ESM
|
|
57
|
+
if (requireExport || importExport) {
|
|
58
|
+
// trying to resolve based on order of importance
|
|
59
|
+
resolvedExport = requireExport.node || requireExport.default || importExport.node || importExport.default
|
|
60
|
+
} else if (imports.node || imports.default) {
|
|
61
|
+
resolvedExport = imports.node || imports.default
|
|
62
|
+
}
|
|
63
|
+
} else if (typeof imports === 'string') {
|
|
64
|
+
resolvedExport = imports
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (resolvedExport) {
|
|
68
|
+
const url = resolvedExport.startsWith('.')
|
|
69
|
+
? pathToFileURL(join(currentDir, resolvedExport))
|
|
70
|
+
: fromUrl
|
|
71
|
+
return [url, resolvedExport]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// return if we find a package.json but did not find an import
|
|
75
|
+
return null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
currentDir = dirname(currentDir)
|
|
79
|
+
}
|
|
80
|
+
} catch (cause) {
|
|
81
|
+
throw Error(`Failed to find export: ${specifier}`, { cause })
|
|
82
|
+
}
|
|
83
|
+
return null
|
|
84
|
+
}
|
|
85
|
+
|
|
30
86
|
async function getCjsExports (url, context, parentLoad, source) {
|
|
31
87
|
if (urlsBeingProcessed.has(url)) {
|
|
32
88
|
return []
|
|
@@ -46,7 +102,14 @@ async function getCjsExports (url, context, parentLoad, source) {
|
|
|
46
102
|
if (re === '.') {
|
|
47
103
|
re = './'
|
|
48
104
|
}
|
|
49
|
-
|
|
105
|
+
|
|
106
|
+
// Entries in the import field should always start with #
|
|
107
|
+
if (re.startsWith('#')) {
|
|
108
|
+
const resolved = resolvePackageImports(re, url)
|
|
109
|
+
if (!resolved) return
|
|
110
|
+
[url, re] = resolved
|
|
111
|
+
}
|
|
112
|
+
|
|
50
113
|
const newUrl = pathToFileURL(require.resolve(re, { paths: [dirname(fileURLToPath(url))] })).href
|
|
51
114
|
|
|
52
115
|
if (newUrl.endsWith('.node') || newUrl.endsWith('.json')) {
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = { ...require('#main-entry-point') }
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "test-fixtures",
|
|
3
|
+
"imports": {
|
|
4
|
+
"#main-entry-point": {
|
|
5
|
+
"require": {
|
|
6
|
+
"node": "./something.js",
|
|
7
|
+
"default": "./something.js"
|
|
8
|
+
},
|
|
9
|
+
"import": {
|
|
10
|
+
"node":"./something.mjs",
|
|
11
|
+
"default": "./something.mjs"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"#main-entry-point-string" : "./something.js",
|
|
15
|
+
"#main-entry-point-external" : "some-external-cjs-module"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = { ...require('#main-entry-point-external') }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = { ...require('#main-entry-point-string') }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '#main-entry-point'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { foo } from '../fixtures/specifier-external.js'
|
|
2
|
+
import Hook from '../../index.js'
|
|
3
|
+
import { strictEqual } from 'assert'
|
|
4
|
+
|
|
5
|
+
Hook((exports, name) => {
|
|
6
|
+
if (name.endsWith('fixtures/specifier-external.js')) {
|
|
7
|
+
exports.foo = 'bar2'
|
|
8
|
+
}
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
strictEqual(foo, 'bar2')
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { foo } from '../fixtures/nested-folder/specifier.js'
|
|
2
|
+
import Hook from '../../index.js'
|
|
3
|
+
import { strictEqual } from 'assert'
|
|
4
|
+
|
|
5
|
+
Hook((exports, name) => {
|
|
6
|
+
if (name.endsWith('fixtures/nested-folder/specifier.js')) {
|
|
7
|
+
exports.foo = 1
|
|
8
|
+
}
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
strictEqual(foo, 1)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { foo } from '../fixtures/specifier-string.js'
|
|
2
|
+
import Hook from '../../index.js'
|
|
3
|
+
import { strictEqual } from 'assert'
|
|
4
|
+
|
|
5
|
+
Hook((exports, name) => {
|
|
6
|
+
if (name.endsWith('fixtures/specifier-string.js')) {
|
|
7
|
+
exports.foo = 1
|
|
8
|
+
}
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
strictEqual(foo, 1)
|