refactor(flow): add flow support to storage

This commit is contained in:
Juan Picado @jotadeveloper 2018-02-04 00:06:33 +01:00
parent 42f23da363
commit 7a86b71342
No known key found for this signature in database
GPG Key ID: 18AC54485952D158
5 changed files with 89 additions and 57 deletions

2
.yarnrc Normal file
View File

@ -0,0 +1,2 @@
save-prefix ""
registry "http://registry.npmjs.org/"

View File

@ -51,7 +51,7 @@
"@commitlint/cli": "^6.1.0", "@commitlint/cli": "^6.1.0",
"@commitlint/config-conventional": "^6.1.0", "@commitlint/config-conventional": "^6.1.0",
"@commitlint/travis-cli": "^6.1.0", "@commitlint/travis-cli": "^6.1.0",
"@verdaccio/types": "0.2.0", "@verdaccio/types": "0.3.0",
"axios": "0.17.1", "axios": "0.17.1",
"babel-cli": "6.26.0", "babel-cli": "6.26.0",
"babel-core": "6.26.0", "babel-core": "6.26.0",

View File

@ -500,7 +500,7 @@ class LocalStorage implements IStorage {
* @param {*} filename * @param {*} filename
* @return {ReadTarball} * @return {ReadTarball}
*/ */
getTarball(name: string, filename: string) { getTarball(name: string, filename: string): IReadTarball {
assert(Utils.validate_name(filename)); assert(Utils.validate_name(filename));
const storage: IPackageStorage = this._getLocalStorage(name); const storage: IPackageStorage = this._getLocalStorage(name);
@ -517,7 +517,7 @@ class LocalStorage implements IStorage {
* @private * @private
* @return {ReadTarball} * @return {ReadTarball}
*/ */
_createFailureStreamResponse() { _createFailureStreamResponse(): IReadTarball {
const stream: IReadTarball = new ReadTarball(); const stream: IReadTarball = new ReadTarball();
process.nextTick(() => { process.nextTick(() => {

View File

@ -1,8 +1,12 @@
// @flow
import _ from 'lodash'; import _ from 'lodash';
import assert from 'assert'; import assert from 'assert';
// $FlowFixMe
import async from 'async'; import async from 'async';
// $FlowFixMe
import Error from 'http-errors'; import Error from 'http-errors';
// $FlowFixMe
import semver from 'semver'; import semver from 'semver';
import Stream from 'stream'; import Stream from 'stream';
@ -12,7 +16,23 @@ import {ReadTarball} from '@verdaccio/streams';
import ProxyStorage from './up-storage'; import ProxyStorage from './up-storage';
import * as Utils from './utils'; import * as Utils from './utils';
const Logger = require('../lib/logger'); import type {
IStorage,
IProxy,
IStorageHandler,
ProxyList,
Package,
Config,
MergeTags,
Version,
DistFile,
Callback,
Logger,
} from '@verdaccio/types';
import type {IReadTarball} from '@verdaccio/streams';
const LoggerApi = require('../lib/logger');
const WHITELIST = ['_rev', 'name', 'versions', 'dist-tags', 'readme', 'time']; const WHITELIST = ['_rev', 'name', 'versions', 'dist-tags', 'readme', 'time'];
const getDefaultMetadata = (name) => { const getDefaultMetadata = (name) => {
return { return {
@ -27,16 +47,21 @@ const getDefaultMetadata = (name) => {
* Implements Storage interface * Implements Storage interface
* (same for storage.js, local-storage.js, up-storage.js). * (same for storage.js, local-storage.js, up-storage.js).
*/ */
class Storage { class Storage implements IStorageHandler {
localStorage: IStorage;
config: Config;
logger: Logger;
uplinks: ProxyList;
/** /**
* @param {*} config * @param {*} config
*/ */
constructor(config) { constructor(config: Config) {
this.config = config; this.config = config;
this.uplinks = {};
this._setupUpLinks(this.config); this._setupUpLinks(this.config);
this.logger = Logger.logger.child(); this.logger = LoggerApi.logger.child();
this.localStorage = new LocalStorage(this.config, Logger.logger); this.localStorage = new LocalStorage(this.config, LoggerApi.logger);
} }
/** /**
@ -48,7 +73,7 @@ class Storage {
* @param {*} metadata * @param {*} metadata
* @param {*} callback * @param {*} callback
*/ */
addPackage(name, metadata, callback) { addPackage(name: string, metadata: any, callback: Function) {
const self = this; const self = this;
/** /**
@ -62,7 +87,7 @@ class Storage {
return reject(err); return reject(err);
} }
if (results) { if (results) {
return reject(Error[409]('this package is already present')); return reject(Utils.ErrorCode.get409('this package is already present'));
} }
return resolve(); return resolve();
}); });
@ -82,7 +107,7 @@ class Storage {
} }
// checking package // checking package
if (results) { if (results) {
return reject(Error[409]('this package is already present')); return reject(Utils.ErrorCode.get409('this package is already present'));
} }
for (let i = 0; i < err_results.length; i++) { for (let i = 0; i < err_results.length; i++) {
// checking error // checking error
@ -144,7 +169,7 @@ class Storage {
* @param {*} tag * @param {*} tag
* @param {*} callback * @param {*} callback
*/ */
addVersion(name, version, metadata, tag, callback) { addVersion(name: string, version: Version, metadata: Package, tag: string, callback: Callback) {
this.localStorage.addVersion(name, version, metadata, tag, callback); this.localStorage.addVersion(name, version, metadata, tag, callback);
} }
@ -155,8 +180,8 @@ class Storage {
* @param {*} tag_hash * @param {*} tag_hash
* @param {*} callback * @param {*} callback
*/ */
mergeTags(name, tag_hash, callback) { mergeTags(name: string, tagHash: MergeTags, callback: Callback) {
this.localStorage.mergeTags(name, tag_hash, callback); this.localStorage.mergeTags(name, tagHash, callback);
} }
/** /**
@ -166,9 +191,9 @@ class Storage {
* @param {*} tag_hash * @param {*} tag_hash
* @param {*} callback * @param {*} callback
*/ */
replace_tags(name, tag_hash, callback) { replace_tags(name: string, tagHash: MergeTags, callback: Callback) {
this.logger.warn('method deprecated'); this.logger.warn('method deprecated');
this.localStorage.mergeTags(name, tag_hash, callback); this.localStorage.mergeTags(name, tagHash, callback);
} }
/** /**
@ -180,7 +205,7 @@ class Storage {
* @param {*} revision * @param {*} revision
* @param {*} callback * @param {*} callback
*/ */
change_package(name, metadata, revision, callback) { change_package(name: string, metadata: Package, revision: string, callback: Callback) {
this.localStorage.changePackage(name, metadata, revision, callback); this.localStorage.changePackage(name, metadata, revision, callback);
} }
@ -191,7 +216,7 @@ class Storage {
* @param {*} name * @param {*} name
* @param {*} callback * @param {*} callback
*/ */
remove_package(name, callback) { remove_package(name: string, callback: Callback) {
this.localStorage.removePackage(name, callback); this.localStorage.removePackage(name, callback);
// update the indexer // update the indexer
Search.remove(name); Search.remove(name);
@ -208,7 +233,7 @@ class Storage {
* @param {*} revision * @param {*} revision
* @param {*} callback * @param {*} callback
*/ */
remove_tarball(name, filename, revision, callback) { remove_tarball(name: string, filename: string, revision: string, callback: Callback) {
this.localStorage.removeTarball(name, filename, revision, callback); this.localStorage.removeTarball(name, filename, revision, callback);
} }
@ -220,7 +245,7 @@ class Storage {
* @param {*} filename * @param {*} filename
* @return {Stream} * @return {Stream}
*/ */
add_tarball(name, filename) { add_tarball(name: string, filename: string) {
return this.localStorage.addTarball(name, filename); return this.localStorage.addTarball(name, filename);
} }
@ -234,7 +259,7 @@ class Storage {
* @param {*} filename * @param {*} filename
* @return {Stream} * @return {Stream}
*/ */
get_tarball(name, filename) { get_tarball(name: string, filename: string) {
let readStream = new ReadTarball(); let readStream = new ReadTarball();
readStream.abort = function() {}; readStream.abort = function() {};
@ -244,7 +269,7 @@ class Storage {
// information about it, so fetching package info is unnecessary // information about it, so fetching package info is unnecessary
// trying local first // trying local first
let localStream = self.localStorage.getTarball(name, filename); let localStream: IReadTarball = self.localStorage.getTarball(name, filename);
let is_open = false; let is_open = false;
localStream.on('error', (err) => { localStream.on('error', (err) => {
if (is_open || err.status !== 404) { if (is_open || err.status !== 404) {
@ -255,13 +280,13 @@ class Storage {
let err404 = err; let err404 = err;
localStream.abort(); localStream.abort();
localStream = null; // gc localStream = null; // gc
self.localStorage.getPackageMetadata(name, (err, info) => { self.localStorage.getPackageMetadata(name, (err, info: Package) => {
if (_.isNil(err) && info._distfiles && _.isNil(info._distfiles[filename]) === false) { if (_.isNil(err) && info._distfiles && _.isNil(info._distfiles[filename]) === false) {
// information about this file exists locally // information about this file exists locally
serveFile(info._distfiles[filename]); serveFile(info._distfiles[filename]);
} else { } else {
// we know nothing about this file, trying to get information elsewhere // we know nothing about this file, trying to get information elsewhere
self._syncUplinksMetadata(name, info, {}, (err, info) => { self._syncUplinksMetadata(name, info, {}, (err, info: Package) => {
if (_.isNil(err) === false) { if (_.isNil(err) === false) {
return readStream.emit('error', err); return readStream.emit('error', err);
} }
@ -286,13 +311,16 @@ class Storage {
* Fetch and cache local/remote packages. * Fetch and cache local/remote packages.
* @param {Object} file define the package shape * @param {Object} file define the package shape
*/ */
function serveFile(file) { function serveFile(file: DistFile) {
let uplink = null; let uplink: any = null;
for (let p in self.uplinks) { for (let p in self.uplinks) {
// $FlowFixMe
if (self.uplinks[p].isUplinkValid(file.url)) { if (self.uplinks[p].isUplinkValid(file.url)) {
uplink = self.uplinks[p]; uplink = self.uplinks[p];
} }
} }
if (uplink == null) { if (uplink == null) {
uplink = new ProxyStorage({ uplink = new ProxyStorage({
url: file.url, url: file.url,
@ -300,10 +328,12 @@ class Storage {
_autogenerated: true, _autogenerated: true,
}, self.config); }, self.config);
} }
let savestream = null; let savestream = null;
if (uplink.config.cache) { if (uplink.config.cache) {
savestream = self.localStorage.addTarball(name, filename); savestream = self.localStorage.addTarball(name, filename);
} }
let on_open = function() { let on_open = function() {
// prevent it from being called twice // prevent it from being called twice
on_open = function() {}; on_open = function() {};
@ -366,7 +396,7 @@ class Storage {
* @property {boolean} options.keepUpLinkData keep up link info in package meta, last update, etc. * @property {boolean} options.keepUpLinkData keep up link info in package meta, last update, etc.
* @property {function} options.callback Callback for receive data * @property {function} options.callback Callback for receive data
*/ */
getPackage(options) { getPackage(options: any) {
this.localStorage.getPackageMetadata(options.name, (err, data) => { this.localStorage.getPackageMetadata(options.name, (err, data) => {
if (err && (!err.status || err.status >= 500)) { if (err && (!err.status || err.status >= 500)) {
// report internal errors right away // report internal errors right away
@ -374,7 +404,7 @@ class Storage {
} }
this._syncUplinksMetadata(options.name, data, {req: options.req}, this._syncUplinksMetadata(options.name, data, {req: options.req},
function getPackageSynUpLinksCallback(err, result, uplink_errors) { function getPackageSynUpLinksCallback(err, result: Package, uplink_errors) {
if (err) { if (err) {
return options.callback(err); return options.callback(err);
} }
@ -412,10 +442,10 @@ class Storage {
* @param {*} options * @param {*} options
* @return {Stream} * @return {Stream}
*/ */
search(startkey, options) { search(startkey: string, options: any) {
let self = this; let self = this;
// stream to write a tarball // stream to write a tarball
let stream = new Stream.PassThrough({objectMode: true}); let stream: any = new Stream.PassThrough({objectMode: true});
async.eachSeries(Object.keys(this.uplinks), function(up_name, cb) { async.eachSeries(Object.keys(this.uplinks), function(up_name, cb) {
// shortcut: if `local=1` is supplied, don't call uplinks // shortcut: if `local=1` is supplied, don't call uplinks
@ -423,7 +453,7 @@ class Storage {
return cb(); return cb();
} }
// search by keyword for each uplink // search by keyword for each uplink
let lstream = self.uplinks[up_name].search(options); let lstream: IUploadTarball = self.uplinks[up_name].search(options);
// join streams // join streams
lstream.pipe(stream, {end: false}); lstream.pipe(stream, {end: false});
lstream.on('error', function(err) { lstream.on('error', function(err) {
@ -444,7 +474,7 @@ class Storage {
// executed after all series // executed after all series
function() { function() {
// attach a local search results // attach a local search results
let lstream = self.localStorage.search(startkey, options); let lstream: IReadTarball = self.localStorage.search(startkey, options);
stream.abort = function() { stream.abort = function() {
lstream.abort(); lstream.abort();
}; };
@ -462,7 +492,7 @@ class Storage {
* Retrieve only private local packages * Retrieve only private local packages
* @param {*} callback * @param {*} callback
*/ */
getLocalDatabase(callback) { getLocalDatabase(callback: Callback) {
let self = this; let self = this;
let locals = this.localStorage.localData.get(); let locals = this.localStorage.localData.get();
let packages = []; let packages = [];
@ -503,7 +533,7 @@ class Storage {
* @param {*} options * @param {*} options
* @param {*} callback * @param {*} callback
*/ */
_syncUplinksMetadata(name, packageInfo, options, callback) { _syncUplinksMetadata(name: string, packageInfo: Package, options: any, callback: Callback) {
let exists = false; let exists = false;
const self = this; const self = this;
const upLinks = []; const upLinks = [];
@ -583,7 +613,7 @@ class Storage {
exists = true; exists = true;
cb(); cb();
}); });
}, (err, upLinksErrors) => { }, (err: Error, upLinksErrors: any) => {
assert(!err && Array.isArray(upLinksErrors)); assert(!err && Array.isArray(upLinksErrors));
if (!exists) { if (!exists) {
return callback( Utils.ErrorCode.get404('no such package available') return callback( Utils.ErrorCode.get404('no such package available')
@ -591,7 +621,7 @@ class Storage {
, upLinksErrors ); , upLinksErrors );
} }
self.localStorage.updateVersions(name, packageInfo, function(err, packageJsonLocal) { self.localStorage.updateVersions(name, packageInfo, function(err, packageJsonLocal: Package) {
if (err) { if (err) {
return callback(err); return callback(err);
} }
@ -606,12 +636,13 @@ class Storage {
* @param {String} upLink uplink name * @param {String} upLink uplink name
* @private * @private
*/ */
_updateVersionsHiddenUpLink(versions, upLink) { _updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy) {
for (let i in versions) { for (let i in versions) {
if (Object.prototype.hasOwnProperty.call(versions, i)) { if (Object.prototype.hasOwnProperty.call(versions, i)) {
const version = versions[i]; const version = versions[i];
// holds a "hidden" value to be used by the package storage. // holds a "hidden" value to be used by the package storage.
// $FlowFixMe
version[Symbol.for('__verdaccio_uplink')] = upLink.upname; version[Symbol.for('__verdaccio_uplink')] = upLink.upname;
} }
} }
@ -622,15 +653,14 @@ class Storage {
* @param {Object} config * @param {Object} config
* @private * @private
*/ */
_setupUpLinks(config) { _setupUpLinks(config: Config) {
// we support a number of uplinks, but only one local storage for (let uplinkName in config.uplinks) {
// Proxy and Local classes should have similar API interfaces if (Object.prototype.hasOwnProperty.call(config.uplinks, uplinkName)) {
this.uplinks = {};
for (let p in config.uplinks) {
if (Object.prototype.hasOwnProperty.call(config.uplinks, p)) {
// instance for each up-link definition // instance for each up-link definition
this.uplinks[p] = new ProxyStorage(config.uplinks[p], config); const proxy: IProxy = new ProxyStorage(config.uplinks[uplinkName], config);
this.uplinks[p].upname = p; proxy.upname = uplinkName;
this.uplinks[uplinkName] = proxy;
} }
} }
} }
@ -643,7 +673,7 @@ class Storage {
* @param {*} config * @param {*} config
* @static * @static
*/ */
static _mergeVersions(local, up, config) { static _mergeVersions(local: Package, up: Package, config: Config) {
// copy new versions to a cache // copy new versions to a cache
// NOTE: if a certain version was updated, we can't refresh it reliably // NOTE: if a certain version was updated, we can't refresh it reliably
for (let i in up.versions) { for (let i in up.versions) {

View File

@ -208,9 +208,9 @@
version "1.0.0" version "1.0.0"
resolved "https://registry.npmjs.org/@verdaccio/streams/-/streams-1.0.0.tgz#d5d24c6747208728b9fd16b908e3932c3fb1f864" resolved "https://registry.npmjs.org/@verdaccio/streams/-/streams-1.0.0.tgz#d5d24c6747208728b9fd16b908e3932c3fb1f864"
"@verdaccio/types@0.2.0": "@verdaccio/types@0.3.0":
version "0.2.0" version "0.3.0"
resolved "https://registry.npmjs.org/@verdaccio/types/-/types-0.2.0.tgz#bd12a9d0df832b123585741c0de43f361f742a99" resolved "https://registry.npmjs.org/@verdaccio/types/-/types-0.3.0.tgz#9a1f30dcf3aa4902cdd69ffcdd4c61cc2b8dd72a"
JSONStream@^1.0.4, JSONStream@^1.1.1: JSONStream@^1.0.4, JSONStream@^1.1.1:
version "1.3.2" version "1.3.2"
@ -628,8 +628,8 @@ babel-eslint@8.2.1:
eslint-visitor-keys "^1.0.0" eslint-visitor-keys "^1.0.0"
babel-generator@^6.18.0, babel-generator@^6.21.0, babel-generator@^6.26.0: babel-generator@^6.18.0, babel-generator@^6.21.0, babel-generator@^6.26.0:
version "6.26.0" version "6.26.1"
resolved "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" resolved "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
dependencies: dependencies:
babel-messages "^6.23.0" babel-messages "^6.23.0"
babel-runtime "^6.26.0" babel-runtime "^6.26.0"
@ -637,7 +637,7 @@ babel-generator@^6.18.0, babel-generator@^6.21.0, babel-generator@^6.26.0:
detect-indent "^4.0.0" detect-indent "^4.0.0"
jsesc "^1.3.0" jsesc "^1.3.0"
lodash "^4.17.4" lodash "^4.17.4"
source-map "^0.5.6" source-map "^0.5.7"
trim-right "^1.0.1" trim-right "^1.0.1"
babel-helper-bindify-decorators@^6.24.1: babel-helper-bindify-decorators@^6.24.1:
@ -4125,8 +4125,8 @@ http-errors@1.6.2, http-errors@^1.4.0, http-errors@~1.6.2:
statuses ">= 1.3.1 < 2" statuses ">= 1.3.1 < 2"
http-parser-js@>=0.4.0: http-parser-js@>=0.4.0:
version "0.4.9" version "0.4.10"
resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.9.tgz#ea1a04fb64adff0242e9974f297dd4c3cad271e1" resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4"
http-proxy-middleware@~0.17.4: http-proxy-middleware@~0.17.4:
version "0.17.4" version "0.17.4"
@ -7016,8 +7016,8 @@ react-router@^4.2.0:
warning "^3.0.0" warning "^3.0.0"
react-stand-in@^4.0.0-beta.17: react-stand-in@^4.0.0-beta.17:
version "4.0.0-beta.18" version "4.0.0-beta.19"
resolved "https://registry.npmjs.org/react-stand-in/-/react-stand-in-4.0.0-beta.18.tgz#67d83309ae5d95526a2d1124beaa7ab093085cb2" resolved "https://registry.npmjs.org/react-stand-in/-/react-stand-in-4.0.0-beta.19.tgz#ef808b1476fc9abb6dc61c424d640f4cae90b841"
dependencies: dependencies:
shallowequal "^1.0.2" shallowequal "^1.0.2"
@ -7828,7 +7828,7 @@ source-map-url@^0.4.0:
version "0.4.0" version "0.4.0"
resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
source-map@0.5.x, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.6: source-map@0.5.x, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.6:
version "0.5.7" version "0.5.7"
resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"