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