// 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