diff --git a/.eslintrc b/.eslintrc index ebc189017..0566b2595 100644 --- a/.eslintrc +++ b/.eslintrc @@ -30,7 +30,7 @@ "__APP_VERSION__": true }, "rules": { - "no-tabs": 0, + "no-tabs": 2, "keyword-spacing": 0, "padded-blocks": 0, "no-useless-escape": 0, diff --git a/src/lib/logger.js b/src/lib/logger.js index b3cb7f89a..fe99cce00 100644 --- a/src/lib/logger.js +++ b/src/lib/logger.js @@ -11,15 +11,15 @@ const pkgJSON = require('../../package.json'); * @return {String} security level */ function getlvl(x) { - switch(true) { - case x < 15: return 'trace'; - case x < 25: return 'debug'; - case x < 35: return 'info'; - case x == 35: return 'http'; - case x < 45: return 'warn'; - case x < 55: return 'error'; - default: return 'fatal'; - } + switch(true) { + case x < 15: return 'trace'; + case x < 25: return 'debug'; + case x < 35: return 'info'; + case x == 35: return 'http'; + case x < 45: return 'warn'; + case x < 55: return 'error'; + default: return 'fatal'; + } } /** @@ -27,75 +27,75 @@ function getlvl(x) { * @param {*} logs list of log configuration */ function setup(logs) { - let streams = []; - if (logs == null) { - logs = [{type: 'stdout', format: 'pretty', level: 'http'}]; - } + let streams = []; + if (logs == null) { + logs = [{type: 'stdout', format: 'pretty', level: 'http'}]; + } - logs.forEach(function(target) { - // create a stream for each log configuration - const stream = new Stream(); - stream.writable = true; + logs.forEach(function(target) { + // create a stream for each log configuration + const stream = new Stream(); + stream.writable = true; - if (target.type === 'stdout' || target.type === 'stderr') { - // destination stream - const dest = target.type === 'stdout' ? process.stdout : process.stderr; + if (target.type === 'stdout' || target.type === 'stderr') { + // destination stream + const dest = target.type === 'stdout' ? process.stdout : process.stderr; - if (target.format === 'pretty') { - // making fake stream for prettypritting - stream.write = function(obj) { - dest.write(print(obj.level, obj.msg, obj, dest.isTTY) + '\n'); - }; - } else if (target.format === 'pretty-timestamped') { - // making fake stream for prettypritting - stream.write = function(obj) { - dest.write(obj.time.toISOString() + print(obj.level, obj.msg, obj, dest.isTTY) + '\n'); - }; - } else { - stream.write = function(obj) { - dest.write(JSON.stringify(obj, Logger.safeCycles()) + '\n'); - }; - } - } else if (target.type === 'file') { - const dest = require('fs').createWriteStream(target.path, {flags: 'a', encoding: 'utf8'}); - dest.on('error', function(err) { - Logger.emit('error', err); - }); - stream.write = function(obj) { - if (target.format === 'pretty') { - dest.write(print(obj.level, obj.msg, obj, false) + '\n'); - } else { - dest.write(JSON.stringify(obj, Logger.safeCycles()) + '\n'); - } - }; - } else { - throw Error('wrong target type for a log'); - } + if (target.format === 'pretty') { + // making fake stream for prettypritting + stream.write = function(obj) { + dest.write(print(obj.level, obj.msg, obj, dest.isTTY) + '\n'); + }; + } else if (target.format === 'pretty-timestamped') { + // making fake stream for prettypritting + stream.write = function(obj) { + dest.write(obj.time.toISOString() + print(obj.level, obj.msg, obj, dest.isTTY) + '\n'); + }; + } else { + stream.write = function(obj) { + dest.write(JSON.stringify(obj, Logger.safeCycles()) + '\n'); + }; + } + } else if (target.type === 'file') { + const dest = require('fs').createWriteStream(target.path, {flags: 'a', encoding: 'utf8'}); + dest.on('error', function(err) { + Logger.emit('error', err); + }); + stream.write = function(obj) { + if (target.format === 'pretty') { + dest.write(print(obj.level, obj.msg, obj, false) + '\n'); + } else { + dest.write(JSON.stringify(obj, Logger.safeCycles()) + '\n'); + } + }; + } else { + throw Error('wrong target type for a log'); + } - if (target.level === 'http') target.level = 35; - streams.push({ - type: 'raw', - level: target.level || 35, - stream: stream, - }); - }); + if (target.level === 'http') target.level = 35; + streams.push({ + type: 'raw', + level: target.level || 35, + stream: stream, + }); + }); - // buyan default configuration - const logger = new Logger({ - name: pkgJSON.name, - streams: streams, - serializers: { - err: Logger.stdSerializers.err, - req: Logger.stdSerializers.req, - res: Logger.stdSerializers.res, - }, - }); + // buyan default configuration + const logger = new Logger({ + name: pkgJSON.name, + streams: streams, + serializers: { + err: Logger.stdSerializers.err, + req: Logger.stdSerializers.req, + res: Logger.stdSerializers.res, + }, + }); process.on('SIGUSR2', function() { Logger.reopenFileStreams(); }); - module.exports.logger = logger; + module.exports.logger = logger; } // adopted from socket.io @@ -104,20 +104,20 @@ function setup(logs) { // level to color const levels = { - fatal: chalk.red, - error: chalk.red, - warn: chalk.yellow, - http: chalk.magenta, - info: chalk.cyan, - debug: chalk.green, - trace: chalk.white, + fatal: chalk.red, + error: chalk.red, + warn: chalk.yellow, + http: chalk.magenta, + info: chalk.cyan, + debug: chalk.green, + trace: chalk.white, }; let max = 0; for (let l in levels) { - if (Object.prototype.hasOwnProperty.call(levels, l)) { - max = Math.max(max, l.length); - } + if (Object.prototype.hasOwnProperty.call(levels, l)) { + max = Math.max(max, l.length); + } } /** @@ -126,10 +126,10 @@ for (let l in levels) { * @return {String} */ function pad(str) { - if (str.length < max) { - return str + ' '.repeat(max - str.length); - } - return str; + if (str.length < max) { + return str + ' '.repeat(max - str.length); + } + return str; } /** @@ -141,58 +141,58 @@ function pad(str) { * @return {String} */ function print(type, msg, obj, colors) { - if (typeof type === 'number') { - type = getlvl(type); - } - let finalmsg = msg.replace(/@{(!?[$A-Za-z_][$0-9A-Za-z\._]*)}/g, function(_, name) { - let str = obj; - let is_error; - if (name[0] === '!') { - name = name.substr(1); - is_error = true; - } + if (typeof type === 'number') { + type = getlvl(type); + } + let finalmsg = msg.replace(/@{(!?[$A-Za-z_][$0-9A-Za-z\._]*)}/g, function(_, name) { + let str = obj; + let is_error; + if (name[0] === '!') { + name = name.substr(1); + is_error = true; + } - let _ref = name.split('.'); - for (let _i = 0; _i < _ref.length; _i++) { - let id = _ref[_i]; - if (Utils.isObject(str) || Array.isArray(str)) { - str = str[id]; - } else { - str = undefined; - } - } + let _ref = name.split('.'); + for (let _i = 0; _i < _ref.length; _i++) { + let id = _ref[_i]; + if (Utils.isObject(str) || Array.isArray(str)) { + str = str[id]; + } else { + str = undefined; + } + } - if (typeof(str) === 'string') { - if (!colors || str.includes('\n')) { - return str; - } else if (is_error) { - return chalk.red(str); - } else { - return chalk.green(str); - } - } else { - return require('util').inspect(str, null, null, colors); - } - }); + if (typeof(str) === 'string') { + if (!colors || str.includes('\n')) { + return str; + } else if (is_error) { + return chalk.red(str); + } else { + return chalk.green(str); + } + } else { + return require('util').inspect(str, null, null, colors); + } + }); - const subsystems = [{ - in: chalk.green('<--'), - out: chalk.yellow('-->'), - fs: chalk.black('-=-'), - default: chalk.blue('---'), - }, { - in: '<--', - out: '-->', - fs: '-=-', - default: '---', - }]; + const subsystems = [{ + in: chalk.green('<--'), + out: chalk.yellow('-->'), + fs: chalk.black('-=-'), + default: chalk.blue('---'), + }, { + in: '<--', + out: '-->', + fs: '-=-', + default: '---', + }]; - const sub = subsystems[colors ? 0 : 1][obj.sub] || subsystems[+!colors].default; - if (colors) { - return ` ${levels[type]((pad(type)))}${chalk.white(`${sub} ${finalmsg}`)}`; - } else { - return ` ${(pad(type))}${sub} ${finalmsg}`; - } + const sub = subsystems[colors ? 0 : 1][obj.sub] || subsystems[+!colors].default; + if (colors) { + return ` ${levels[type]((pad(type)))}${chalk.white(`${sub} ${finalmsg}`)}`; + } else { + return ` ${(pad(type))}${sub} ${finalmsg}`; + } } module.exports.setup = setup; diff --git a/src/lib/metadata-utils.js b/src/lib/metadata-utils.js index f45033914..57c370ced 100644 --- a/src/lib/metadata-utils.js +++ b/src/lib/metadata-utils.js @@ -9,11 +9,11 @@ import type {Package} from '@verdaccio/types'; /** * Function gets a local info and an info from uplinks and tries to merge it exported for unit tests only. - * @param {*} local - * @param {*} up - * @param {*} config - * @static - */ + * @param {*} local + * @param {*} up + * @param {*} config + * @static + */ export function mergeVersions(local: Package, up: Package) { // copy new versions to a cache // NOTE: if a certain version was updated, we can't refresh it reliably diff --git a/src/lib/search.js b/src/lib/search.js index 422d1d53d..c81b20433 100644 --- a/src/lib/search.js +++ b/src/lib/search.js @@ -32,7 +32,7 @@ class Search implements IWebSearch { * @return {Array} list of results. */ query(query: string) { - return query === '*' + return query === '*' ? this.storage.localStorage.localData.get((items) => { items.map( function( pkg ) { return {ref: pkg, score: 1}; diff --git a/src/lib/uplink-util.js b/src/lib/uplink-util.js index 32ac3d0ba..4d831b91b 100644 --- a/src/lib/uplink-util.js +++ b/src/lib/uplink-util.js @@ -9,99 +9,99 @@ import type {IProxy, ProxyList} from '../../types'; /** * Set up the Up Storage for each link. - */ + */ export function setupUpLinks(config: Config): ProxyList { - const uplinks: ProxyList = {}; + const uplinks: ProxyList = {}; - for (let uplinkName in config.uplinks) { - if (Object.prototype.hasOwnProperty.call(config.uplinks, uplinkName)) { - // instance for each up-link definition - const proxy: IProxy = new ProxyStorage(config.uplinks[uplinkName], config); - proxy.upname = uplinkName; + for (let uplinkName in config.uplinks) { + if (Object.prototype.hasOwnProperty.call(config.uplinks, uplinkName)) { + // instance for each up-link definition + const proxy: IProxy = new ProxyStorage(config.uplinks[uplinkName], config); + proxy.upname = uplinkName; - uplinks[uplinkName] = proxy; - } - } + uplinks[uplinkName] = proxy; + } + } - return uplinks; + return uplinks; } export function updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy) { - for (let i in versions) { - if (Object.prototype.hasOwnProperty.call(versions, i)) { - const version = versions[i]; + for (let i in versions) { + if (Object.prototype.hasOwnProperty.call(versions, i)) { + const version = versions[i]; - // holds a "hidden" value to be used by the package storage. - // $FlowFixMe - version[Symbol.for('__verdaccio_uplink')] = upLink.upname; - } - } + // holds a "hidden" value to be used by the package storage. + // $FlowFixMe + version[Symbol.for('__verdaccio_uplink')] = upLink.upname; + } + } } export function fetchUplinkMetadata(name: string, packageInfo: Package, - options: any, upLink: any, logger: Logger): Promise { + options: any, upLink: any, logger: Logger): Promise { - return new Promise(function(resolve, reject) { - const _options = Object.assign({}, options); - const upLinkMeta = packageInfo._uplinks[upLink.upname]; + return new Promise(function(resolve, reject) { + const _options = Object.assign({}, options); + const upLinkMeta = packageInfo._uplinks[upLink.upname]; - if (isObject(upLinkMeta)) { + if (isObject(upLinkMeta)) { - const fetched = upLinkMeta.fetched; + const fetched = upLinkMeta.fetched; - // check whether is too soon to ask for metadata - if (fetched && (Date.now() - fetched) < upLink.maxage) { - return resolve(false); - } + // check whether is too soon to ask for metadata + if (fetched && (Date.now() - fetched) < upLink.maxage) { + return resolve(false); + } - _options.etag = upLinkMeta.etag; - } + _options.etag = upLinkMeta.etag; + } - upLink.getRemoteMetadata(name, _options, function handleUplinkMetadataResponse(err, upLinkResponse, eTag) { - if (err && err.remoteStatus === 304) { - upLinkMeta.fetched = Date.now(); - } + 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')); - } + 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); - } + 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(), - }; + packageInfo._uplinks[upLink.upname] = { + etag: eTag, + fetched: Date.now(), + }; - // added to fix verdaccio#73 - if ('time' in upLinkResponse) { - packageInfo.time = upLinkResponse.time; - } + // added to fix verdaccio#73 + if ('time' in upLinkResponse) { + packageInfo.time = upLinkResponse.time; + } - updateVersionsHiddenUpLink(upLinkResponse.versions, upLink); + 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); - } + 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); - }); - }); + // 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 5b14dcc90..8362d8fdd 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -21,16 +21,16 @@ export const DIST_TAGS = 'dist-tags'; * @return {Boolean} whether the package is valid or not */ function validate_package(name: any): boolean { - name = name.split('/', 2); - if (name.length === 1) { - // normal package - return module.exports.validate_name(name[0]); - } else { - // scoped package - return name[0][0] === '@' - && module.exports.validate_name(name[0].slice(1)) - && module.exports.validate_name(name[1]); - } + name = name.split('/', 2); + if (name.length === 1) { + // normal package + return module.exports.validate_name(name[0]); + } else { + // scoped package + return name[0][0] === '@' + && module.exports.validate_name(name[0].slice(1)) + && module.exports.validate_name(name[1]); + } } /** @@ -39,20 +39,20 @@ function validate_package(name: any): boolean { * @return {Boolean} whether is valid or not */ function validate_name(name: string): boolean { - if (_.isString(name) === false) { - return false; - } - name = name.toLowerCase(); + if (_.isString(name) === false) { + return false; + } + name = name.toLowerCase(); - // all URL-safe characters and "@" for issue #75 - return !(!name.match(/^[-a-zA-Z0-9_.!~*'()@]+$/) - || name.charAt(0) === '.' // ".bin", etc. - || name.charAt(0) === '-' // "-" is reserved by couchdb - || name === 'node_modules' - || name === '__proto__' - || name === 'package.json' - || name === 'favicon.ico' - ); + // all URL-safe characters and "@" for issue #75 + return !(!name.match(/^[-a-zA-Z0-9_.!~*'()@]+$/) + || name.charAt(0) === '.' // ".bin", etc. + || name.charAt(0) === '-' // "-" is reserved by couchdb + || name === 'node_modules' + || name === '__proto__' + || name === 'package.json' + || name === 'favicon.ico' + ); } /** @@ -61,7 +61,7 @@ function validate_name(name: string): boolean { * @return {Boolean} */ function isObject(obj: any): boolean { - return _.isObject(obj) && _.isNull(obj) === false && _.isArray(obj) === false; + return _.isObject(obj) && _.isNull(obj) === false && _.isArray(obj) === false; } /** @@ -72,18 +72,18 @@ function isObject(obj: any): boolean { * @return {Object} the object with additional properties as dist-tags ad versions */ function validate_metadata(object: Package, name: string) { - assert(isObject(object), 'not a json object'); - assert.equal(object.name, name); + assert(isObject(object), 'not a json object'); + assert.equal(object.name, name); - if (!isObject(object[DIST_TAGS])) { - object[DIST_TAGS] = {}; - } + if (!isObject(object[DIST_TAGS])) { + object[DIST_TAGS] = {}; + } - if (!isObject(object['versions'])) { - object['versions'] = {}; - } + if (!isObject(object['versions'])) { + object['versions'] = {}; + } - return object; + return object; } /** @@ -91,17 +91,17 @@ function validate_metadata(object: Package, name: string) { * @return {String} base registry url */ function combineBaseUrl(protocol: string, host: string, prefix?: string): string { - let result = `${protocol}://${host}`; + let result = `${protocol}://${host}`; - if (prefix) { - prefix = prefix.replace(/\/$/, ''); + if (prefix) { + prefix = prefix.replace(/\/$/, ''); - result = (prefix.indexOf('/') === 0) - ? `${result}${prefix}` - : prefix; - } + result = (prefix.indexOf('/') === 0) + ? `${result}${prefix}` + : prefix; + } - return result; + return result; } /** @@ -112,31 +112,31 @@ function combineBaseUrl(protocol: string, host: string, prefix?: string): string * @return {String} a filtered package */ function filter_tarball_urls(pkg: Package, req: $Request, config: Config) { - /** - * Filter a tarball url. - * @param {*} _url - * @return {String} a parsed url - */ - const filter = function(_url) { - if (!req.headers.host) { - return _url; - } - // $FlowFixMe - const filename = URL.parse(_url).pathname.replace(/^.*\//, ''); - const base = combineBaseUrl(getWebProtocol(req), req.headers.host, config.url_prefix); + /** + * Filter a tarball url. + * @param {*} _url + * @return {String} a parsed url + */ + const filter = function(_url) { + if (!req.headers.host) { + return _url; + } + // $FlowFixMe + const filename = URL.parse(_url).pathname.replace(/^.*\//, ''); + const base = combineBaseUrl(getWebProtocol(req), req.headers.host, config.url_prefix); - return `${base}/${pkg.name.replace(/\//g, '%2f')}/-/${filename}`; - }; + return `${base}/${pkg.name.replace(/\//g, '%2f')}/-/${filename}`; + }; - for (let ver in pkg.versions) { - if (Object.prototype.hasOwnProperty.call(pkg.versions, ver)) { - const dist = pkg.versions[ver].dist; - if (_.isNull(dist) === false && _.isNull(dist.tarball) === false) { - dist.tarball = filter(dist.tarball); - } - } - } - return pkg; + for (let ver in pkg.versions) { + if (Object.prototype.hasOwnProperty.call(pkg.versions, ver)) { + const dist = pkg.versions[ver].dist; + if (_.isNull(dist) === false && _.isNull(dist.tarball) === false) { + dist.tarball = filter(dist.tarball); + } + } + } + return pkg; } /** @@ -147,20 +147,20 @@ function filter_tarball_urls(pkg: Package, req: $Request, config: Config) { * @return {Boolean} whether a package has been tagged */ function tagVersion(data: Package, version: string, tag: StringValue) { - if (tag) { - if (data[DIST_TAGS][tag] !== version) { - if (semver.parse(version, true)) { - // valid version - store - data[DIST_TAGS][tag] = version; - return true; - } - } - Logger.logger.warn({ver: version, tag: tag}, 'ignoring bad version @{ver} in @{tag}'); - if (tag && data[DIST_TAGS][tag]) { - delete data[DIST_TAGS][tag]; - } - } - return false; + if (tag) { + if (data[DIST_TAGS][tag] !== version) { + if (semver.parse(version, true)) { + // valid version - store + data[DIST_TAGS][tag] = version; + return true; + } + } + Logger.logger.warn({ver: version, tag: tag}, 'ignoring bad version @{ver} in @{tag}'); + if (tag && data[DIST_TAGS][tag]) { + delete data[DIST_TAGS][tag]; + } + } + return false; } /** @@ -168,63 +168,63 @@ function tagVersion(data: Package, version: string, tag: StringValue) { * @return {String} return the semantic version of a package */ function get_version(pkg: Package, version: any) { - // this condition must allow cast - if (pkg.versions[version] != null) { - return pkg.versions[version]; - } + // this condition must allow cast + if (pkg.versions[version] != null) { + return pkg.versions[version]; + } - try { - version = semver.parse(version, true); - for (let versionItem in pkg.versions) { - // $FlowFixMe - if (version.compare(semver.parse(versionItem, true)) === 0) { - return pkg.versions[versionItem]; - } - } - } catch (err) { - return undefined; - } + try { + version = semver.parse(version, true); + for (let versionItem in pkg.versions) { + // $FlowFixMe + if (version.compare(semver.parse(versionItem, true)) === 0) { + return pkg.versions[versionItem]; + } + } + } catch (err) { + return undefined; + } } /** * Parse an internet address * Allow: - - https:localhost:1234 - protocol + host + port - - localhost:1234 - host + port - - 1234 - port - - http::1234 - protocol + port - - https://localhost:443/ - full url + https - - http://[::1]:443/ - ipv6 - - unix:/tmp/http.sock - unix sockets - - https://unix:/tmp/http.sock - unix sockets (https) + - https:localhost:1234 - protocol + host + port + - localhost:1234 - host + port + - 1234 - port + - http::1234 - protocol + port + - https://localhost:443/ - full url + https + - http://[::1]:443/ - ipv6 + - unix:/tmp/http.sock - unix sockets + - https://unix:/tmp/http.sock - unix sockets (https) * @param {*} urlAddress the internet address definition * @return {Object|Null} literal object that represent the address parsed */ function parse_address(urlAddress: any) { - // - // TODO: refactor it to something more reasonable? - // - // protocol : // ( host )|( ipv6 ): port / - let urlPattern = /^((https?):(\/\/)?)?((([^\/:]*)|\[([^\[\]]+)\]):)?(\d+)\/?$/.exec(urlAddress); + // + // TODO: refactor it to something more reasonable? + // + // protocol : // ( host )|( ipv6 ): port / + let urlPattern = /^((https?):(\/\/)?)?((([^\/:]*)|\[([^\[\]]+)\]):)?(\d+)\/?$/.exec(urlAddress); - if (urlPattern) { - return { + if (urlPattern) { + return { proto: urlPattern[2] || 'http', host: urlPattern[6] || urlPattern[7] || 'localhost', port: urlPattern[8] || '4873', }; } - urlPattern = /^((https?):(\/\/)?)?unix:(.*)$/.exec(urlAddress); + urlPattern = /^((https?):(\/\/)?)?unix:(.*)$/.exec(urlAddress); - if (urlPattern) { - return { - proto: urlPattern[2] || 'http', - path: urlPattern[4], - }; - } + if (urlPattern) { + return { + proto: urlPattern[2] || 'http', + path: urlPattern[4], + }; + } - return null; + return null; } /** @@ -232,15 +232,15 @@ function parse_address(urlAddress: any) { * @return {Array} sorted Array */ function semverSort(listVersions: Array) { - return listVersions.filter(function(x) { - 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) { + if (!semver.parse(x, true)) { + Logger.logger.warn( {ver: x}, 'ignoring bad version @{ver}' ); + return false; + } + return true; + }) + .sort(semver.compareLoose) + .map(String); } /** @@ -248,35 +248,35 @@ function semverSort(listVersions: Array) { * @param {*} data */ export function normalizeDistTags(pkg: Package) { - let sorted; - if (!pkg[DIST_TAGS].latest) { - // overwrite latest with highest known version based on semver sort - sorted = semverSort(Object.keys(pkg.versions)); - if (sorted && sorted.length) { - pkg[DIST_TAGS].latest = sorted.pop(); - } - } + let sorted; + if (!pkg[DIST_TAGS].latest) { + // overwrite latest with highest known version based on semver sort + sorted = semverSort(Object.keys(pkg.versions)); + if (sorted && sorted.length) { + pkg[DIST_TAGS].latest = sorted.pop(); + } + } - for (let tag in pkg[DIST_TAGS]) { - if (_.isArray(pkg[DIST_TAGS][tag])) { - if (pkg[DIST_TAGS][tag].length) { - // sort array - // $FlowFixMe - sorted = semverSort(pkg[DIST_TAGS][tag]); - if (sorted.length) { - // use highest version based on semver sort - pkg[DIST_TAGS][tag] = sorted.pop(); - } - } else { - delete pkg[DIST_TAGS][tag]; - } - } else if (_.isString(pkg[DIST_TAGS][tag] )) { - if (!semver.parse(pkg[DIST_TAGS][tag], true)) { - // if the version is invalid, delete the dist-tag entry - delete pkg[DIST_TAGS][tag]; - } - } - } + for (let tag in pkg[DIST_TAGS]) { + if (_.isArray(pkg[DIST_TAGS][tag])) { + if (pkg[DIST_TAGS][tag].length) { + // sort array + // $FlowFixMe + sorted = semverSort(pkg[DIST_TAGS][tag]); + if (sorted.length) { + // use highest version based on semver sort + pkg[DIST_TAGS][tag] = sorted.pop(); + } + } else { + delete pkg[DIST_TAGS][tag]; + } + } else if (_.isString(pkg[DIST_TAGS][tag] )) { + if (!semver.parse(pkg[DIST_TAGS][tag], true)) { + // if the version is invalid, delete the dist-tag entry + delete pkg[DIST_TAGS][tag]; + } + } + } } const parseIntervalTable = { @@ -350,10 +350,10 @@ const ErrorCode = { }, get404: (customMessage?: string) => { return createError(404, customMessage || 'no such package available'); - }, - getCode: (statusCode: number, customMessage: string) => { + }, + getCode: (statusCode: number, customMessage: string) => { return createError(statusCode, customMessage); - }, + }, }; const parseConfigFile = (configPath: string) => YAML.safeLoad(fs.readFileSync(configPath, 'utf8')); @@ -433,25 +433,25 @@ function addGravatarSupport(pkgInfo: any) { } export { - addGravatarSupport, - deleteProperties, - addScope, - sortByName, - folder_exists, - fileExists, - parseInterval, - semverSort, - parse_address, - get_version, - tagVersion, - combineBaseUrl, - filter_tarball_urls, - validate_metadata, - isObject, - validate_name, - validate_package, - getWebProtocol, - getLatestVersion, - ErrorCode, - parseConfigFile, + addGravatarSupport, + deleteProperties, + addScope, + sortByName, + folder_exists, + fileExists, + parseInterval, + semverSort, + parse_address, + get_version, + tagVersion, + combineBaseUrl, + filter_tarball_urls, + validate_metadata, + isObject, + validate_name, + validate_package, + getWebProtocol, + getLatestVersion, + ErrorCode, + parseConfigFile, }; diff --git a/types/index.js b/types/index.js index 204654057..65757f3b9 100644 --- a/types/index.js +++ b/types/index.js @@ -1,17 +1,17 @@ // @flow import type { - UpLinkConf, - Callback, - Versions, - Version, - MergeTags, - Config, - Logger, - Package} from '@verdaccio/types'; + UpLinkConf, + Callback, + Versions, + Version, + MergeTags, + Config, + Logger, + Package} from '@verdaccio/types'; import type { - IUploadTarball, - IReadTarball, + IUploadTarball, + IReadTarball, } from '@verdaccio/streams'; import type {ILocalData} from '@verdaccio/local-storage'; import type {NextFunction, $Request, $Response} from 'request'; @@ -19,98 +19,98 @@ import type {NextFunction, $Request, $Response} from 'request'; export type StringValue = string | void | null; export interface IAuth { - config: Config; - logger: Logger; - secret: string; - plugins: Array; - aes_encrypt(buf: Buffer): Buffer; - apiJWTmiddleware(): $NextFunctionVer; + config: Config; + logger: Logger; + secret: string; + plugins: Array; + aes_encrypt(buf: Buffer): Buffer; + apiJWTmiddleware(): $NextFunctionVer; webUIJWTmiddleware(): $NextFunctionVer; - authenticate(user: string, password: string, cb: Callback): void; - allow_access(packageName: string, user: string, callback: Callback): void; + authenticate(user: string, password: string, cb: Callback): void; + allow_access(packageName: string, user: string, callback: Callback): void; issueUIjwt(user: string, time: string): string; - add_user(user: string, password: string, cb: Callback): any; + add_user(user: string, password: string, cb: Callback): any; } export interface IWebSearch { - index: any; - storage: IStorageHandler; - query(query: string): any; - add(pkg: Version): void; - remove(name: string): void; - reindex(): void; - configureStorage(storage: IStorageHandler): void; + index: any; + storage: IStorageHandler; + query(query: string): any; + add(pkg: Version): void; + remove(name: string): void; + reindex(): void; + configureStorage(storage: IStorageHandler): void; } export interface IProxy { - config: UpLinkConf; - failed_requests: number; - userAgent: string; - ca?: string | void; - logger: Logger; - server_id: string; - url: any; - maxage: number; - timeout: number; - max_fails: number; - fail_timeout: number; - upname: string; - fetchTarball(url: string): IReadTarball; - isUplinkValid(url: string): boolean; - getRemoteMetadata(name: string, options: any, callback: Callback): void; + config: UpLinkConf; + failed_requests: number; + userAgent: string; + ca?: string | void; + logger: Logger; + server_id: string; + url: any; + maxage: number; + timeout: number; + max_fails: number; + fail_timeout: number; + upname: string; + fetchTarball(url: string): IReadTarball; + isUplinkValid(url: string): boolean; + getRemoteMetadata(name: string, options: any, callback: Callback): void; } export type ProxyList = { - [key: string]: IProxy; + [key: string]: IProxy; } export type Utils = { - ErrorCode: any; - getLatestVersion: Callback; - isObject: (value: any) => boolean; - validate_name: (value: any) => boolean; - tag_version: (value: any, version: string, tag: string) => void; - normalizeDistTags: (pkg: Package) => void; - semverSort: (keys: Array) => Array; + ErrorCode: any; + getLatestVersion: Callback; + isObject: (value: any) => boolean; + validate_name: (value: any) => boolean; + tag_version: (value: any, version: string, tag: string) => void; + normalizeDistTags: (pkg: Package) => void; + semverSort: (keys: Array) => Array; } export interface IStorageHandler { - config: Config; - localStorage: IStorage; - logger: Logger; - uplinks: ProxyList; - addPackage(name: string, metadata: any, callback: Function): Promise; - init(config: Config): Promise; - addVersion(name: string, version: string, metadata: Version, tag: StringValue, callback: Callback): void; - mergeTags(name: string, tagHash: MergeTags, callback: Callback): void; - replaceTags(name: string, tagHash: MergeTags, callback: Callback): void; - changePackage(name: string, metadata: Package, revision: string, callback: Callback): void; - removePackage(name: string, callback: Callback): void; - removeTarball(name: string, filename: string, revision: string, callback: Callback): void; - addTarball(name: string, filename: string): IUploadTarball; - getTarball(name: string, filename: string): IReadTarball; - getPackage(options: any): void; - search(startkey: string, options: any): void; - getLocalDatabase(callback: Callback): void; - _syncUplinksMetadata(name: string, packageInfo: Package, options: any, callback: Callback): void; - _updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy): void; + config: Config; + localStorage: IStorage; + logger: Logger; + uplinks: ProxyList; + addPackage(name: string, metadata: any, callback: Function): Promise; + init(config: Config): Promise; + addVersion(name: string, version: string, metadata: Version, tag: StringValue, callback: Callback): void; + mergeTags(name: string, tagHash: MergeTags, callback: Callback): void; + replaceTags(name: string, tagHash: MergeTags, callback: Callback): void; + changePackage(name: string, metadata: Package, revision: string, callback: Callback): void; + removePackage(name: string, callback: Callback): void; + removeTarball(name: string, filename: string, revision: string, callback: Callback): void; + addTarball(name: string, filename: string): IUploadTarball; + getTarball(name: string, filename: string): IReadTarball; + getPackage(options: any): void; + search(startkey: string, options: any): void; + getLocalDatabase(callback: Callback): void; + _syncUplinksMetadata(name: string, packageInfo: Package, options: any, callback: Callback): void; + _updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy): void; } export interface IStorage { - config: Config; - localData: ILocalData; - logger: Logger; - addPackage(name: string, info: Package, callback: Callback): void; - removePackage(name: string, callback: Callback): void; - updateVersions(name: string, packageInfo: Package, callback: Callback): void; - addVersion(name: string, version: string, metadata: Version, tag: StringValue, callback: Callback): void; - mergeTags(name: string, tags: MergeTags, callback: Callback): void; - changePackage(name: string, metadata: Package, revision: string, callback: Callback): void; - removeTarball(name: string, filename: string, revision: string, callback: Callback): void; - addTarball(name: string, filename: string): IUploadTarball; - getTarball(name: string, filename: string): IReadTarball; - getPackageMetadata(name: string, callback: Callback): void; - search(startKey: string, options: any): IUploadTarball; + config: Config; + localData: ILocalData; + logger: Logger; + addPackage(name: string, info: Package, callback: Callback): void; + removePackage(name: string, callback: Callback): void; + updateVersions(name: string, packageInfo: Package, callback: Callback): void; + addVersion(name: string, version: string, metadata: Version, tag: StringValue, callback: Callback): void; + mergeTags(name: string, tags: MergeTags, callback: Callback): void; + changePackage(name: string, metadata: Package, revision: string, callback: Callback): void; + removeTarball(name: string, filename: string, revision: string, callback: Callback): void; + addTarball(name: string, filename: string): IUploadTarball; + getTarball(name: string, filename: string): IReadTarball; + getPackageMetadata(name: string, callback: Callback): void; + search(startKey: string, options: any): IUploadTarball; getSecret(config: Config): Promise; }