Skip to content

Instantly share code, notes, and snippets.

@isaacs
Last active June 2, 2021 17:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save isaacs/29ad4f7d0a2e60f6e793f6ea01c92b65 to your computer and use it in GitHub Desktop.
Save isaacs/29ad4f7d0a2e60f6e793f6ea01c92b65 to your computer and use it in GitHub Desktop.
diff --git a/lib/cli.js b/lib/cli.js
index f42132f94..b1f6ba6ae 100644
--- a/lib/cli.js
+++ b/lib/cli.js
@@ -53,7 +53,9 @@ module.exports = (process) => {
npm.config.set('usage', false, 'cli')
}
- npm.updateNotification = await updateNotifier(npm)
+ npm.updateNotification = updateNotifier(npm).then(notification =>
+ npm.updateNotification = notification)
+ // await npm.updateNotification
const cmd = npm.argv.shift()
const impl = npm.commands[cmd]
diff --git a/lib/utils/error-handler.js b/lib/utils/error-handler.js
index 1fc31df44..da716679d 100644
--- a/lib/utils/error-handler.js
+++ b/lib/utils/error-handler.js
@@ -119,7 +119,9 @@ const errorHandler = (er) => {
if (cbCalled)
er = er || new Error('Callback called more than once.')
- if (npm.updateNotification) {
+ // only show the notification if it finished before the other stuff we
+ // were doing. no need to hang on `npm -v` or something.
+ if (typeof npm.updateNotification === 'string') {
const { level } = log
log.level = log.levels.notice
log.notice('', npm.updateNotification)
diff --git a/lib/utils/update-notifier.js b/lib/utils/update-notifier.js
index 1af948a2d..d6ad2b6bd 100644
--- a/lib/utils/update-notifier.js
+++ b/lib/utils/update-notifier.js
@@ -21,23 +21,29 @@ const isGlobalNpmUpdate = npm => {
const DAILY = 1000 * 60 * 60 * 24
const WEEKLY = DAILY * 7
-const updateTimeout = async (npm, duration) => {
+// don't put it in the _cacache folder, just in npm's cache
+const lastCheckedFile = npm =>
+ resolve(npm.flatOptions.cache, '../_update-notifier-last-checked')
+
+const checkTimeout = async (npm, duration) => {
const t = new Date(Date.now() - duration)
- // don't put it in the _cacache folder, just in npm's cache
- const f = resolve(npm.flatOptions.cache, '../_update-notifier-last-checked')
+ const f = lastCheckedFile(npm)
// if we don't have a file, then definitely check it.
const st = await stat(f).catch(() => ({ mtime: t - 1 }))
+ return t > st.mtime
+}
- if (t > st.mtime) {
+const updateTimeout = async (npm, duration) => {
+ if (checkTimeout(npm, duration)) {
// best effort, if this fails, it's ok.
// might be using /dev/null as the cache or something weird like that.
- await writeFile(f, '').catch(() => {})
+ await writeFile(lastCheckedFile(npm), '').catch(() => {})
return true
} else
return false
}
-const updateNotifier = module.exports = async (npm, spec = 'latest') => {
+const updateNotifier = async (npm, spec = 'latest') => {
// never check for updates in CI, when updating npm already, or opted out
if (!npm.config.get('update-notifier') ||
isGlobalNpmUpdate(npm) ||
@@ -57,7 +63,7 @@ const updateNotifier = module.exports = async (npm, spec = 'latest') => {
const duration = spec !== 'latest' ? DAILY : WEEKLY
// if we've already checked within the specified duration, don't check again
- if (!(await updateTimeout(npm, duration)))
+ if (!(await checkTimeout(npm, duration)))
return null
// if they're currently using a prerelease, nudge to the next prerelease
@@ -113,3 +119,11 @@ const updateNotifier = module.exports = async (npm, spec = 'latest') => {
return messagec
}
+
+// only update the notification timeout if we actually finished checking
+module.exports = async npm => {
+ const notification = await updateNotifier(npm)
+ // intentional. do not await this. it's a best-effort update.
+ updateTimeout(npm)
+ return notification
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment