@@ -22,6 +22,10 @@ function dirName () {
22
22
return __dirname
23
23
}
24
24
25
+ function npmExecPath ( ) {
26
+ return process . env . npm_execpath
27
+ }
28
+
25
29
const userMessageThrottleTime = 1000 * 60 // 1 minute
26
30
const execTimeout = 3000
27
31
@@ -76,10 +80,21 @@ function redactSensitivePackageInfo (dependencyInfo) {
76
80
return dependencyInfo
77
81
}
78
82
83
+ /*
84
+ Scarf-js is automatically disabled when being run inside of a yarn install.
85
+ The `npm_execpath` environment variable tells us which package manager is
86
+ running our install
87
+ */
88
+ function isYarn ( ) {
89
+ const execPath = module . exports . npmExecPath ( ) || ''
90
+ return [ 'yarn' , 'yarn.js' , 'yarnpkg' , 'yarn.cmd' , 'yarnpkg.cmd' ]
91
+ . some ( packageManBinName => execPath . endsWith ( packageManBinName ) )
92
+ }
93
+
79
94
function processDependencyTreeOutput ( resolve , reject ) {
80
95
return function ( error , stdout , stderr ) {
81
- if ( error ) {
82
- return reject ( new Error ( `Scarf received an error from npm -ls: ${ error } ` ) )
96
+ if ( error && ! stdout ) {
97
+ return reject ( new Error ( `Scarf received an error from npm -ls: ${ error } | ${ stderr } ` ) )
83
98
}
84
99
85
100
try {
@@ -116,8 +131,8 @@ function processDependencyTreeOutput (resolve, reject) {
116
131
}
117
132
118
133
// If any intermediate dependency in the chain of deps that leads to scarf
119
- // has disabled Scarf, we must respect that setting
120
- if ( dependencyToReport . anyInChainDisabled ) {
134
+ // has disabled Scarf, we must respect that setting unless the user overrides it.
135
+ if ( dependencyToReport . anyInChainDisabled && ! userHasOptedIn ( dependencyToReport . rootPackage ) ) {
121
136
return reject ( new Error ( 'Scarf has been disabled via a package.json in the dependency chain.' ) )
122
137
}
123
138
@@ -137,13 +152,18 @@ async function getDependencyInfo () {
137
152
138
153
async function reportPostInstall ( ) {
139
154
const scarfApiToken = process . env . SCARF_API_TOKEN
140
- const dependencyInfo = await getDependencyInfo ( )
155
+
156
+ const dependencyInfo = await module . exports . getDependencyInfo ( )
141
157
if ( ! dependencyInfo . parent || ! dependencyInfo . parent . name ) {
142
158
return Promise . reject ( new Error ( 'No parent, nothing to report' ) )
143
159
}
144
160
145
161
const rootPackage = dependencyInfo . rootPackage
146
162
163
+ if ( ! userHasOptedIn ( rootPackage ) && isYarn ( ) ) {
164
+ return Promise . reject ( new Error ( 'Package manager is yarn. scarf-js is unable to inform user of analytics. Aborting.' ) )
165
+ }
166
+
147
167
await new Promise ( ( resolve , reject ) => {
148
168
if ( dependencyInfo . parent . scarfSettings . defaultOptIn ) {
149
169
if ( userHasOptedOut ( rootPackage ) ) {
@@ -153,7 +173,7 @@ async function reportPostInstall () {
153
173
if ( ! userHasOptedIn ( rootPackage ) ) {
154
174
rateLimitedUserLog ( optedInLogRateLimitKey , `
155
175
The dependency '${ dependencyInfo . parent . name } ' is tracking installation
156
- statistics using Scarf (https://scarf.sh), which helps open-source developers
176
+ statistics using scarf-js (https://scarf.sh), which helps open-source developers
157
177
fund and maintain their projects. Scarf securely logs basic installation
158
178
details when this package is installed. The Scarf npm library is open source
159
179
and permissively licensed at https://github.com/scarf-sh/scarf-js. For more
@@ -172,7 +192,7 @@ async function reportPostInstall () {
172
192
}
173
193
rateLimitedUserLog ( optedOutLogRateLimitKey , `
174
194
The dependency '${ dependencyInfo . parent . name } ' would like to track
175
- installation statistics using Scarf (https://scarf.sh), which helps
195
+ installation statistics using scarf-js (https://scarf.sh), which helps
176
196
open-source developers fund and maintain their projects. Reporting is disabled
177
197
by default for this package. When enabled, Scarf securely logs basic
178
198
installation details when this package is installed. The Scarf npm library is
@@ -404,6 +424,19 @@ function writeCurrentTimeToLogHistory (rateLimitKey, history) {
404
424
fs . writeFileSync ( module . exports . tmpFileName ( ) , JSON . stringify ( history ) )
405
425
}
406
426
427
+ module . exports = {
428
+ redactSensitivePackageInfo,
429
+ hasHitRateLimit,
430
+ getRateLimitedLogHistory,
431
+ rateLimitedUserLog,
432
+ tmpFileName,
433
+ dirName,
434
+ processDependencyTreeOutput,
435
+ npmExecPath,
436
+ getDependencyInfo,
437
+ reportPostInstall
438
+ }
439
+
407
440
if ( require . main === module ) {
408
441
try {
409
442
reportPostInstall ( ) . catch ( e => {
@@ -418,13 +451,3 @@ if (require.main === module) {
418
451
process . exit ( 0 )
419
452
}
420
453
}
421
-
422
- module . exports = {
423
- redactSensitivePackageInfo,
424
- hasHitRateLimit,
425
- getRateLimitedLogHistory,
426
- rateLimitedUserLog,
427
- tmpFileName,
428
- dirName,
429
- processDependencyTreeOutput
430
- }
0 commit comments