From ede3c087007fd1808e02b1af70562220d03b18a9 Mon Sep 17 00:00:00 2001 From: isaacs Date: Thu, 13 Feb 2020 16:50:20 -0800 Subject: [PATCH 1/6] fix: Remove figgy-pudding, use canonical option names BREAKING CHANGE: this removes figgy-pudding, and drops several option aliases. Defaults and behavior are all the same, and this module is now using the canonical camelCase option names that npm v7 will provide to all its deps. Related to: https://github.com/npm/rfcs/pull/102 PR-URL: https://github.com/npm/npm-registry-fetch/pull/22 Credit: @isaacs Close: #22 Reviewed-by: @claudiahdz --- README.md | 48 +++++++---------- auth.js | 9 ++-- check-response.js | 7 +-- config.js | 92 --------------------------------- default-opts.js | 22 ++++++++ index.js | 78 +++++++++++++--------------- package.json | 1 - test/cache.js | 33 ++++++------ test/check-response.js | 20 ++++--- test/config.js | 30 ----------- test/errors.js | 10 ++-- test/index.js | 115 +++++++++++++++++++++++------------------ 12 files changed, 186 insertions(+), 279 deletions(-) delete mode 100644 config.js create mode 100644 default-opts.js delete mode 100644 test/config.js diff --git a/README.md b/README.md index 9b298868..da722827 100644 --- a/README.md +++ b/README.md @@ -181,7 +181,7 @@ to trust only that specific signing authority. Multiple CAs can be trusted by specifying an array of certificates instead of a single string. -See also [`opts.strict-ssl`](#opts-strict-ssl), [`opts.ca`](#opts-ca) and +See also [`opts.strictSSL`](#opts-strictSSL), [`opts.ca`](#opts-ca) and [`opts.key`](#opts-key) ##### `opts.cache` @@ -194,8 +194,8 @@ will be cached according to [IETF RFC 7234](https://tools.ietf.org/html/rfc7234) rules. This will speed up future requests, as well as make the cached data available offline if necessary/requested. -See also [`offline`](#opts-offline), [`prefer-offline`](#opts-prefer-offline), -and [`prefer-online`](#opts-prefer-online). +See also [`offline`](#opts-offline), [`preferOffline`](#opts-preferOffline), +and [`preferOnline`](#opts-preferOnline). ##### `opts.cert` @@ -216,7 +216,7 @@ It is _not_ the path to a certificate file (and there is no "certfile" option). See also: [`opts.ca`](#opts-ca) and [`opts.key`](#opts-key) -##### `opts.fetch-retries` +##### `opts.fetchRetries` * Type: Number * Default: 2 @@ -227,7 +227,7 @@ packages from the registry. See also [`opts.retry`](#opts-retry) to provide all retry options as a single object. -##### `opts.fetch-retry-factor` +##### `opts.fetchRetryFactor` * Type: Number * Default: 10 @@ -238,7 +238,7 @@ packages. See also [`opts.retry`](#opts-retry) to provide all retry options as a single object. -##### `opts.fetch-retry-mintimeout` +##### `opts.fetchRetryMintimeout` * Type: Number * Default: 10000 (10 seconds) @@ -249,7 +249,7 @@ packages. See also [`opts.retry`](#opts-retry) to provide all retry options as a single object. -##### `opts.fetch-retry-maxtimeout` +##### `opts.fetchRetryMaxtimeout` * Type: Number * Default: 60000 (1 minute) @@ -260,9 +260,8 @@ packages. See also [`opts.retry`](#opts-retry) to provide all retry options as a single object. -##### `opts.force-auth` +##### `opts.forceAuth` -* Alias: `opts.forceAuth` * Type: Object * Default: null @@ -288,9 +287,8 @@ Additional headers for the outgoing request. This option can also be used to override headers automatically generated by `npm-registry-fetch`, such as `Content-Type`. -##### `opts.ignore-body` +##### `opts.ignoreBody` -* Alias: `opts.ignoreBody` * Type: Boolean * Default: false @@ -317,9 +315,8 @@ previously-generated integrity hash for the saved request information, so `EINTEGRITY` errors can happen if [`opts.cache`](#opts-cache) is used, even if `opts.integrity` is not passed in. -##### `opts.is-from-ci` +##### `opts.isFromCI` -* Alias: `opts.isFromCI` * Type: Boolean * Default: Based on environment variables @@ -343,7 +340,7 @@ It is _not_ the path to a key file (and there is no "keyfile" option). See also: [`opts.ca`](#opts-ca) and [`opts.cert`](#opts-cert) -##### `opts.local-address` +##### `opts.localAddress` * Type: IP Address String * Default: null @@ -361,9 +358,8 @@ See also [`opts.proxy`](#opts-proxy) Logger object to use for logging operation details. Must have the same methods as `npmlog`. -##### `opts.map-json` +##### `opts.mapJSON` -* Alias: `mapJson`, `mapJSON` * Type: Function * Default: undefined @@ -371,9 +367,8 @@ When using `fetch.json.stream()` (NOT `fetch.json()`), this will be passed down to [`JSONStream`](https://npm.im/JSONStream) as the second argument to `JSONStream.parse`, and can be used to transform stream data before output. -##### `opts.maxsockets` +##### `opts.maxSockets` -* Alias: `opts.max-sockets` * Type: Integer * Default: 12 @@ -394,9 +389,8 @@ HTTP method to use for the outgoing request. Case-insensitive. If true, proxying will be disabled even if [`opts.proxy`](#opts-proxy) is used. -##### `opts.npm-session` +##### `opts.npmSession` -* Alias: `opts.npmSession` * Type: String * Default: null @@ -411,7 +405,7 @@ invocations of the CLI). Force offline mode: no network requests will be done during install. To allow `npm-registry-fetch` to fill in missing cache data, see -[`opts.prefer-offline`](#opts-prefer-offline). +[`opts.preferOffline`](#opts-preferOffline). This option is only really useful if you're also using [`opts.cache`](#opts-cache). @@ -448,7 +442,7 @@ That is: See also [`opts.username`](#opts-username) -##### `opts.prefer-offline` +##### `opts.preferOffline` * Type: Boolean * Default: false @@ -463,7 +457,7 @@ This option is generally only useful if you're also using This option is set to `false` when the request includes `write=true` in the query string. -##### `opts.prefer-online` +##### `opts.preferOnline` * Type: Boolean * Default: false @@ -477,9 +471,8 @@ This option is generally only useful if you're also using This option is set to `true` when the request includes `write=true` in the query string. -##### `opts.project-scope` +##### `opts.projectScope` -* Alias: `opts.projectScope` * Type: String * Default: null @@ -510,7 +503,6 @@ If the request URI already has a query string, it will be merged with ##### `opts.refer` -* Alias: `opts.referer` * Type: String * Default: null @@ -574,7 +566,7 @@ If provided, can be used to automatically configure [`opts.scope`](#opts-scope) based on a specific package name. Non-registry package specs will throw an error. -##### `opts.strict-ssl` +##### `opts.strictSSL` * Type: Boolean * Default: true @@ -607,7 +599,7 @@ Can be scoped to a registry by using a "nerf dart" for that registry. That is: } ``` -##### `opts.user-agent` +##### `opts.userAgent` * Type: String * Default: `'npm-registry-fetch@/node@+ ()'` diff --git a/auth.js b/auth.js index 3198b9c4..11c3bde6 100644 --- a/auth.js +++ b/auth.js @@ -1,17 +1,14 @@ 'use strict' -const config = require('./config.js') +const defaultOpts = require('./default-opts.js') const url = require('url') module.exports = getAuth -function getAuth (registry, opts) { +function getAuth (registry, opts_ = {}) { if (!registry) { throw new Error('registry is required') } - opts = config(opts) + const opts = opts_.forceAuth ? opts_.forceAuth : { ...defaultOpts, ...opts_ } const AUTH = {} const regKey = registry && registryKey(registry) - if (opts.forceAuth) { - opts = opts.forceAuth - } const doKey = (key, alias) => addKey(opts, AUTH, regKey, key, alias) doKey('token') doKey('_authToken', 'token') diff --git a/check-response.js b/check-response.js index 3137ea71..933c8f7c 100644 --- a/check-response.js +++ b/check-response.js @@ -1,12 +1,13 @@ 'use strict' -const config = require('./config.js') const errors = require('./errors.js') const LRU = require('lru-cache') const { Response } = require('minipass-fetch') +const defaultOpts = require('./default-opts.js') + module.exports = checkResponse -function checkResponse (method, res, registry, startTime, opts) { - opts = config(opts) +function checkResponse (method, res, registry, startTime, opts_ = {}) { + const opts = { ...defaultOpts, ...opts_ } if (res.headers.has('npm-notice') && !res.headers.has('x-local-cache')) { opts.log.notice('', res.headers.get('npm-notice')) } diff --git a/config.js b/config.js deleted file mode 100644 index d6681d09..00000000 --- a/config.js +++ /dev/null @@ -1,92 +0,0 @@ -'use strict' - -const pkg = require('./package.json') -const figgyPudding = require('figgy-pudding') -const silentLog = require('./silentlog.js') -const ciDetect = require('@npmcli/ci-detect') - -const AUTH_REGEX = /^(?:.*:)?(token|_authToken|username|_password|password|email|always-auth|_auth|otp)$/ -const SCOPE_REGISTRY_REGEX = /@.*:registry$/gi -module.exports = figgyPudding({ - agent: {}, - algorithms: {}, - body: {}, - ca: {}, - cache: {}, - cert: {}, - 'fetch-retries': {}, - 'fetch-retry-factor': {}, - 'fetch-retry-maxtimeout': {}, - 'fetch-retry-mintimeout': {}, - 'force-auth': {}, - forceAuth: 'force-auth', - gzip: {}, - headers: {}, - 'https-proxy': {}, - 'ignore-body': {}, - ignoreBody: 'ignore-body', - integrity: {}, - 'is-from-ci': 'isFromCI', - isFromCI: { - default () { - return ciDetect() - } - }, - key: {}, - 'local-address': {}, - log: { - default: silentLog - }, - 'map-json': 'mapJson', - mapJSON: 'mapJson', - mapJson: {}, - 'max-sockets': 'maxsockets', - maxsockets: { - default: 12 - }, - memoize: {}, - method: { - default: 'GET' - }, - 'no-proxy': {}, - noproxy: {}, - 'npm-session': 'npmSession', - npmSession: {}, - offline: {}, - otp: {}, - 'prefer-offline': {}, - 'prefer-online': {}, - projectScope: {}, - 'project-scope': 'projectScope', - proxy: {}, - query: {}, - refer: {}, - referer: 'refer', - registry: { - default: 'https://registry.npmjs.org/' - }, - retry: {}, - scope: {}, - spec: {}, - 'strict-ssl': {}, - timeout: { - default: 30 * 1000 - }, - 'user-agent': { - default: `${ - pkg.name - }@${ - pkg.version - }/node@${ - process.version - }+${ - process.arch - } (${ - process.platform - })` - } -}, { - other (key) { - return key.match(AUTH_REGEX) || key.match(SCOPE_REGISTRY_REGEX) - } -}) diff --git a/default-opts.js b/default-opts.js new file mode 100644 index 00000000..4d51da47 --- /dev/null +++ b/default-opts.js @@ -0,0 +1,22 @@ +const pkg = require('./package.json') +const ciDetect = require('@npmcli/ci-detect') +module.exports = { + isFromCI: ciDetect(), + log: require('./silentlog.js'), + maxSockets: 12, + method: 'GET', + registry: 'https://registry.npmjs.org/', + timeout: 30 * 1000, + strictSSL: true, + noProxy: process.env.NOPROXY, + userAgent: `${pkg.name + }@${ + pkg.version + }/node@${ + process.version + }+${ + process.arch + } (${ + process.platform + })` +} diff --git a/index.js b/index.js index 6a0b110d..9efb7c02 100644 --- a/index.js +++ b/index.js @@ -2,9 +2,7 @@ const Buffer = require('safe-buffer').Buffer -const ciDetect = require('@npmcli/ci-detect') const checkResponse = require('./check-response.js') -const config = require('./config.js') const getAuth = require('./auth.js') const fetch = require('make-fetch-happen') const JSONStream = require('minipass-json-stream') @@ -14,6 +12,8 @@ const url = require('url') const zlib = require('minizlib') const Minipass = require('minipass') +const defaultOpts = require('./default-opts.js') + // WhatWG URL throws if it's not fully resolved const urlIsValid = u => { try { @@ -24,12 +24,15 @@ const urlIsValid = u => { } module.exports = regFetch -function regFetch (uri, opts) { - opts = config(opts) - const registry = ( +function regFetch (uri, /* istanbul ignore next */ opts_ = {}) { + const opts = { + ...defaultOpts, + ...opts_ + } + const registry = opts.registry = ( (opts.spec && pickRegistry(opts.spec, opts)) || opts.registry || - /* istanbul ignore next: default set in figgy pudding config */ + /* istanbul ignore next */ 'https://registry.npmjs.org/' ) @@ -41,9 +44,7 @@ function regFetch (uri, opts) { }` } - const method = opts.method || - /* istanbul ignore next: default set in figgy pudding config */ - 'GET' + const method = opts.method || 'GET' // through that takes into account the scope, the prefix of `uri`, etc const startTime = Date.now() @@ -92,11 +93,9 @@ function regFetch (uri, opts) { // do not cache, because this GET is fetching a rev that will be // used for a subsequent PUT or DELETE, so we need to conditionally // update cache. - opts = opts.concat({ - offline: false, - 'prefer-offline': false, - 'prefer-online': true - }) + opts.offline = false + opts.preferOffline = false + opts.preferOnline = true } const doFetch = (body) => fetch(uri, { @@ -110,21 +109,21 @@ function regFetch (uri, opts) { headers, integrity: opts.integrity, key: opts.key, - localAddress: opts['local-address'], - maxSockets: opts.maxsockets, + localAddress: opts.localAddress, + maxSockets: opts.maxSockets, memoize: opts.memoize, method: method, - noProxy: opts['no-proxy'] || opts.noproxy, - proxy: opts['https-proxy'] || opts.proxy, + noProxy: opts.noProxy, + proxy: opts.httpsProxy || opts.proxy, referer: opts.refer, - retry: opts.retry != null ? opts.retry : { - retries: opts['fetch-retries'], - factor: opts['fetch-retry-factor'], - minTimeout: opts['fetch-retry-mintimeout'], - maxTimeout: opts['fetch-retry-maxtimeout'] + retry: opts.retry ? opts.retry : { + retries: opts.fetchRetries, + factor: opts.fetchRetryFactor, + minTimeout: opts.fetchRetryMintimeout, + maxTimeout: opts.fetchRetryMaxtimeout }, - strictSSL: !!opts['strict-ssl'], - timeout: opts.timeout + strictSSL: opts.strictSSL, + timeout: opts.timeout || 30 * 1000 }).then(res => checkResponse( method, res, registry, startTime, opts )) @@ -138,9 +137,9 @@ function fetchJSON (uri, opts) { } module.exports.json.stream = fetchJSONStream -function fetchJSONStream (uri, jsonPath, opts) { - opts = config(opts) - const parser = JSONStream.parse(jsonPath, opts.mapJson) +function fetchJSONStream (uri, jsonPath, /* istanbul ignore next */ opts_ = {}) { + const opts = { ...defaultOpts, ...opts_ } + const parser = JSONStream.parse(jsonPath, opts.mapJSON) regFetch(uri, opts).then(res => res.body.on('error', /* istanbul ignore next: unlikely and difficult to test */ @@ -150,9 +149,8 @@ function fetchJSONStream (uri, jsonPath, opts) { } module.exports.pickRegistry = pickRegistry -function pickRegistry (spec, opts) { +function pickRegistry (spec, opts = {}) { spec = npa(spec) - opts = config(opts) let registry = spec.scope && opts[spec.scope.replace(/^@?/, '@') + ':registry'] @@ -161,9 +159,7 @@ function pickRegistry (spec, opts) { } if (!registry) { - registry = opts.registry || - /* istanbul ignore next: default set by figgy pudding config */ - 'https://registry.npmjs.org/' + registry = opts.registry || 'https://registry.npmjs.org/' } return registry @@ -172,23 +168,21 @@ function pickRegistry (spec, opts) { function getCacheMode (opts) { return opts.offline ? 'only-if-cached' - : opts['prefer-offline'] + : opts.preferOffline ? 'force-cache' - : opts['prefer-online'] + : opts.preferOnline ? 'no-cache' : 'default' } function getHeaders (registry, uri, opts) { const headers = Object.assign({ - 'npm-in-ci': !!( - opts['is-from-ci'] || ciDetect() - ), - 'npm-scope': opts['project-scope'], - 'npm-session': opts['npm-session'], - 'user-agent': opts['user-agent'], + 'npm-in-ci': !!opts.isFromCI, + 'npm-scope': opts.projectScope, + 'npm-session': opts.npmSession, + 'user-agent': opts.userAgent, referer: opts.refer - }, opts.headers) + }, opts.headers || {}) const auth = getAuth(registry, opts) // If a tarball is hosted on a different place than the manifest, only send diff --git a/package.json b/package.json index b685796f..5147d17f 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "license": "ISC", "dependencies": { "@npmcli/ci-detect": "^1.0.0", - "figgy-pudding": "^3.4.1", "lru-cache": "^5.1.1", "make-fetch-happen": "^7.1.0", "minipass": "^3.0.0", diff --git a/test/cache.js b/test/cache.js index 97f7092c..82f10d20 100644 --- a/test/cache.js +++ b/test/cache.js @@ -2,7 +2,6 @@ const { promisify } = require('util') const statAsync = promisify(require('fs').stat) -const config = require('../config.js') const npmlog = require('npmlog') const path = require('path') const test = require('tap').test @@ -14,7 +13,7 @@ const testDir = require('./util/test-dir.js')(__filename) npmlog.level = process.env.LOGLEVEL || 'silent' const REGISTRY = 'https://mock.reg' -const OPTS = config({ +const OPTS = { log: npmlog, memoize: false, timeout: 0, @@ -26,7 +25,7 @@ const OPTS = config({ }, cache: path.join(testDir, '_cacache'), registry: REGISTRY -}) +} test('can cache GET requests', t => { tnock(t, REGISTRY) @@ -35,22 +34,22 @@ test('can cache GET requests', t => { .reply(200, { obj: 'value' }) return fetch.json('/normal', OPTS) .then(val => t.deepEqual(val, { obj: 'value' }, 'got expected response')) - .then(() => statAsync(OPTS.get('cache'))) + .then(() => statAsync(OPTS.cache)) .then(stat => t.ok(stat.isDirectory(), 'cache directory created')) .then(() => fetch.json('/normal', OPTS)) .then(val => t.deepEqual(val, { obj: 'value' }, 'response was cached')) }) -test('prefer-offline', t => { +test('preferOffline', t => { tnock(t, REGISTRY) - .get('/prefer-offline') + .get('/preferOffline') .times(1) .reply(200, { obj: 'value' }) - return fetch.json('/prefer-offline', OPTS.concat({ 'prefer-offline': true })) + return fetch.json('/preferOffline', { ...OPTS, preferOffline: true }) .then(val => t.deepEqual(val, { obj: 'value' }, 'got expected response')) - .then(() => statAsync(OPTS.get('cache'))) + .then(() => statAsync(OPTS.cache)) .then(stat => t.ok(stat.isDirectory(), 'cache directory created')) - .then(() => fetch.json('/prefer-offline', OPTS.concat({ 'prefer-offline': true }))) + .then(() => fetch.json('/preferOffline', { ...OPTS, preferOffline: true })) .then(val => t.deepEqual(val, { obj: 'value' }, 'response was cached')) }) @@ -61,24 +60,24 @@ test('offline', t => { .reply(200, { obj: 'value' }) return fetch.json('/offline', OPTS) .then(val => t.deepEqual(val, { obj: 'value' }, 'got expected response')) - .then(() => statAsync(OPTS.get('cache'))) + .then(() => statAsync(OPTS.cache)) .then(stat => t.ok(stat.isDirectory(), 'cache directory created')) - .then(() => fetch.json('/offline', OPTS.concat({ offline: true }))) + .then(() => fetch.json('/offline', { ...OPTS, offline: true })) .then(val => t.deepEqual(val, { obj: 'value' }, 'response was cached')) }) test('offline fails if not cached', t => - t.rejects(() => fetch('/offline-fails', OPTS.concat({ offline: true })))) + t.rejects(() => fetch('/offline-fails', { ...OPTS, offline: true }))) -test('prefer-online', t => { +test('preferOnline', t => { tnock(t, REGISTRY) - .get('/prefer-online') + .get('/preferOnline') .times(2) .reply(200, { obj: 'value' }) - return fetch.json('/prefer-online', OPTS) + return fetch.json('/preferOnline', OPTS) .then(val => t.deepEqual(val, { obj: 'value' }, 'got expected response')) - .then(() => statAsync(OPTS.get('cache'))) + .then(() => statAsync(OPTS.cache)) .then(stat => t.ok(stat.isDirectory(), 'cache directory created')) - .then(() => fetch.json('/prefer-online', OPTS.concat({ 'prefer-online': true }))) + .then(() => fetch.json('/preferOnline', { ...OPTS, preferOnline: true })) .then(val => t.deepEqual(val, { obj: 'value' }, 'response was refetched')) }) diff --git a/test/check-response.js b/test/check-response.js index 1be14360..95566088 100644 --- a/test/check-response.js +++ b/test/check-response.js @@ -1,7 +1,6 @@ const { Readable } = require('stream') const test = require('tap').test -const config = require('../config.js') const checkResponse = require('../check-response.js') const errors = require('./errors.js') const silentLog = require('../silentlog.js') @@ -27,7 +26,16 @@ test('any response error should be silent', t => { status: 400 }) t.rejects(checkResponse('get', res, 'registry', Date.now(), { ignoreBody: true }), errors.HttpErrorGeneral) - t.done() + t.end() +}) + +test('all checks are ok, nothing to report', t => { + const res = Object.assign({}, mockFetchRes, { + buffer: () => Promise.resolve(Buffer.from('ok')), + status: 400 + }) + t.rejects(checkResponse('get', res, 'registry', Date.now()), errors.HttpErrorGeneral) + t.end() }) test('log x-fetch-attempts header value', t => { @@ -37,13 +45,13 @@ test('log x-fetch-attempts header value', t => { headers, status: 400 }) - t.rejects(checkResponse('get', res, 'registry', Date.now(), config({ + t.rejects(checkResponse('get', res, 'registry', Date.now(), { log: Object.assign({}, silentLog, { http (header, msg) { t.ok(msg.endsWith('attempt #3'), 'should log correct number of attempts') } }) - }))) + })) t.plan(2) }) @@ -56,12 +64,12 @@ test('bad-formatted warning headers', t => { const res = Object.assign({}, mockFetchRes, { headers }) - t.ok(checkResponse('get', res, 'registry', Date.now(), config({ + t.ok(checkResponse('get', res, 'registry', Date.now(), { log: Object.assign({}, silentLog, { warn (header, msg) { t.fail('should not log warnings') } }) - }))) + })) t.plan(1) }) diff --git a/test/config.js b/test/config.js deleted file mode 100644 index c64a295d..00000000 --- a/test/config.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict' - -const requireInject = require('require-inject') -const config = requireInject('../config.js', { - '@npmcli/ci-detect': () => false -}) -const npmlog = require('npmlog') -const { test } = require('tap') - -npmlog.level = process.env.LOGLEVEL || 'silent' - -test('isFromCI config option', t => { - const OPTS = config({ - log: npmlog, - timeout: 0, - registry: 'https://mock.reg/' - }) - t.equal(OPTS.isFromCI, false, 'should be false if not on a CI env') - t.end() -}) - -test('default timeout', t => { - const DEFAULT_OPTS = config({}) - t.equal(DEFAULT_OPTS.timeout, 30 * 1000, 'default timeout is 30s') - const SPECIFIED_OPTS = config({ - timeout: 15 * 1000 - }) - t.equal(SPECIFIED_OPTS.timeout, 15 * 1000, 'default timeout can be overridden') - t.end() -}) diff --git a/test/errors.js b/test/errors.js index 54d7de1a..e3ab7c5f 100644 --- a/test/errors.js +++ b/test/errors.js @@ -1,6 +1,5 @@ 'use strict' -const config = require('../config.js') const npa = require('npm-package-arg') const npmlog = require('npmlog') const test = require('tap').test @@ -9,7 +8,7 @@ const tnock = require('./util/tnock.js') const fetch = require('../index.js') npmlog.level = process.env.LOGLEVEL || 'silent' -const OPTS = config({ +const OPTS = { log: npmlog, timeout: 0, retry: { @@ -19,7 +18,7 @@ const OPTS = config({ maxTimeout: 10 }, registry: 'https://mock.reg/' -}) +} test('generic request errors', t => { tnock(t, OPTS.registry) @@ -69,9 +68,10 @@ test('pkgid with `opts.spec`', t => { tnock(t, OPTS.registry) .get('/ohno/_rewrite/ohyeah') .reply(400, 'failwhale!') - return fetch('/ohno/_rewrite/ohyeah', OPTS.concat({ + return fetch('/ohno/_rewrite/ohyeah', { + ...OPTS, spec: npa('foo@1.2.3') - })) + }) .then( () => { throw new Error('should not have succeeded!') }, err => t.equal(err.pkgid, 'foo@1.2.3', 'opts.spec used for pkgid') diff --git a/test/index.js b/test/index.js index ea251721..50f64291 100644 --- a/test/index.js +++ b/test/index.js @@ -2,7 +2,6 @@ const Buffer = require('safe-buffer').Buffer -const config = require('../config.js') const Minipass = require('minipass') const npmlog = require('npmlog') const silentLog = require('../silentlog.js') @@ -14,7 +13,7 @@ const zlib = require('zlib') const fetch = require('../index.js') npmlog.level = process.env.LOGLEVEL || 'silent' -const OPTS = config({ +const OPTS = { // just to make sure we hit the second branch when // we are ACTUALLY in CI isFromCI: false, @@ -27,13 +26,16 @@ const OPTS = config({ maxTimeout: 10 }, registry: 'https://mock.reg/' -}) +} test('hello world', t => { tnock(t, OPTS.registry) .get('/hello') .reply(200, { hello: 'world' }) - return fetch('/hello', OPTS) + return fetch('/hello', { + method: false, // will fall back to GET if falsey, + ...OPTS + }) .then(res => { t.equal(res.status, 200, 'got successful response') return res.json() @@ -54,10 +56,11 @@ test('JSON body param', t => { }, 'got the JSON version of the body') return reqBody }) - const opts = OPTS.concat({ + const opts = { + ...OPTS, method: 'POST', body: { hello: 'world' } - }) + } return fetch('/hello', opts) .then(res => { t.equal(res.status, 200) @@ -81,10 +84,11 @@ test('buffer body param', t => { ) return reqBody }) - const opts = OPTS.concat({ + const opts = { + ...OPTS, method: 'POST', body: Buffer.from('hello', 'utf8') - }) + } return fetch('/hello', opts) .then(res => { t.equal(res.status, 200) @@ -110,10 +114,11 @@ test('stream body param', t => { }) const stream = new Minipass() setImmediate(() => stream.end(JSON.stringify({ hello: 'world' }))) - const opts = OPTS.concat({ + const opts = { + ...OPTS, method: 'POST', body: stream - }) + } return fetch('/hello', opts) .then(res => { t.equal(res.status, 200) @@ -135,11 +140,12 @@ test('JSON body param', t => { .post('/hello') // NOTE: can't really test the body itself here because nock freaks out. .reply(200) - const opts = OPTS.concat({ + const opts = { + ...OPTS, method: 'POST', body: { hello: 'world' }, gzip: true - }) + } return fetch('/hello', opts) .then(res => { t.equal(res.status, 200, 'request succeeded') @@ -166,11 +172,12 @@ test('gzip + buffer body param', t => { ) return reqBody }) - const opts = OPTS.concat({ + const opts = { + ...OPTS, method: 'POST', body: Buffer.from('hello', 'utf8'), gzip: true - }) + } return fetch('/hello', opts) .then(res => { t.equal(res.status, 200) @@ -201,7 +208,8 @@ test('gzip + stream body param', t => { }) const stream = new Minipass() setImmediate(() => stream.end(JSON.stringify({ hello: 'world' }))) - const opts = OPTS.concat({ + const opts = { + ...OPTS, method: 'POST', body: stream, gzip: true, @@ -209,7 +217,7 @@ test('gzip + stream body param', t => { everything: undefined, is: undefined } - }) + } return fetch('/hello', opts) .then(res => { t.equal(res.status, 200) @@ -222,18 +230,20 @@ test('query strings', t => { tnock(t, OPTS.registry) .get('/hello?hi=there&who=wor%20ld') .reply(200, { hello: 'world' }) - return fetch.json('/hello?hi=there', OPTS.concat({ + return fetch.json('/hello?hi=there', { + ...OPTS, query: 'who=wor ld' - })).then(json => t.equal(json.hello, 'world', 'query-string merged')) + }).then(json => t.equal(json.hello, 'world', 'query-string merged')) }) test('query strings - undefined values', t => { tnock(t, OPTS.registry) .get('/hello?who=wor%20ld') .reply(200, { ok: true }) - return fetch.json('/hello', OPTS.concat({ + return fetch.json('/hello', { + ...OPTS, query: { hi: undefined, who: 'wor ld' } - })).then(json => t.ok(json.ok, 'undefined keys not included in query string')) + }).then(json => t.ok(json.ok, 'undefined keys not included in query string')) }) test('json()', t => { @@ -246,25 +256,25 @@ test('json()', t => { test('query string with ?write=true', t => { const cache = t.testdir() - const opts = OPTS.concat({ 'prefer-offline': true, cache }) - const qsString = opts.concat({ query: { write: 'true' } }) - const qsBool = opts.concat({ query: { write: true } }) + const opts = { ...OPTS, preferOffline: true, cache } + const qsString = { ...opts, query: { write: 'true' } } + const qsBool = { ...opts, query: { write: true } } tnock(t, opts.registry) - .get('/hello?write=true') + .get('/writeTrueTest?write=true') .times(6) .reply(200, { write: 'go for it' }) - return fetch.json('/hello?write=true', opts) + return fetch.json('/writeTrueTest?write=true', opts) .then(res => t.strictSame(res, { write: 'go for it' })) - .then(() => fetch.json('/hello?write=true', opts)) + .then(() => fetch.json('/writeTrueTest?write=true', opts)) .then(res => t.strictSame(res, { write: 'go for it' })) - .then(() => fetch.json('/hello', qsString)) + .then(() => fetch.json('/writeTrueTest', qsString)) .then(res => t.strictSame(res, { write: 'go for it' })) - .then(() => fetch.json('/hello', qsString)) + .then(() => fetch.json('/writeTrueTest', qsString)) .then(res => t.strictSame(res, { write: 'go for it' })) - .then(() => fetch.json('/hello', qsBool)) + .then(() => fetch.json('/writeTrueTest', qsBool)) .then(res => t.strictSame(res, { write: 'go for it' })) - .then(() => fetch.json('/hello', qsBool)) + .then(() => fetch.json('/writeTrueTest', qsBool)) .then(res => t.strictSame(res, { write: 'go for it' })) }) @@ -283,17 +293,18 @@ test('fetch.json.stream()', t => { }) }) -test('fetch.json.stream opts.mapJson', t => { +test('fetch.json.stream opts.mapJSON', t => { tnock(t, OPTS.registry).get('/hello').reply(200, { a: 1, b: 2, c: 3 }) - return fetch.json.stream('/hello', '*', OPTS.concat({ - mapJson (value, [key]) { + return fetch.json.stream('/hello', '*', { + ...OPTS, + mapJSON (value, [key]) { return [key, value] } - })).collect().then(data => { + }).collect().then(data => { t.deepEqual(data, [ ['a', 1], ['b', 2], @@ -303,11 +314,12 @@ test('fetch.json.stream opts.mapJson', t => { }) test('fetch.json.stream gets fetch error on stream', t => { - return t.rejects(fetch.json.stream('/hello', '*', OPTS.concat({ + return t.rejects(fetch.json.stream('/hello', '*', { + ...OPTS, body: Promise.reject(new Error('no body for you')), method: 'POST', gzip: true // make sure we don't gzip the promise, lol! - })).collect(), { + }).collect(), { message: 'no body for you' }) }) @@ -316,7 +328,7 @@ test('opts.ignoreBody', t => { tnock(t, OPTS.registry) .get('/hello') .reply(200, { hello: 'world' }) - return fetch('/hello', OPTS.concat({ ignoreBody: true })) + return fetch('/hello', { ...OPTS, ignoreBody: true }) .then(res => { t.equal(res.body, null, 'body omitted') }) @@ -326,9 +338,10 @@ test('method configurable', t => { tnock(t, OPTS.registry) .delete('/hello') .reply(200) - const opts = OPTS.concat({ + const opts = { + ...OPTS, method: 'DELETE' - }) + } return fetch('/hello', opts) .then(res => { t.equal(res.status, 200, 'successfully used DELETE method') @@ -341,14 +354,15 @@ test('npm-notice header logging', t => { .reply(200, { hello: 'world' }, { 'npm-notice': 'npm <3 u' }) - const opts = OPTS.concat({ + const opts = { + ...OPTS, log: Object.assign({}, silentLog, { notice (header, msg) { t.equal(header, '', 'empty log header thing') t.equal(msg, 'npm <3 u', 'logged out npm-notice at NOTICE level') } }) - }) + } t.plan(3) return fetch('/hello', opts) .then(res => t.equal(res.status, 200, 'got successful response')) @@ -361,13 +375,13 @@ test('optionally verifies request body integrity', t => { .times(2) .reply(200, 'hello') const integrity = ssri.fromData('hello') - return fetch('/hello', OPTS.concat({ integrity })) + return fetch('/hello', { ...OPTS, integrity }) .then(res => res.buffer()) .then(buf => t.equal( buf.toString('utf8'), 'hello', 'successfully got the right data') ) .then(() => { - return fetch('/hello', OPTS.concat({ integrity: 'sha1-nope' })) + return fetch('/hello', { ...OPTS, integrity: 'sha1-nope' }) .then(res => { t.ok(res.body, 'no error until body starts getting read') return res @@ -422,18 +436,20 @@ test('pickRegistry through opts.spec', t => { .get('/pkg') .times(2) .reply(200, { source: scopedReg }) - return fetch.json('/pkg', OPTS.concat({ + return fetch.json('/pkg', { + ...OPTS, spec: 'pkg@1.2.3', '@myscope:registry': scopedReg - })).then(json => t.equal( + }).then(json => t.equal( json.source, OPTS.registry, 'request made to main registry' - )).then(() => fetch.json('/pkg', OPTS.concat({ + )).then(() => fetch.json('/pkg', { + ...OPTS, spec: 'pkg@1.2.3', '@myscope:registry': scopedReg, scope: '@myscope' - }))).then(json => t.equal( + })).then(json => t.equal( json.source, scopedReg, 'request made to scope registry using opts.scope' @@ -451,14 +467,15 @@ test('log warning header info', t => { tnock(t, OPTS.registry) .get('/hello') .reply(200, { hello: 'world' }, { Warning: '199 - "ENOTFOUND" "Wed, 21 Oct 2015 07:28:00 GMT"' }) - const opts = OPTS.concat({ + const opts = { + ...OPTS, log: Object.assign({}, silentLog, { warn (header, msg) { t.equal(header, 'registry', 'expected warn log header') t.equal(msg, `Using stale data from ${OPTS.registry} because the host is inaccessible -- are you offline?`, 'logged out at WARNING level') } }) - }) + } t.plan(3) return fetch('/hello', opts) .then(res => t.equal(res.status, 200, 'got successful response')) From 6bccc1a398dde6b707f4d499468837bf9b5f3949 Mon Sep 17 00:00:00 2001 From: isaacs Date: Mon, 17 Feb 2020 16:29:30 -0800 Subject: [PATCH 2/6] chore: remove extraneous semver dep Fix #17 --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 5147d17f..f0de2f8f 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,7 @@ "minipass-json-stream": "^1.0.1", "minizlib": "^2.0.0", "npm-package-arg": "^8.0.0", - "safe-buffer": "^5.2.0", - "semver": "^7.0.0" + "safe-buffer": "^5.2.0" }, "devDependencies": { "cacache": "^13.0.1", From 152e666f2e1e91f82cf08cf8fc06353e4ce0a3bc Mon Sep 17 00:00:00 2001 From: isaacs Date: Mon, 17 Feb 2020 16:30:14 -0800 Subject: [PATCH 3/6] chore: remove extraneous safe-buffer dep Node Date: Mon, 17 Feb 2020 17:42:08 -0800 Subject: [PATCH 4/6] chore: update cacache, ssri, make-fetch-happen BREAKING CHANGE: figgy pudding is now nowhere to be found. --- package-lock.json | 89 ++++++++++++++++++++++++++++++----------------- package.json | 6 ++-- 2 files changed, 60 insertions(+), 35 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9fca789f..e7af4474 100644 --- a/package-lock.json +++ b/package-lock.json @@ -416,28 +416,34 @@ "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=" }, "cacache": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", - "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.0.tgz", + "integrity": "sha512-L0JpXHhplbJSiDGzyJJnJCTL7er7NzbBgxzVqLswEb4bO91Zbv17OUMuUeu/q0ZwKn3V+1HM4wb9tO4eVE/K8g==", "requires": { "chownr": "^1.1.2", - "figgy-pudding": "^3.5.1", "fs-minipass": "^2.0.0", "glob": "^7.1.4", - "graceful-fs": "^4.2.2", "infer-owner": "^1.0.4", "lru-cache": "^5.1.1", - "minipass": "^3.0.0", + "minipass": "^3.1.1", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.2", - "mkdirp": "^0.5.1", + "mkdirp": "^1.0.3", "move-concurrently": "^1.0.1", "p-map": "^3.0.0", "promise-inflight": "^1.0.1", "rimraf": "^2.7.1", - "ssri": "^7.0.0", + "ssri": "^8.0.0", + "tar": "^6.0.1", "unique-filename": "^1.1.1" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.3.tgz", + "integrity": "sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g==" + } } }, "caching-transform": { @@ -554,9 +560,9 @@ } }, "chownr": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", - "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "clean-stack": { "version": "2.2.0", @@ -1911,11 +1917,6 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==" - }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -2145,9 +2146,9 @@ "dev": true }, "fs-minipass": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.0.0.tgz", - "integrity": "sha512-40Qz+LFXmd9tzYVnnBmZvFfvAADfUA14TXPK1s7IfElJTIZ97rA8w4Kin7Wt5JBrC3ShnnFJO/5vPjPEeJIq9A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "requires": { "minipass": "^3.0.0" } @@ -2756,9 +2757,9 @@ } }, "http-cache-semantics": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", - "integrity": "sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==" + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-Z2EICWNJou7Tr9Bd2M2UqDJq3A9F2ePG9w3lIpjoyuSyXFP9QbniJVu3XQYytuw5ebmG7dXSXO9PgAjJG8DDKA==" }, "http-proxy-agent": { "version": "3.0.0", @@ -3515,13 +3516,13 @@ "dev": true }, "make-fetch-happen": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-7.1.0.tgz", - "integrity": "sha512-/5ICTcpd4ApIRn76pxcl4aQhrWxdDCnRDy3y+Tu7DbRsfqde6q8OYXUm7bYhH5dSey590AMT0RH9LDFq7v5KRA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.1.tgz", + "integrity": "sha512-oiK8xz6+IxaPqmOCW+rmlH922RTZ+fi4TAULGRih8ryqIju0x6WriDR3smm7Z+8NZRxDIK/iDLM096F/gLfiWg==", "requires": { "agentkeepalive": "^4.1.0", - "cacache": "^13.0.1", - "http-cache-semantics": "^4.0.3", + "cacache": "^15.0.0", + "http-cache-semantics": "^4.0.4", "http-proxy-agent": "^3.0.0", "https-proxy-agent": "^4.0.0", "is-lambda": "^1.0.1", @@ -3533,7 +3534,7 @@ "minipass-pipeline": "^1.2.2", "promise-retry": "^1.1.1", "socks-proxy-agent": "^4.0.0", - "ssri": "^7.0.1" + "ssri": "^8.0.0" } }, "map-obj": { @@ -4984,11 +4985,10 @@ } }, "ssri": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz", - "integrity": "sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", + "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", "requires": { - "figgy-pudding": "^3.5.1", "minipass": "^3.1.1" } }, @@ -6358,6 +6358,31 @@ "yaml": "^1.5.0" } }, + "tar": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.0.1.tgz", + "integrity": "sha512-bKhKrrz2FJJj5s7wynxy/fyxpE0CmCjmOQ1KV4KkgXFWOgoIT/NbTMnB1n+LFNrNk0SSBVGGxcK5AGsyC+pW5Q==", + "requires": { + "chownr": "^1.1.3", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.0", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.3.tgz", + "integrity": "sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, "tcompare": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/tcompare/-/tcompare-3.0.4.tgz", diff --git a/package.json b/package.json index 055f224b..4c6acecc 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "dependencies": { "@npmcli/ci-detect": "^1.0.0", "lru-cache": "^5.1.1", - "make-fetch-happen": "^7.1.0", + "make-fetch-happen": "^8.0.1", "minipass": "^3.0.0", "minipass-fetch": "^1.1.2", "minipass-json-stream": "^1.0.1", @@ -38,13 +38,13 @@ "npm-package-arg": "^8.0.0" }, "devDependencies": { - "cacache": "^13.0.1", + "cacache": "^15.0.0", "mkdirp": "^0.5.1", "nock": "^11.7.0", "npmlog": "^4.1.2", "require-inject": "^1.4.4", "rimraf": "^2.6.2", - "ssri": "^7.1.0", + "ssri": "^8.0.0", "standard": "^14.3.1", "standard-version": "^7.0.1", "tap": "^14.10.4" From 5d78c78138f7d68699e0318f06756081e41973cd Mon Sep 17 00:00:00 2001 From: isaacs Date: Mon, 17 Feb 2020 17:43:14 -0800 Subject: [PATCH 5/6] chore: ignore coverage folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ec23a805..f2b57334 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /node_modules /.nyc_output /test/cache +/coverage From 68a2570d01c3ef6aed952b4d94cfbc05fdb160b7 Mon Sep 17 00:00:00 2001 From: isaacs Date: Mon, 17 Feb 2020 17:43:26 -0800 Subject: [PATCH 6/6] chore(release): 7.0.0 --- CHANGELOG.md | 25 +++++++++++++++++++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a25d7210..36eb6efb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,31 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [7.0.0](https://github.com/npm/registry-fetch/compare/v6.0.2...v7.0.0) (2020-02-18) + + +### ⚠ BREAKING CHANGES + +* figgy pudding is now nowhere to be found. +* this removes figgy-pudding, and drops several option +aliases. + +Defaults and behavior are all the same, and this module is now using the +canonical camelCase option names that npm v7 will provide to all its +deps. + +Related to: https://github.com/npm/rfcs/pull/102 + +PR-URL: https://github.com/npm/npm-registry-fetch/pull/22 +Credit: @isaacs + +### Bug Fixes + +* Remove figgy-pudding, use canonical option names ([ede3c08](https://github.com/npm/registry-fetch/commit/ede3c087007fd1808e02b1af70562220d03b18a9)), closes [#22](https://github.com/npm/registry-fetch/issues/22) + + +* update cacache, ssri, make-fetch-happen ([57fcc88](https://github.com/npm/registry-fetch/commit/57fcc889bee03edcc0a2025d96a171039108c231)) + ### [6.0.2](https://github.com/npm/registry-fetch/compare/v6.0.1...v6.0.2) (2020-02-14) diff --git a/package-lock.json b/package-lock.json index e7af4474..bc4eb0f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "npm-registry-fetch", - "version": "6.0.2", + "version": "7.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 4c6acecc..ccc8e39c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "npm-registry-fetch", - "version": "6.0.2", + "version": "7.0.0", "description": "Fetch-based http client for use with npm registry APIs", "main": "index.js", "files": [