import { EventProcessor , Hub , Integration } from '@sentry/types' ; import { existsSync , readFileSync } from 'fs' ; import { dirname , join } from 'path' ; let moduleCache ; /** Extract information about paths */ function getPaths ( ) { try { return require . cache ? Object . keys ( require . cache as Record < string , unknown > ) : [ ] ; } catch ( e ) { return [ ] ; } } /** Extract information about package.json modules */ function collectModules ( ) { const mainPaths = ( require . main && require . main . paths ) || [ ] ; const paths = getPaths ( ) ; const infos = { } ; const seen = { } ; paths . forEach ( path => { let dir = path ; /** Traverse directories upward in the search of package.json file */ const updir = ( ) : void | ( ( ) => void ) => { const orig = dir ; dir = dirname ( orig ) ; if ( ! dir || orig === dir || seen [ orig ] ) { return undefined ; } if ( mainPaths . indexOf ( dir ) < 0 ) { return updir ( ) ; } const pkgfile = join ( orig , 'package.json' ) ; seen [ orig ] = true ; if ( ! existsSync ( pkgfile ) ) { return updir ( ) ; } try { const info = JSON . parse ( readFileSync ( pkgfile , 'utf8' ) ) as { name : string ; version : string ; } ; infos [ info . name ] = info . version ; } catch ( _oO ) { } } ; updir ( ) ; } ) ; return infos ; } /** Add node modules / packages to the event */ export class Modules implements Integration { inheritDoc public static id : string = 'Modules' ; inheritDoc public name : string = Modules . id ; inheritDoc public setupOnce ( addGlobalEventProcessor , getCurrentHub ) { addGlobalEventProcessor ( event => { if ( ! getCurrentHub ( ) . getIntegration ( Modules ) ) { return event ; } return { ... event , modules : this . _getModules ( ) , } ; } ) ; } /** Fetches the list of modules and the versions loaded by the entry file for your node.js app. */ private _getModules ( ) { if ( ! moduleCache ) { moduleCache = collectModules ( ) ; } return moduleCache ; } }