{"version":3,"file":"RequireInTheMiddleSingleton.js","sourceRoot":"","sources":["../../../../src/platform/node/RequireInTheMiddleSingleton.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAGH,iEAA6C;AAC7C,6BAA6B;AAC7B,qDAAuE;AAOvE;;;;;GAKG;AACH,MAAM,OAAO,GAAG;IACd,WAAW;IACX,OAAO;IACP,YAAY;IACZ,QAAQ;IACR,UAAU;IACV,IAAI;CACL,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE;IACX,gEAAgE;IAChE,OAAO,OAAO,MAAM,CAAC,EAAE,CAAC,KAAK,UAAU,CAAC;AAC1C,CAAC,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAa,2BAA2B;IAItC;QAHQ,oBAAe,GAAmB,IAAI,+BAAc,EAAE,CAAC;QAI7D,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAEO,WAAW;QACjB,IAAI,4BAAI;QACN,wEAAwE;QACxE,IAAI,EACJ,EAAE,SAAS,EAAE,IAAI,EAAE,EACnB,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;YACzB,iFAAiF;YACjF,MAAM,oBAAoB,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;YAE3D,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,oBAAoB,EAAE;gBAChE,sBAAsB,EAAE,IAAI;gBAC5B,gFAAgF;gBAChF,wDAAwD;gBACxD,oDAAoD;gBACpD,QAAQ,EAAE,OAAO,KAAK,SAAS;aAChC,CAAC,CAAC;YAEH,KAAK,MAAM,EAAE,SAAS,EAAE,IAAI,OAAO,EAAE;gBACnC,OAAO,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;aAC7C;YAED,OAAO,OAAO,CAAC;QACjB,CAAC,CACF,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,QAAQ,CAAC,UAAkB,EAAE,SAAsB;QACjD,MAAM,MAAM,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;QACzC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,WAAW;;QAChB,iDAAiD;QACjD,qDAAqD;QACrD,IAAI,OAAO;YAAE,OAAO,IAAI,2BAA2B,EAAE,CAAC;QAEtD,OAAO,CAAC,IAAI,CAAC,SAAS;YACpB,MAAA,IAAI,CAAC,SAAS,mCAAI,IAAI,2BAA2B,EAAE,CAAC,CAAC;IACzD,CAAC;CACF;AA5DD,kEA4DC;AAED;;;;;GAKG;AACH,SAAS,uBAAuB,CAAC,gBAAwB;IACvD,OAAO,IAAI,CAAC,GAAG,KAAK,oCAAmB;QACrC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,oCAAmB,CAAC;QAC5D,CAAC,CAAC,gBAAgB,CAAC;AACvB,CAAC","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { OnRequireFn } from 'require-in-the-middle';\nimport { Hook } from 'require-in-the-middle';\nimport * as path from 'path';\nimport { ModuleNameTrie, ModuleNameSeparator } from './ModuleNameTrie';\n\nexport type Hooked = {\n moduleName: string;\n onRequire: OnRequireFn;\n};\n\n/**\n * Whether Mocha is running in this process\n * Inspired by https://github.com/AndreasPizsa/detect-mocha\n *\n * @type {boolean}\n */\nconst isMocha = [\n 'afterEach',\n 'after',\n 'beforeEach',\n 'before',\n 'describe',\n 'it',\n].every(fn => {\n // @ts-expect-error TS7053: Element implicitly has an 'any' type\n return typeof global[fn] === 'function';\n});\n\n/**\n * Singleton class for `require-in-the-middle`\n * Allows instrumentation plugins to patch modules with only a single `require` patch\n * WARNING: Because this class will create its own `require-in-the-middle` (RITM) instance,\n * we should minimize the number of new instances of this class.\n * Multiple instances of `@opentelemetry/instrumentation` (e.g. multiple versions) in a single process\n * will result in multiple instances of RITM, which will have an impact\n * on the performance of instrumentation hooks being applied.\n */\nexport class RequireInTheMiddleSingleton {\n private _moduleNameTrie: ModuleNameTrie = new ModuleNameTrie();\n private static _instance?: RequireInTheMiddleSingleton;\n\n private constructor() {\n this._initialize();\n }\n\n private _initialize() {\n new Hook(\n // Intercept all `require` calls; we will filter the matching ones below\n null,\n { internals: true },\n (exports, name, basedir) => {\n // For internal files on Windows, `name` will use backslash as the path separator\n const normalizedModuleName = normalizePathSeparators(name);\n\n const matches = this._moduleNameTrie.search(normalizedModuleName, {\n maintainInsertionOrder: true,\n // For core modules (e.g. `fs`), do not match on sub-paths (e.g. `fs/promises').\n // This matches the behavior of `require-in-the-middle`.\n // `basedir` is always `undefined` for core modules.\n fullOnly: basedir === undefined,\n });\n\n for (const { onRequire } of matches) {\n exports = onRequire(exports, name, basedir);\n }\n\n return exports;\n }\n );\n }\n\n /**\n * Register a hook with `require-in-the-middle`\n *\n * @param {string} moduleName Module name\n * @param {OnRequireFn} onRequire Hook function\n * @returns {Hooked} Registered hook\n */\n register(moduleName: string, onRequire: OnRequireFn): Hooked {\n const hooked = { moduleName, onRequire };\n this._moduleNameTrie.insert(hooked);\n return hooked;\n }\n\n /**\n * Get the `RequireInTheMiddleSingleton` singleton\n *\n * @returns {RequireInTheMiddleSingleton} Singleton of `RequireInTheMiddleSingleton`\n */\n static getInstance(): RequireInTheMiddleSingleton {\n // Mocha runs all test suites in the same process\n // This prevents test suites from sharing a singleton\n if (isMocha) return new RequireInTheMiddleSingleton();\n\n return (this._instance =\n this._instance ?? new RequireInTheMiddleSingleton());\n }\n}\n\n/**\n * Normalize the path separators to forward slash in a module name or path\n *\n * @param {string} moduleNameOrPath Module name or path\n * @returns {string} Normalized module name or path\n */\nfunction normalizePathSeparators(moduleNameOrPath: string): string {\n return path.sep !== ModuleNameSeparator\n ? moduleNameOrPath.split(path.sep).join(ModuleNameSeparator)\n : moduleNameOrPath;\n}\n"]}