• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* eslint node/no-deprecated-api: "off" */
2const semver = require('semver')
3const { basename } = require('path')
4const { parse } = require('url')
5module.exports = (name, tgz) => {
6  const base = basename(tgz)
7  if (!base.endsWith('.tgz')) {
8    return null
9  }
10
11  const u = parse(tgz)
12  if (/^https?:/.test(u.protocol)) {
13    // registry url?  check for most likely pattern.
14    // either /@foo/bar/-/bar-1.2.3.tgz or
15    // /foo/-/foo-1.2.3.tgz, and fall through to
16    // basename checking.  Note that registries can
17    // be mounted below the root url, so /a/b/-/x/y/foo/-/foo-1.2.3.tgz
18    // is a potential option.
19    const tfsplit = u.path.slice(1).split('/-/')
20    if (tfsplit.length > 1) {
21      const afterTF = tfsplit.pop()
22      if (afterTF === base) {
23        const pre = tfsplit.pop()
24        const preSplit = pre.split(/\/|%2f/i)
25        const project = preSplit.pop()
26        const scope = preSplit.pop()
27        return versionFromBaseScopeName(base, scope, project)
28      }
29    }
30  }
31
32  const split = name.split(/\/|%2f/i)
33  const project = split.pop()
34  const scope = split.pop()
35  return versionFromBaseScopeName(base, scope, project)
36}
37
38const versionFromBaseScopeName = (base, scope, name) => {
39  if (!base.startsWith(name + '-')) {
40    return null
41  }
42
43  const parsed = semver.parse(base.substring(name.length + 1, base.length - 4))
44  return parsed ? {
45    name: scope && scope.charAt(0) === '@' ? `${scope}/${name}` : name,
46    version: parsed.version,
47  } : null
48}
49