import * as path from "path" ; import * as semver from "semver" ; export type PatchFunction = ( module : any , path : string ) => any ; export interface IModulePatcher { versionSpecifier : string ; patch : PatchFunction ; } export interface IModulePatchMap { [ key ] : IModulePatcher [ ] ; } declare const process ; const moduleModule = require ( "module" ) ; const nativeModules = Object . keys ( process . binding ( "natives" ) ) ; const originalRequire = moduleModule . prototype . require ; export function makePatchingRequire ( knownPatches ) { const patchedModules = { } ; return function patchedRequire ( moduleId ) : any { const originalModule = originalRequire . apply ( this , arguments ) ; if ( knownPatches [ moduleId ] ) { const modulePath = moduleModule . _resolveFilename ( moduleId , this ) ; if ( patchedModules . hasOwnProperty ( modulePath ) ) { return patchedModules [ modulePath ] ; } let moduleVersion ; if ( nativeModules . indexOf ( moduleId ) < 0 ) { try { moduleVersion = originalRequire . call ( this , path . join ( moduleId , "package.json" ) ) . version ; } catch ( e ) { return originalModule ; } } else { moduleVersion = process . version . substring ( 1 ) ; } const prereleaseTagIndex = moduleVersion . indexOf ( "-" ) ; if ( prereleaseTagIndex >= 0 ) { moduleVersion = moduleVersion . substring ( 0 , prereleaseTagIndex ) ; } let modifiedModule = originalModule ; for ( const modulePatcher of knownPatches [ moduleId ] ) { if ( semver . satisfies ( moduleVersion , modulePatcher . versionSpecifier ) ) { modifiedModule = modulePatcher . patch ( modifiedModule , modulePath ) ; } } return patchedModules [ modulePath ] = modifiedModule ; } return originalModule ; } ; }