File Explorer

/proc/self/root/var/lang/lib/node_modules/npm/node_modules/@npmcli/arborist/lib

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 /.

dep-valid.js6.0 KB · 180 lines
// Do not rely on package._fields, so that we don't throw// false failures if a tree is generated by other clients.// Only relies on child.resolved, which MAY come from// client-specific package.json meta _fields, but most of// the time will be pulled out of a lockfile const semver = require('semver')const npa = require('npm-package-arg')const { relative } = require('node:path')const fromPath = require('./from-path.js') // A named ref (tag or branch) resolves to a commit hash, so look up the// committish recorded for this edge in the lockfile to detect spec changes.const lockedGitCommittish = (child, requestor) => {  const lock = requestor.root?.meta?.data?.packages?.[requestor.location]  const spec = lock && (    lock.dependencies?.[child.name] ||    lock.optionalDependencies?.[child.name] ||    lock.devDependencies?.[child.name] ||    lock.peerDependencies?.[child.name]  )  if (!spec) {    return null  }  try {    const parsed = npa.resolve(child.name, spec, requestor.realpath)    return parsed.type === 'git' ? parsed.gitCommittish || '' : null  } catch {    return null  }} const depValid = (child, requested, requestor) => {  // NB: we don't do much to verify 'tag' type requests.  // Just verify that we got a remote resolution.  Presumably, it  // came from a registry and was tagged at some point.   if (typeof requested === 'string') {    try {      // tarball/dir must have resolved to the same tgz on disk, but for      // file: deps that depend on other files/dirs, we must resolve the      // location based on the *requestor* file/dir, not where it ends up.      // '' is equivalent to '*'      requested = npa.resolve(child.name, requested || '*', fromPath(requestor, requestor.edgesOut.get(child.name)))    } catch (er) {      // Not invalid because the child doesn't match, but because      // the spec itself is not supported.  Nothing would match,      // so the edge is definitely not valid and never can be.      er.dependency = child.name      er.requested = requested      requestor.errors.push(er)      return false    }  }   // if the lockfile is super old, or hand-modified,  // then it's possible to hit this state.  if (!requested) {    const er = new Error('Invalid dependency specifier')    er.dependency = child.name    er.requested = requested    requestor.errors.push(er)    return false  }   switch (requested.type) {    case 'range':      if (requested.fetchSpec === '*') {        return true      }      // fallthrough    case 'version':      // if it's a version or a range other than '*', semver it      return semver.satisfies(child.version, requested.fetchSpec, true)     case 'directory':      return linkValid(child, requested, requestor)     case 'file':      return tarballValid(child, requested, requestor)     case 'alias':      // check that the alias target is valid      return depValid(child, requested.subSpec, requestor)     case 'tag':      // if it's a tag, we just verify that it has a tarball resolution      // presumably, it came from the registry and was tagged at some point      return child.resolved && npa(child.resolved).type === 'remote'     case 'remote':      // verify that we got it from the desired location      return child.resolved === requested.fetchSpec     case 'git': {      // if it's a git type, verify that they're the same repo      //      // if it specifies a definite commit, then it must have the      // same commit to be considered the same repo      //      // if it has a #semver:<range> specifier, verify that the      // version in the package is in the semver range      const resRepo = npa(child.resolved || '')      const resHost = resRepo.hosted      const reqHost = requested.hosted      const reqCommit = /^[a-fA-F0-9]{40,64}$/.test(requested.gitCommittish || '')      const nc = { noCommittish: !reqCommit }      if (!resHost) {        if (resRepo.fetchSpec !== requested.fetchSpec) {          return false        }      } else {        if (reqHost?.ssh(nc) !== resHost.ssh(nc)) {          return false        }      }      if (!requested.gitRange) {        // a named ref can't be verified against the resolved commit offline,        // so re-resolve if it differs from the committish in the lockfile        if (!reqCommit) {          const locked = lockedGitCommittish(child, requestor)          if (locked !== null && locked !== (requested.gitCommittish || '')) {            return false          }        }        return true      }      return semver.satisfies(child.package.version, requested.gitRange, {        loose: true,      })    }     default: // impossible, just being cautious      break  }   const er = new Error('Unsupported dependency type')  er.dependency = child.name  er.requested = requested  requestor.errors.push(er)  return false} const linkValid = (child, requested, requestor) => {  const isLink = !!child.isLink  // if we're installing links and the node is a link, then it's invalid because we want  // a real node to be there.  Except for workspaces. They are always links.  if (requestor.installLinks && !child.isWorkspace) {    return !isLink  }   // directory must be a link to the specified folder  return isLink && relative(child.realpath, requested.fetchSpec) === ''} const tarballValid = (child, requested) => {  if (child.isLink) {    return false  }   if (child.resolved) {    return child.resolved.replace(/\\/g, '/') === `file:${requested.fetchSpec.replace(/\\/g, '/')}`  }   // if we have a legacy mutated package.json file.  we can't be 100%  // sure that it resolved to the same file, but if it was the same  // request, that's a pretty good indicator of sameness.  if (child.package._requested) {    return child.package._requested.saveSpec === requested.saveSpec  }   // ok, we're probably dealing with some legacy cruft here, not much  // we can do at this point unfortunately.  return false} module.exports = (child, requested, accept, requestor) =>  depValid(child, requested, requestor) ||  (typeof accept === 'string' ? depValid(child, accept, requestor) : false)