@@ -5,10 +5,19 @@ import { logger } from '@sentry/core';
5
5
import { DEBUG_BUILD } from '../debug-build' ;
6
6
import { isCjs } from '../utils/commonjs' ;
7
7
8
- let moduleCache : { [ key : string ] : string } ;
8
+ type ModuleInfo = Record < string , string > ;
9
+
10
+ let moduleCache : ModuleInfo | undefined ;
9
11
10
12
const INTEGRATION_NAME = 'Modules' ;
11
13
14
+ declare const __SENTRY_SERVER_MODULES__ : Record < string , string > ;
15
+
16
+ /**
17
+ * This is replaced at build time with the modules loaded by the server.
18
+ */
19
+ const SERVER_MODULES = typeof __SENTRY_SERVER_MODULES__ === 'undefined' ? { } : __SENTRY_SERVER_MODULES__ ;
20
+
12
21
const _modulesIntegration = ( ( ) => {
13
22
// This integration only works in CJS contexts
14
23
if ( ! isCjs ( ) ) {
@@ -52,17 +61,23 @@ function getPaths(): string[] {
52
61
}
53
62
54
63
/** Extract information about package.json modules */
55
- function collectModules ( ) : {
56
- [ name : string ] : string ;
57
- } {
64
+ function collectModules ( ) : ModuleInfo {
65
+ return {
66
+ ...SERVER_MODULES ,
67
+ ...getModulesFromPackageJson ( ) ,
68
+ ...collectRequireModules ( ) ,
69
+ } ;
70
+ }
71
+
72
+ /** Extract information about package.json modules from require.cache */
73
+ function collectRequireModules ( ) : ModuleInfo {
58
74
const mainPaths = require . main ?. paths || [ ] ;
59
75
const paths = getPaths ( ) ;
60
- const infos : {
61
- [ name : string ] : string ;
62
- } = { } ;
63
- const seen : {
64
- [ path : string ] : boolean ;
65
- } = { } ;
76
+
77
+ // We start with the modules from package.json (if possible)
78
+ // These may be overwritten by more specific versions from the require.cache
79
+ const infos : ModuleInfo = { } ;
80
+ const seen = new Set < string > ( ) ;
66
81
67
82
paths . forEach ( path => {
68
83
let dir = path ;
@@ -72,15 +87,15 @@ function collectModules(): {
72
87
const orig = dir ;
73
88
dir = dirname ( orig ) ;
74
89
75
- if ( ! dir || orig === dir || seen [ orig ] ) {
90
+ if ( ! dir || orig === dir || seen . has ( orig ) ) {
76
91
return undefined ;
77
92
}
78
93
if ( mainPaths . indexOf ( dir ) < 0 ) {
79
94
return updir ( ) ;
80
95
}
81
96
82
97
const pkgfile = join ( orig , 'package.json' ) ;
83
- seen [ orig ] = true ;
98
+ seen . add ( orig ) ;
84
99
85
100
if ( ! existsSync ( pkgfile ) ) {
86
101
return updir ( ) ;
@@ -104,9 +119,35 @@ function collectModules(): {
104
119
}
105
120
106
121
/** Fetches the list of modules and the versions loaded by the entry file for your node.js app. */
107
- function _getModules ( ) : { [ key : string ] : string } {
122
+ function _getModules ( ) : ModuleInfo {
108
123
if ( ! moduleCache ) {
109
124
moduleCache = collectModules ( ) ;
110
125
}
111
126
return moduleCache ;
112
127
}
128
+
129
+ interface PackageJson {
130
+ dependencies ?: Record < string , string > ;
131
+ devDependencies ?: Record < string , string > ;
132
+ }
133
+
134
+ function getPackageJson ( ) : PackageJson {
135
+ try {
136
+ // @ts -expect-error This actually works, we transpile this in CJS
137
+ const filePath = join ( dirname ( import . meta. url ) , 'package.json' ) ;
138
+ const packageJson = JSON . parse ( readFileSync ( filePath , 'utf8' ) ) as PackageJson ;
139
+
140
+ return packageJson ;
141
+ } catch ( e ) {
142
+ return { } ;
143
+ }
144
+ }
145
+
146
+ function getModulesFromPackageJson ( ) : ModuleInfo {
147
+ const packageJson = getPackageJson ( ) ;
148
+
149
+ return {
150
+ ...packageJson . dependencies ,
151
+ ...packageJson . devDependencies ,
152
+ } ;
153
+ }
0 commit comments