2
2
// but not in CI, and not if we're doing that already.
3
3
// Check daily for betas, and weekly otherwise.
4
4
5
- const pacote = require ( 'pacote' )
6
5
const ciInfo = require ( 'ci-info' )
7
6
const semver = require ( 'semver' )
8
7
const { stat, writeFile } = require ( 'fs/promises' )
9
8
const { resolve } = require ( 'path' )
10
9
11
- const SKIP = Symbol ( 'SKIP' )
12
-
13
- const isGlobalNpmUpdate = npm => {
14
- return npm . flatOptions . global &&
15
- [ 'install' , 'update' ] . includes ( npm . command ) &&
16
- npm . argv . some ( arg => / ^ n p m ( @ | $ ) / . test ( arg ) )
17
- }
18
-
19
10
// update check frequency
20
11
const DAILY = 1000 * 60 * 60 * 24
21
12
const WEEKLY = DAILY * 7
@@ -24,39 +15,10 @@ const WEEKLY = DAILY * 7
24
15
const lastCheckedFile = npm =>
25
16
resolve ( npm . flatOptions . cache , '../_update-notifier-last-checked' )
26
17
27
- const checkTimeout = async ( npm , duration ) => {
28
- const t = new Date ( Date . now ( ) - duration )
29
- const f = lastCheckedFile ( npm )
30
- // if we don't have a file, then definitely check it.
31
- const st = await stat ( f ) . catch ( ( ) => ( { mtime : t - 1 } ) )
32
- return t > st . mtime
33
- }
34
-
35
- const updateNotifier = async ( npm , spec = 'latest' ) => {
36
- // never check for updates in CI, when updating npm already, or opted out
37
- if ( ! npm . config . get ( 'update-notifier' ) ||
38
- isGlobalNpmUpdate ( npm ) ||
39
- ciInfo . isCI ) {
40
- return SKIP
41
- }
42
-
43
- // if we're on a prerelease train, then updates are coming fast
44
- // check for a new one daily. otherwise, weekly.
45
- const { version } = npm
46
- const current = semver . parse ( version )
47
-
48
- // if we're on a beta train, always get the next beta
49
- if ( current . prerelease . length ) {
50
- spec = `^${ version } `
51
- }
52
-
53
- // while on a beta train, get updates daily
54
- const duration = spec !== 'latest' ? DAILY : WEEKLY
55
-
56
- // if we've already checked within the specified duration, don't check again
57
- if ( ! ( await checkTimeout ( npm , duration ) ) ) {
58
- return null
59
- }
18
+ // Actual check for updates. This is a separate function so that we only load
19
+ // this if we are doing the actual update
20
+ const updateCheck = async ( npm , spec , version , current ) => {
21
+ const pacote = require ( 'pacote' )
60
22
61
23
const mani = await pacote . manifest ( `npm@${ spec } ` , {
62
24
// always prefer latest, even if doing --tag=whatever on the cmd
@@ -112,15 +74,49 @@ const updateNotifier = async (npm, spec = 'latest') => {
112
74
return message
113
75
}
114
76
77
+ const updateNotifier = async ( npm , spec = 'latest' ) => {
78
+ // if we're on a prerelease train, then updates are coming fast
79
+ // check for a new one daily. otherwise, weekly.
80
+ const { version } = npm
81
+ const current = semver . parse ( version )
82
+
83
+ // if we're on a beta train, always get the next beta
84
+ if ( current . prerelease . length ) {
85
+ spec = `^${ version } `
86
+ }
87
+
88
+ // while on a beta train, get updates daily
89
+ const duration = spec !== 'latest' ? DAILY : WEEKLY
90
+
91
+ const t = new Date ( Date . now ( ) - duration )
92
+ // if we don't have a file, then definitely check it.
93
+ const st = await stat ( lastCheckedFile ( npm ) ) . catch ( ( ) => ( { mtime : t - 1 } ) )
94
+
95
+ // if we've already checked within the specified duration, don't check again
96
+ if ( ! ( t > st . mtime ) ) {
97
+ return null
98
+ }
99
+
100
+ return updateCheck ( npm , spec , version , current )
101
+ }
102
+
115
103
// only update the notification timeout if we actually finished checking
116
104
module . exports = async npm => {
117
- const notification = await updateNotifier ( npm )
118
-
119
- // dont write the file if we skipped checking altogether
120
- if ( notification === SKIP ) {
105
+ if (
106
+ // opted out
107
+ ! npm . config . get ( 'update-notifier' )
108
+ // global npm update
109
+ || ( npm . flatOptions . global &&
110
+ [ 'install' , 'update' ] . includes ( npm . command ) &&
111
+ npm . argv . some ( arg => / ^ n p m ( @ | $ ) / . test ( arg ) ) )
112
+ // CI
113
+ || ciInfo . isCI
114
+ ) {
121
115
return null
122
116
}
123
117
118
+ const notification = await updateNotifier ( npm )
119
+
124
120
// intentional. do not await this. it's a best-effort update. if this
125
121
// fails, it's ok. might be using /dev/null as the cache or something weird
126
122
// like that.
0 commit comments