mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-16 21:56:25 -05:00
refactor(flow): add flow support to storage
This commit is contained in:
parent
42f23da363
commit
7a86b71342
5 changed files with 78 additions and 46 deletions
2
.yarnrc
Normal file
2
.yarnrc
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
save-prefix ""
|
||||||
|
registry "http://registry.npmjs.org/"
|
|
@ -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",
|
||||||
|
|
|
@ -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(() => {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
BIN
yarn.lock
BIN
yarn.lock
Binary file not shown.
Loading…
Reference in a new issue