const url = require('url') const URLFormat = /^\/((?:@[^\/@]+\/)?[^\/@]+)(?:@([^\/]+))?(\/.*)?$/ function decodeParam(param) { if (param) { try { return decodeURIComponent(param) : '' } catch (error) { // Ignore param parsing errors. } } return null } const ValidQueryKeys = { main: true, meta: true, json: true } function queryIsValid(query) { return Object.keys(query).every(function (key) { return ValidQueryKeys[key] }) } function parsePackageURL(packageURL) { const { pathname, search, query } = url.parse(packageURL, true) // Do not allow unrecognized query parameters because // some people use them to bust the cache. if (!queryIsValid(query)) return null const match = URLFormat.exec(pathname) if (match == null) return null const packageName = match[1] const packageVersion = decodeParam(match[2]) || 'latest' const filename = decodeParam(match[3]) return { // If the URL is /@scope/name@version/file.js?main=browser: pathname, // /@scope/name@version/path.js search, // ?main=browser query, // { main: 'browser' } packageName, // @scope/name packageVersion, // version filename // /file.js } } function createPackageURL(packageName, version, filename, search) { let pathname = `/${packageName}` if (version != null) pathname += `@${version}` if (filename) pathname += filename if (search) pathname += search return pathname } module.exports = { parse: parsePackageURL, create: createPackageURL }