From ee625596158f04678e5e182727b8169cdd6293b5 Mon Sep 17 00:00:00 2001 From: "Juan Picado @jotadeveloper" Date: Sat, 9 Jun 2018 17:13:38 +0200 Subject: [PATCH 1/9] refactor: merge time prop instead overwrite it remove dead code --- src/lib/storage-utils.js | 16 ++++++--- src/lib/storage.js | 24 +++----------- src/lib/uplink-util.js | 71 +--------------------------------------- src/lib/utils.js | 4 +++ 4 files changed, 21 insertions(+), 94 deletions(-) diff --git a/src/lib/storage-utils.js b/src/lib/storage-utils.js index f45065801..1871ce2ce 100644 --- a/src/lib/storage-utils.js +++ b/src/lib/storage-utils.js @@ -11,7 +11,6 @@ import type {IStorage} from '../../types'; const pkgFileName = 'package.json'; const fileExist: string = 'EEXISTS'; const noSuchFile: string = 'ENOENT'; -const resourceNotAvailable: string = 'EAGAIN'; const DEFAULT_REVISION: string = `0-0000000000000000`; const generatePackageTemplate = function(name: string): Package { @@ -19,11 +18,11 @@ const generatePackageTemplate = function(name: string): Package { // standard things name, versions: {}, - 'dist-tags': {}, time: {}, + [DIST_TAGS]: {}, + _uplinks: {}, _distfiles: {}, _attachments: {}, - _uplinks: {}, _rev: '', }; }; @@ -179,6 +178,14 @@ export function checkPackageRemote(name: string, isAllowPublishOffline: boolean, }); } +export function mergeTime(localMetadata: Package, remoteMetadata: Package) { + if ('time' in remoteMetadata) { + return Object.assign({}, localMetadata.time, remoteMetadata.time); + } + + return localMetadata.time; +} + export function prepareSearchPackage(data: Package, time: mixed) { const listVersions: Array = Object.keys(data.versions); const versions: Array = semverSort(listVersions); @@ -189,7 +196,7 @@ export function prepareSearchPackage(data: Package, time: mixed) { const pkg: any = { name: version.name, description: version.description, - 'dist-tags': {latest}, + [DIST_TAGS]: {latest}, maintainers: version.maintainers || [version.author].filter(Boolean), author: version.author, repository: version.repository, @@ -218,6 +225,5 @@ export { fileExist, noSuchFile, pkgFileName, - resourceNotAvailable, }; diff --git a/src/lib/storage.js b/src/lib/storage.js index eef2c9d01..f59bee002 100644 --- a/src/lib/storage.js +++ b/src/lib/storage.js @@ -8,7 +8,8 @@ import ProxyStorage from './up-storage'; import Search from './search'; import LocalStorage from './local-storage'; import {ReadTarball} from '@verdaccio/streams'; -import {checkPackageLocal, publishPackage, checkPackageRemote, cleanUpLinksRef} from './storage-utils'; +import {checkPackageLocal, publishPackage, checkPackageRemote, cleanUpLinksRef, + mergeTime, generatePackageTemplate} from './storage-utils'; import {setupUpLinks, updateVersionsHiddenUpLink} from './uplink-util'; import {mergeVersions} from './metadata-utils'; import {ErrorCode, normalizeDistTags, validate_metadata, isObject, DIST_TAGS} from './utils'; @@ -26,19 +27,6 @@ import type { import type {IReadTarball, IUploadTarball} from '@verdaccio/streams'; const LoggerApi = require('../lib/logger'); -const getDefaultMetadata = function(name): Package { - const pkgMetadata: Package = { - name, - versions: {}, - 'dist-tags': {}, - _uplinks: {}, - _distfiles: {}, - _attachments: {}, - _rev: '', - }; - - return pkgMetadata; -}; class Storage implements IStorageHandler { localStorage: IStorage; @@ -417,9 +405,10 @@ class Storage implements IStorageHandler { let exists = true; const self = this; const upLinks = []; + if (!packageInfo || packageInfo === null) { exists = false; - packageInfo = getDefaultMetadata(name); + packageInfo = generatePackageTemplate(name); } for (let up in this.uplinks) { @@ -467,10 +456,7 @@ class Storage implements IStorageHandler { fetched: Date.now(), }; - // added to fix verdaccio#73 - if ('time' in upLinkResponse) { - packageInfo.time = upLinkResponse.time; - } + packageInfo.time = mergeTime(packageInfo, upLinkResponse); updateVersionsHiddenUpLink(upLinkResponse.versions, upLink); diff --git a/src/lib/uplink-util.js b/src/lib/uplink-util.js index 02bfc52fd..cfd52400f 100644 --- a/src/lib/uplink-util.js +++ b/src/lib/uplink-util.js @@ -1,10 +1,7 @@ // @flow -import {ErrorCode, isObject, validate_metadata} from './utils'; import ProxyStorage from './up-storage'; -import {mergeVersions} from './metadata-utils'; - -import type {Package, Versions, Config, Logger} from '@verdaccio/types'; +import type {Versions, Config} from '@verdaccio/types'; import type {IProxy, ProxyList} from '../../types'; /** @@ -37,69 +34,3 @@ export function updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy) { } } } - -export function fetchUplinkMetadata(name: string, packageInfo: Package, - options: any, upLink: any, logger: Logger): Promise { - return new Promise(function(resolve, reject) { - const _options = Object.assign({}, options); - const upLinkMeta = packageInfo._uplinks[upLink.upname]; - - if (isObject(upLinkMeta)) { - const fetched = upLinkMeta.fetched; - - // check whether is too soon to ask for metadata - if (fetched && (Date.now() - fetched) < upLink.maxage) { - return resolve(false); - } - - _options.etag = upLinkMeta.etag; - } - - upLink.getRemoteMetadata(name, _options, function handleUplinkMetadataResponse(err, upLinkResponse, eTag) { - if (err && err.remoteStatus === 304) { - upLinkMeta.fetched = Date.now(); - } - - if (err || !upLinkResponse) { - // $FlowFixMe - return reject(err || ErrorCode.get500('no data')); - } - - try { - validate_metadata(upLinkResponse, name); - } catch (err) { - logger.error({ - sub: 'out', - err: err, - }, 'package.json validating error @{!err.message}\n@{err.stack}'); - return reject(err); - } - - packageInfo._uplinks[upLink.upname] = { - etag: eTag, - fetched: Date.now(), - }; - - // added to fix verdaccio#73 - if ('time' in upLinkResponse) { - packageInfo.time = upLinkResponse.time; - } - - updateVersionsHiddenUpLink(upLinkResponse.versions, upLink); - - try { - mergeVersions(packageInfo, upLinkResponse); - } catch (err) { - logger.error({ - sub: 'out', - err: err, - }, 'package.json parsing error @{!err.message}\n@{err.stack}'); - return reject(err); - } - - // if we got to this point, assume that the correct package exists - // on the uplink - resolve(true); - }); - }); -} diff --git a/src/lib/utils.js b/src/lib/utils.js index 38e2de686..0285bee8a 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -81,6 +81,10 @@ function validate_metadata(object: Package, name: string) { object['versions'] = {}; } + if (!isObject(object['time'])) { + object['time'] = {}; + } + return object; } From 995271a8366f273a1b84e5d91a53806280a9d353 Mon Sep 17 00:00:00 2001 From: "Juan Picado @jotadeveloper" Date: Sat, 9 Jun 2018 18:18:50 +0200 Subject: [PATCH 2/9] refactor: usage of error utils --- src/lib/up-storage.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/lib/up-storage.js b/src/lib/up-storage.js index 9cad3acff..576262f86 100644 --- a/src/lib/up-storage.js +++ b/src/lib/up-storage.js @@ -2,7 +2,6 @@ import zlib from 'zlib'; import JSONStream from 'JSONStream'; -import createError from 'http-errors'; import _ from 'lodash'; import request from 'request'; import Stream from 'stream'; @@ -114,7 +113,7 @@ class ProxyStorage implements IProxy { cb(ErrorCode.get500('uplink is offline')); } // $FlowFixMe - streamRead.emit('error', createError('uplink is offline')); + streamRead.emit('error', ErrorCode.get500('uplink is offline')); }); // $FlowFixMe streamRead._read = function() {}; @@ -415,7 +414,7 @@ class ProxyStorage implements IProxy { return callback( ErrorCode.get404('package doesn\'t exist on uplink')); } if (!(res.statusCode >= 200 && res.statusCode < 300)) { - const error = createError(500, `bad status code: ${res.statusCode}`); + const error = ErrorCode.get500(`bad status code: ${res.statusCode}`); // $FlowFixMe error.remoteStatus = res.statusCode; return callback(error); @@ -448,7 +447,7 @@ class ProxyStorage implements IProxy { return stream.emit('error', ErrorCode.get404('file doesn\'t exist on uplink')); } if (!(res.statusCode >= 200 && res.statusCode < 300)) { - return stream.emit('error', createError(500, 'bad uplink status code: ' + res.statusCode)); + return stream.emit('error', ErrorCode.get500(`bad uplink status code: ${res.statusCode}`)); } if (res.headers['content-length']) { expected_length = res.headers['content-length']; @@ -469,7 +468,7 @@ class ProxyStorage implements IProxy { current_length += data.length; } if (expected_length && current_length != expected_length) { - stream.emit('error', createError(500, 'content length mismatch')); + stream.emit('error', ErrorCode.get500('content length mismatch')); } }); return stream; @@ -498,7 +497,7 @@ class ProxyStorage implements IProxy { requestStream.on('response', (res) => { if (!String(res.statusCode).match(/^2\d\d$/)) { - return transformStream.emit('error', createError(500, `bad status code ${res.statusCode} from uplink`)); + return transformStream.emit('error', ErrorCode.get500(`bad status code ${res.statusCode} from uplink`)); } // See https://github.com/request/request#requestoptions-callback From 78e5c9d778c59de6f85eeb30d36854415f9f5d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Herrera=20Guzm=C3=A1n?= Date: Sat, 9 Jun 2018 18:19:43 +0200 Subject: [PATCH 3/9] chore: store coverage --- .circleci/config.yml | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c86aaf623..45e5c7b30 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,6 +22,8 @@ aliases: <<: *node9_executor - &repo_key repo-{{ .Branch }}-{{ .Revision }} + - &coverage_key + coverage-{{ .Branch }}-{{ .Revision }} - &base_config_key base-config-{{ .Branch }}-{{ .Revision }} - &yarn_cache_key @@ -108,6 +110,10 @@ jobs: - run: name: Test with Node 9 command: yarn run test + - save_cache: + key: *coverage_key + paths: + - coverage test_node10: <<: *defaults @@ -132,9 +138,19 @@ jobs: <<: *default_executor steps: - *restore_repo + - restore_cache: + key: *coverage_key - run: name: Publish coverage command: yarn run coverage:publish + - store_artifacts: + path: coverage/clover.xml + prefix: tests + - store_artifacts: + path: coverage + prefix: coverage + - store_test_results: + path: coverage/clover.xml publish_gh_pages: <<: *defaults @@ -189,7 +205,11 @@ workflows: <<: *ignore_branches - coverage: requires: - - prepare + - test_node6 + - test_node8 + - test_node9 + - test_node10 + - test_e2e <<: *ignore_branches - publish_gh_pages: requires: @@ -198,10 +218,10 @@ workflows: - test_node9 - test_node10 - test_e2e - - coverage <<: *ignore_branches - deploy: requires: + - coverage - publish_gh_pages filters: branches: From 98ac855e0f7bb0f64fea240b2ac0afdf4317c53d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Canberger?= Date: Mon, 11 Jun 2018 12:50:53 +0200 Subject: [PATCH 4/9] fix: configure fetch to send cookies Previously, when XMLHttpRequest was used, cookies ware sent when getting /-/verdaccio/logo & /-/verdaccio/packages After switching to fetch in sha fef7ee75e8a02dc3a6017b70dcb62dabf9183e0f cookies are no longer sent. This commit configures fetch in the webui to send cookies to the same domain. > The "same-origin" value makes fetch behave similarly to > XMLHttpRequest with regards to cookies. > https://github.com/github/fetch#sending-cookies --- src/webui/utils/api.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/webui/utils/api.js b/src/webui/utils/api.js index 084738dfd..c76ffe3e2 100644 --- a/src/webui/utils/api.js +++ b/src/webui/utils/api.js @@ -26,6 +26,7 @@ class API { return fetch(url, { method, + credentials: 'same-origin', ...options }).then(handleErrors); } From 3ee1807cc9addcca1bdd03b10610872d4a0236ef Mon Sep 17 00:00:00 2001 From: "Juan Picado @jotadeveloper" Date: Mon, 11 Jun 2018 19:45:24 +0200 Subject: [PATCH 5/9] chore: docker node alpine to 10.3 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f4702f79e..58f406b5a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:10.1-alpine +FROM node:10.3-alpine LABEL maintainer="https://github.com/verdaccio/verdaccio" RUN apk --no-cache add openssl && \ From 0923c4419a4fccdae30f7f14e5214e6c4283e27d Mon Sep 17 00:00:00 2001 From: "Juan Picado @jotadeveloper" Date: Mon, 11 Jun 2018 19:56:12 +0200 Subject: [PATCH 6/9] chore(release): 3.1.2 --- CHANGELOG.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5da87d386..c00cbf000 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ 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. + +## [3.1.2](https://github.com/verdaccio/verdaccio/compare/v3.1.1...v3.1.2) (2018-06-11) + + +### Bug Fixes + +* configure fetch to send cookies ([98ac855](https://github.com/verdaccio/verdaccio/commit/98ac855)) +* search implementation depends now of each plugin ([8f0508f](https://github.com/verdaccio/verdaccio/commit/8f0508f)) + + + ## [3.1.1](https://github.com/verdaccio/verdaccio/compare/v3.1.0...v3.1.1) (2018-06-07) diff --git a/package.json b/package.json index d8a8ee9b4..2dfcb22b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "verdaccio", - "version": "3.1.1", + "version": "3.1.2", "description": "Private npm repository server", "author": { "name": "Alex Kocharin", From 9e3ab09d6ed64dedb6cbe69cda4c2e81cd2ea3af Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Mon, 11 Jun 2018 22:22:45 +0200 Subject: [PATCH 7/9] fix: fixed linebreaks lint issue --- .eslintrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc b/.eslintrc index bf264f883..4b4184023 100644 --- a/.eslintrc +++ b/.eslintrc @@ -40,6 +40,7 @@ "valid-jsdoc": 0, "prefer-spread": 1, "prefer-rest-params": 1, + "linebreak-style": 0, "quote-props":["error", "as-needed"] } } From 82e457b7ed11ad04bf7ee8ad569f85e5af93136c Mon Sep 17 00:00:00 2001 From: "Juan Picado @jotadeveloper" Date: Tue, 12 Jun 2018 08:17:27 +0200 Subject: [PATCH 8/9] chore: display all versions on sidebar remove hidden metadata --- src/api/web/endpoint/package.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/api/web/endpoint/package.js b/src/api/web/endpoint/package.js index fc8e3a2ba..e2f6a48af 100644 --- a/src/api/web/endpoint/package.js +++ b/src/api/web/endpoint/package.js @@ -86,12 +86,11 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth) req, callback: function(err: Error, info: $SidebarPackage) { if (_.isNil(err)) { - const sideBarInfo: any = _.clone(info); + let sideBarInfo: any = _.clone(info); sideBarInfo.latest = info.versions[info[DIST_TAGS].latest]; - - info = deleteProperties(['readme', 'versions'], sideBarInfo); - info = addGravatarSupport(sideBarInfo); - next(info); + sideBarInfo = deleteProperties(['readme', '_attachments', '_rev', 'name'], sideBarInfo); + sideBarInfo = addGravatarSupport(sideBarInfo); + next(sideBarInfo); } else { res.status(404); res.end(); From 92e1eb00ca04674b71bd16455ac8079abdd9df5e Mon Sep 17 00:00:00 2001 From: "Juan Picado @jotadeveloper" Date: Tue, 12 Jun 2018 08:22:23 +0200 Subject: [PATCH 9/9] chore: update unit test sidebar --- test/unit/api.spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/api.spec.js b/test/unit/api.spec.js index 29bfa1549..bd5091f6d 100644 --- a/test/unit/api.spec.js +++ b/test/unit/api.spec.js @@ -609,7 +609,6 @@ describe('endpoint unit test', () => { const sideBarInfo = res.body; const latestVersion = publishMetadata.versions[publishMetadata['dist-tags'].latest]; - expect(sideBarInfo.name).toBe(latestVersion.name); expect(sideBarInfo.latest.author).toBeDefined(); expect(sideBarInfo.latest.author.avatar).toMatch(/www.gravatar.com/); expect(sideBarInfo.latest.author.name).toBe(latestVersion.author.name);