diff --git a/.travis.yml b/.travis.yml index f77cd9a..4ad5b87 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,5 +2,4 @@ language: node_js sudo: false node_js: - "7" - - "6" - - "4" + - "6" \ No newline at end of file diff --git a/index.js b/index.js index d9a8373..b9a82ec 100644 --- a/index.js +++ b/index.js @@ -23,6 +23,9 @@ function pickManifest (packument, wanted, opts) { const versions = Object.keys(packument.versions || {}).filter(v => { return semver.valid(v, true) }) + const policyRestrictions = packument.policyRestrictions + const restrictedVersions = policyRestrictions + ? Object.keys(policyRestrictions.versions) : [] function enjoyableBy (v) { return !time || ( @@ -32,7 +35,7 @@ function pickManifest (packument, wanted, opts) { let err - if (!versions.length) { + if (!versions.length && !restrictedVersions.length) { err = new Error(`No valid versions available for ${packument.name}`) err.code = 'ENOVERSIONS' err.name = packument.name @@ -98,16 +101,24 @@ function pickManifest (packument, wanted, opts) { packument.versions[target] ) if (!manifest) { - err = new Error( - `No matching version found for ${packument.name}@${wanted}${ - opts.enjoyBy - ? ` with an Enjoy By date of ${ - new Date(opts.enjoyBy).toLocaleString() - }. Maybe try a different date?` - : '' - }` - ) - err.code = 'ETARGET' + // Check if target is forbidden + const isForbidden = target && policyRestrictions && policyRestrictions.versions[target] + const pckg = `${packument.name}@${wanted}${ + opts.enjoyBy + ? ` with an Enjoy By date of ${ + new Date(opts.enjoyBy).toLocaleString() + }. Maybe try a different date?` + : '' + }` + + if (isForbidden) { + err = new Error(`Could not download ${pckg} due to policy violations.\n${policyRestrictions.message}\n`) + err.code = 'E403' + } else { + err = new Error(`No matching version found for ${pckg}.`) + err.code = 'ETARGET' + } + err.name = packument.name err.type = type err.wanted = wanted diff --git a/test/index.js b/test/index.js index c583aec..d826d33 100644 --- a/test/index.js +++ b/test/index.js @@ -128,6 +128,25 @@ test('ETARGET if range does not match anything', t => { t.done() }) +test('E403 if version is forbidden', t => { + const metadata = { + policyRestrictions: { + versions: { + '2.1.0': { version: '2.1.0' } + } + }, + versions: { + '1.0.0': { version: '1.0.0' }, + '2.0.0': { version: '2.0.0' }, + '2.0.5': { version: '2.0.5' } + } + } + t.throws(() => { + pickManifest(metadata, '2.1.0') + }, {code: 'E403'}, 'got correct error on match failure') + t.done() +}) + test('if `defaultTag` matches a given range, use it', t => { const metadata = { 'dist-tags': { @@ -195,6 +214,16 @@ test('errors if metadata has no versions', t => { t.done() }) +test('errors if metadata has no versions or restricted versions', t => { + t.throws(() => { + pickManifest({versions: {}, policyRestrictions: { versions: {} }}, '^1.0.0') + }, {code: 'ENOVERSIONS'}) + t.throws(() => { + pickManifest({}, '^1.0.0') + }, {code: 'ENOVERSIONS'}) + t.done() +}) + test('matches even if requested version has spaces', t => { const metadata = { versions: {