From 3c539975c3a8184bddac518c414e2bce61eb6b84 Mon Sep 17 00:00:00 2001 From: "Juan Picado @jotadeveloper" Date: Sun, 23 Jun 2019 22:57:46 +0200 Subject: [PATCH 1/2] feat: plugins can throw http status codes This feature aims to fix a unfair and missleading situation with storage plugins. Until now they were forced to throw Node error codes https://nodejs.org/api/errors.html#nodejs-error-codes when a resource is not found or a file exist already. Error codes as EEXISTS or ENOENT does not exist in environments where storage is a database or cloud api, thus must be mock. This PR has backward compability and plugins can safely migrate to new error http codes. --- src/lib/local-storage.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/lib/local-storage.js b/src/lib/local-storage.js index 16fcceed2..33ff4a09a 100644 --- a/src/lib/local-storage.js +++ b/src/lib/local-storage.js @@ -8,7 +8,7 @@ import UrlNode from 'url'; import _ from 'lodash'; import { ErrorCode, isObject, getLatestVersion, tagVersion, validateName } from './utils'; import { generatePackageTemplate, normalizePackage, generateRevision, getLatestReadme, cleanUpReadme, normalizeContributors } from './storage-utils'; -import { API_ERROR, DIST_TAGS, STORAGE, USERS } from './constants'; +import { API_ERROR, DIST_TAGS, HTTP_STATUS, STORAGE, USERS } from './constants'; import { createTarballHash } from './crypto-utils'; import { prepareSearchPackage } from './storage-utils'; import loadPlugin from '../lib/plugin-loader'; @@ -41,7 +41,7 @@ class LocalStorage implements IStorage { } storage.createPackage(name, generatePackageTemplate(name), err => { - if (_.isNull(err) === false && err.code === STORAGE.FILE_EXIST_ERROR) { + if (_.isNull(err) === false && (err.code === STORAGE.FILE_EXIST_ERROR || err.code === HTTP_STATUS.CONFLICT)) { return callback(ErrorCode.getConflict()); } @@ -69,7 +69,7 @@ class LocalStorage implements IStorage { storage.readPackage(name, (err, data) => { if (_.isNil(err) === false) { - if (err.code === STORAGE.NO_SUCH_FILE_ERROR) { + if (err.code === STORAGE.NO_SUCH_FILE_ERROR || err.code === HTTP_STATUS.NOT_FOUND) { return callback(ErrorCode.getNotFound()); } else { return callback(err); @@ -422,10 +422,10 @@ class LocalStorage implements IStorage { const writeStream: IUploadTarball = storage.writeTarball(filename); writeStream.on('error', err => { - if (err.code === STORAGE.FILE_EXIST_ERROR) { + if (err.code === STORAGE.FILE_EXIST_ERROR || err.code === HTTP_STATUS.CONFLICT) { uploadStream.emit('error', ErrorCode.getConflict()); uploadStream.abort(); - } else if (err.code === STORAGE.NO_SUCH_FILE_ERROR) { + } else if (err.code === STORAGE.NO_SUCH_FILE_ERROR || err.code === HTTP_STATUS.NOT_FOUND) { // check if package exists to throw an appropriate message this.getPackageMetadata(name, function(_err, res) { if (_err) { @@ -523,7 +523,6 @@ class LocalStorage implements IStorage { _streamSuccessReadTarBall(storage: any, filename: string): IReadTarball { const stream: IReadTarball = new ReadTarball(); const readTarballStream = storage.readTarball(filename); - const e404 = ErrorCode.getNotFound; (stream: any).abort = function() { if (_.isNil(readTarballStream) === false) { @@ -532,8 +531,10 @@ class LocalStorage implements IStorage { }; readTarballStream.on('error', function(err) { - if (err && err.code === STORAGE.NO_SUCH_FILE_ERROR) { - stream.emit('error', e404('no such file available')); + if (_.isNil(err)) { + stream.emit('error', ErrorCode.getInternalError('error reading the tarball')); + } else if (err.code === STORAGE.NO_SUCH_FILE_ERROR || err.code === HTTP_STATUS.NOT_FOUND) { + stream.emit('error', ErrorCode.getNotFound('no such file available')); } else { stream.emit('error', err); } @@ -622,7 +623,7 @@ class LocalStorage implements IStorage { _readPackage(name: string, storage: any, callback: Callback) { storage.readPackage(name, (err, result) => { if (err) { - if (err.code === STORAGE.NO_SUCH_FILE_ERROR) { + if (err.code === STORAGE.NO_SUCH_FILE_ERROR || err.code === HTTP_STATUS.NOT_FOUND) { return callback(ErrorCode.getNotFound()); } else { return callback(this._internalError(err, STORAGE.PACKAGE_FILE_NAME, 'error reading')); @@ -663,7 +664,7 @@ class LocalStorage implements IStorage { storage.readPackage(pkgName, (err, data) => { // TODO: race condition if (_.isNil(err) === false) { - if (err.code === STORAGE.NO_SUCH_FILE_ERROR) { + if (err.code === STORAGE.NO_SUCH_FILE_ERROR || err.code === HTTP_STATUS.NOT_FOUND) { data = generatePackageTemplate(pkgName); } else { return callback(this._internalError(err, STORAGE.PACKAGE_FILE_NAME, 'error reading')); From 12b60f6cb7559b8481123546599924a7bd14f0c1 Mon Sep 17 00:00:00 2001 From: "Juan Picado @jotadeveloper" Date: Tue, 16 Jul 2019 18:27:58 +0200 Subject: [PATCH 2/2] build: fix semver missing type on build with docker it seems the @types/semver do not handle a legitimate method named 'compareLoose' --- package.json | 1 + src/lib/utils.ts | 24 ++++++++++++++---------- yarn.lock | Bin 362379 -> 362649 bytes 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 78f0174e7..ee9e0cd67 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "@types/minimatch": "3.0.3", "@types/node": "12.6.2", "@types/request": "2.48.2", + "@types/semver": "6.0.1", "@typescript-eslint/eslint-plugin": "1.12.0", "@verdaccio/babel-preset": "0.2.1", "@verdaccio/eslint-config": "0.0.1", diff --git a/src/lib/utils.ts b/src/lib/utils.ts index e19f41cd9..1bc0ff545 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -263,16 +263,20 @@ export function parseAddress(urlAddress: any): any { * @return {Array} sorted Array */ export function semverSort(listVersions: string[]): string[] { - return listVersions - .filter(function(x): boolean { - if (!semver.parse(x, true)) { - Logger.logger.warn({ ver: x }, 'ignoring bad version @{ver}'); - return false; - } - return true; - }) - .sort(semver.compareLoose) - .map(String); + return ( + listVersions + .filter(function(x): boolean { + if (!semver.parse(x, true)) { + Logger.logger.warn({ ver: x }, 'ignoring bad version @{ver}'); + return false; + } + return true; + }) + // FIXME: it seems the @types/semver do not handle a legitimate method named 'compareLoose' + // @ts-ignore + .sort(semver.compareLoose) + .map(String) + ); } /** diff --git a/yarn.lock b/yarn.lock index f1478dc6cd6c14d7163c37db297a4036a02133f8..49b27947e5d001c26e8b7da224641da0cae53c95 100644 GIT binary patch delta 215 zcmeC~7n?aztYHh|O-b(DveY66Gd%-6L#650KeE_QPhe!^bSzEi*ibW^Mk{3{M{474T>Ty zA}UJ!Eh9>^Q$q4ALK2Qj9>%1jNih%(DHt6zis30P7eHo&W#<