File Explorer

/proc/self/root/proc/1/task/1/cwd/node24/lib/node_modules/npm/lib/cli

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

update-notifier.js3.8 KB · 116 lines
// print a banner telling the user to upgrade npm to latest but not in CI, and not if we're doing that already. const ciInfo = require('ci-info')const gt = require('semver/functions/gt')const gte = require('semver/functions/gte')const parse = require('semver/functions/parse')const { stat, writeFile } = require('node:fs/promises')const { resolve } = require('node:path') // update check frequencyconst DAILY = 1000 * 60 * 60 * 24const WEEKLY = DAILY * 7 // don't put it in the _cacache folder, just in npm's cacheconst lastCheckedFile = npm => resolve(npm.flatOptions.cache, '../_update-notifier-last-checked') // Actual check for updates. This is a separate function so that we only load this if we are doing the actual updateconst updateCheck = async (npm, spec, version, current) => {  const pacote = require('pacote')   const mani = await pacote.manifest(`npm@${spec}`, {    // always prefer latest, even if doing --tag=whatever on the cmd    defaultTag: 'latest',    ...npm.flatOptions,    cache: false,  }).catch(() => null)   // if pacote failed, give up  if (!mani) {    return null  }   const latest = mani.version   // if the current version is *greater* than latest, we're on a 'next' and should get the updates from that release train.  // Note that this isn't another http request over the network, because the packument will be cached by pacote from previous request.  if (gt(version, latest) && spec === '*') {    return updateNotifier(npm, `^${version}`)  }   // if we already have something >= the desired spec, then we're done  if (gte(version, latest)) {    return null  }   const chalk = npm.logChalk   // ok! notify the user about this update they should get.  // The message is saved for printing at process exit so it will not get lost in any other messages being printed as part of the command.  const update = parse(mani.version)  const type = update.major !== current.major ? 'major'    : update.minor !== current.minor ? 'minor'    : update.patch !== current.patch ? 'patch'    : 'prerelease'  const typec = type === 'major' ? 'red'    : type === 'minor' ? 'yellow'    : 'cyan'  const message = [    '',    `New ${chalk[typec](type)} version of npm available! ${chalk[typec](current)} -> ${chalk.blue(latest)}`,    `Changelog: ${chalk.blue(`https://github.com/npm/cli/releases/tag/v${latest}`)}`,    `To update run: ${chalk.underline(`npm install -g npm@${latest}`)}`,    '',  ].join('\n')   return message} const updateNotifier = async (npm, spec = '*') => {  // if we're on a prerelease train, then updates are coming fast check for a new one daily.  // otherwise, weekly.  const { version } = npm  const current = parse(version)   // if we're on a beta train, always get the next beta  if (current.prerelease.length) {    spec = `^${version}`  }   // while on a beta train, get updates daily  const duration = current.prerelease.length ? DAILY : WEEKLY   const t = new Date(Date.now() - duration)  // if we don't have a file, then definitely check it.  const st = await stat(lastCheckedFile(npm)).catch(() => ({ mtime: t - 1 }))   // if we've already checked within the specified duration, don't check again  if (!(t > st.mtime)) {    return null  }   // intentional.  do not await this.  it's a best-effort update.  // if this fails, it's ok.  // might be using /dev/null as the cache or something weird like that.  writeFile(lastCheckedFile(npm), '').catch(() => {})   return updateCheck(npm, spec, version, current)} module.exports = async npm => {  if (    // opted out    !npm.config.get('update-notifier')    // global npm update    || (npm.flatOptions.global &&      ['install', 'update'].includes(npm.command) &&      npm.argv.some(arg => /^npm(@|$)/.test(arg)))    // CI    || ciInfo.isCI  ) {    return null  }   return updateNotifier(npm)}