forked from nodejs/import-in-the-middle
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
93 lines (81 loc) · 2.35 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License.
//
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
const path = require('path')
const parse = require('module-details-from-path')
const { fileURLToPath } = require('url')
const {
importHooks,
specifiers,
toHook
} = require('./lib/register')
function addHook (hook) {
importHooks.push(hook)
toHook.forEach(([name, namespace]) => hook(name, namespace))
}
function removeHook (hook) {
const index = importHooks.indexOf(hook)
if (index > -1) {
importHooks.splice(index, 1)
}
}
function callHookFn (hookFn, namespace, name, baseDir) {
const newDefault = hookFn(namespace, name, baseDir)
if (newDefault && newDefault !== namespace) {
namespace.default = newDefault
}
}
function Hook (modules, options, hookFn) {
if ((this instanceof Hook) === false) return new Hook(modules, options, hookFn)
if (typeof modules === 'function') {
hookFn = modules
modules = null
options = null
} else if (typeof options === 'function') {
hookFn = options
options = null
}
const internals = options ? options.internals === true : false
this._iitmHook = (name, namespace) => {
const filename = name
const isBuiltin = name.startsWith('node:')
let baseDir
if (isBuiltin) {
name = name.replace(/^node:/, '')
} else {
if (name.startsWith('file://')) {
try {
name = fileURLToPath(name)
} catch (e) {}
}
const details = parse(name)
if (details) {
name = details.name
baseDir = details.basedir
}
}
if (modules) {
for (const moduleName of modules) {
if (moduleName === name) {
if (baseDir) {
if (internals) {
name = name + path.sep + path.relative(baseDir, fileURLToPath(filename))
} else {
if (!baseDir.endsWith(specifiers.get(filename))) continue
}
}
callHookFn(hookFn, namespace, name, baseDir)
}
}
} else {
callHookFn(hookFn, namespace, name, baseDir)
}
}
addHook(this._iitmHook)
}
Hook.prototype.unhook = function () {
removeHook(this._iitmHook)
}
module.exports = Hook
module.exports.addHook = addHook
module.exports.removeHook = removeHook