0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-12-16 21:56:25 -05:00

Refactor Storage, move local storage to inner folder.

Refactor methods to camelCase
Relocate utilities
This commit is contained in:
Juan Picado @jotadeveloper 2017-06-10 23:41:24 +02:00
parent d2a4cf3264
commit 2ee4f38743
No known key found for this signature in database
GPG key ID: 18AC54485952D158
12 changed files with 96 additions and 85 deletions

View file

@ -157,7 +157,7 @@ class Auth {
allow_access(package_name, user, callback) {
let plugins = this.plugins.slice(0);
let pkg = Object.assign({name: package_name},
this.config.get_package_spec(package_name))
this.config.getMatchedPackagesSpec(package_name))
;(function next() {
let p = plugins.shift();
@ -183,7 +183,7 @@ class Auth {
allow_publish(package_name, user, callback) {
let plugins = this.plugins.slice(0);
let pkg = Object.assign({name: package_name},
this.config.get_package_spec(package_name))
this.config.getMatchedPackagesSpec(package_name))
;(function next() {
let p = plugins.shift();

View file

@ -8,6 +8,7 @@ const _ = require('lodash');
const Error = require('http-errors');
const Crypto = require('crypto');
const minimatch = require('minimatch');
const Utils = require('./utils');
const pkginfo = require('pkginfo')(module); // eslint-disable-line no-unused-vars
const pkgVersion = module.exports.version;
@ -30,50 +31,12 @@ function flatten(array) {
return result;
}
const parse_interval_table = {
'': 1000,
'ms': 1,
's': 1000,
'm': 60*1000,
'h': 60*60*1000,
'd': 86400000,
'w': 7*86400000,
'M': 30*86400000,
'y': 365*86400000,
};
/**
* Parse an internal string to number
* @param {*} interval
* @return {Number}
*/
function parse_interval(interval) {
if (typeof(interval) === 'number') {
return interval * 1000;
}
let result = 0;
let last_suffix = Infinity;
interval.split(/\s+/).forEach(function(x) {
if (!x) return;
let m = x.match(/^((0|[1-9][0-9]*)(\.[0-9]+)?)(ms|s|m|h|d|w|M|y|)$/);
if (!m
|| parse_interval_table[m[4]] >= last_suffix
|| (m[4] === '' && last_suffix !== Infinity)) {
throw Error('invalid interval: ' + interval);
}
last_suffix = parse_interval_table[m[4]];
result += Number(m[1]) * parse_interval_table[m[4]];
});
return result;
}
/**
* Coordinates the application configuration
*/
class Config {
/**
* Constructor
* @param {*} config config the content
*/
constructor(config) {
@ -214,23 +177,25 @@ class Config {
/**
* Check whether an uplink can proxy
* @param {*} pkg
* @param {*} uplink
* @param {String} pkg package anem
* @param {*} upLink
* @return {Boolean}
*/
can_proxy_to(pkg, uplink) {
return (this.get_package_spec(pkg).proxy || []).reduce(function(prev, curr) {
if (uplink === curr) return true;
hasProxyTo(pkg, upLink) {
return (this.getMatchedPackagesSpec(pkg).proxy || []).reduce(function(prev, curr) {
if (upLink === curr) {
return true;
}
return prev;
}, false);
}
/**
* Check for package spec
* @param {*} pkg
* @param {String} pkg package name
* @return {Object}
*/
get_package_spec(pkg) {
getMatchedPackagesSpec(pkg) {
for (let i in this.packages) {
if (minimatch.makeRe(i).exec(pkg)) {
return this.packages[i];
@ -257,4 +222,3 @@ class Config {
}
module.exports = Config;
module.exports.parse_interval = parse_interval;

View file

@ -8,10 +8,10 @@ const semver = require('semver');
const Stream = require('stream');
const Search = require('./search');
const LocalStorage = require('./local-storage');
const LocalStorage = require('./storage/local/local-storage');
const Logger = require('./logger');
const MyStreams = require('./streams');
const Proxy = require('./up-storage');
const MyStreams = require('./storage/streams');
const Proxy = require('./storage/up-storage');
const Utils = require('./utils');
/**
@ -67,7 +67,7 @@ class Storage {
* Check whether a package exist in any of the uplinks.
* @return {Promise}
*/
const check_package_remote = () => {
const checkPackageRemote = () => {
return new Promise((resolve, reject) => {
self._sync_package_with_uplinks(name, null, {}, (err, results, err_results) => {
// something weird
@ -97,7 +97,7 @@ class Storage {
* Add a package to the local database
* @return {Promise}
*/
const publish_package = () => {
const publishPackage = () => {
return new Promise((resolve, reject) => {
self.localStorage.addPackage(name, metadata, (err, latest) => {
if (!_.isNull(err)) {
@ -116,8 +116,8 @@ class Storage {
// so all requests are necessary
checkPackageLocal()
.then(() => {
return check_package_remote().then(() => {
return publish_package().then(() => {
return checkPackageRemote().then(() => {
return publishPackage().then(() => {
callback();
}, (err) => callback(err));
}, (err) => callback(err));
@ -499,7 +499,7 @@ class Storage {
let uplinks = [];
for (let i in self.uplinks) {
if (self.config.can_proxy_to(name, i)) {
if (self.config.hasProxyTo(name, i)) {
uplinks.push(self.uplinks[i]);
}
}

View file

@ -6,8 +6,8 @@ const fs = require('fs');
const path = require('path');
const createError = require('http-errors');
const mkdirp = require('mkdirp');
const MyStream = require('./streams');
const locker = require('./file-locking');
const MyStream = require('../streams');
const locker = require('../../file-locking');
const fileExist = 'EEXISTS';
const noSuchFile = 'ENOENT';

View file

@ -1,29 +1,29 @@
/* eslint prefer-rest-params: "off" */
/* eslint prefer-spread: "off" */
'use strict';
const assert = require('assert');
const Crypto = require('crypto');
const fs = require('fs');
const Path = require('path');
const Stream = require('stream');
const url = require('url');
const async = require('async');
const createError = require('http-errors');
const _ = require('lodash');
const fsStorage = require('./local-fs');
const LocalData = require('./local-data');
const Logger = require('./logger');
const customStream = require('./streams');
const Utils = require('./utils');
const Logger = require('../../logger');
const customStream = require('../streams');
const Utils = require('../../utils');
const pkgFileName = 'package.json';
const fileExist = 'EEXISTS';
const noSuchFile = 'ENOENT';
const resourceNotAvailable = 'EAGAIN';
// returns the minimal package file
const get_boilerplate = function(name) {
const generatePackageTemplate = function(name) {
return {
// standard things
'name': name,
@ -47,15 +47,24 @@ class LocalStorage {
*/
constructor(config) {
this.config = config;
// local data handler is linked with the configuration handler
this.localList = new LocalData(Path.join(Path.resolve(Path.dirname(config.self_path || ''), config.storage),
// FUTURE: the database might be parameterizable from config.yaml
'.sinopia-db.json'
)
);
this.localList = new LocalData(this._buildStoragePath(this.config));
this.logger = Logger.logger.child({sub: 'fs'});
}
/**
* Build the local database path.
* @param {Object} config
* @return {string|String|*}
* @private
*/
_buildStoragePath(config) {
// FUTURE: the database might be parameterizable from config.yaml
return Path.join(Path.resolve(Path.dirname(config.self_path || ''),
config.storage,
'.sinopia-db.json'
));
}
/**
* Add a package.
@ -66,11 +75,12 @@ class LocalStorage {
*/
addPackage(name, info, callback) {
const storage = this.storage(name);
if (!storage) {
return callback( createError(404, 'this package cannot be added'));
}
storage.createJSON(pkgFileName, get_boilerplate(name), function(err) {
storage.createJSON(pkgFileName, generatePackageTemplate(name), function(err) {
if (err && err.code === fileExist) {
return callback( createError(409, 'this package is already present'));
}
@ -607,7 +617,7 @@ class LocalStorage {
* @return {Object}
*/
storage(pkg) {
let path = this.config.get_package_spec(pkg).storage;
let path = this.config.getMatchedPackagesSpec(pkg).storage;
if (_.isNil(path)) {
path = this.config.storage;
}
@ -709,7 +719,7 @@ class LocalStorage {
_readCreatePackage(name, callback) {
const storage = this.storage(name);
if (!storage) {
const data = get_boilerplate(name);
const data = generatePackageTemplate(name);
this._normalizePackage(data);
return callback(null, data);
}
@ -718,7 +728,7 @@ class LocalStorage {
if (err) {
if (err.code === noSuchFile) {
// if package doesn't exist, we create it here
data = get_boilerplate(name);
data = generatePackageTemplate(name);
} else {
return callback(this._internalError(err, pkgFileName, 'error reading'));
}

View file

@ -6,10 +6,9 @@ const _ = require('lodash');
const request = require('request');
const Stream = require('stream');
const URL = require('url');
const parseInterval = require('./config').parse_interval;
const Logger = require('./logger');
const Logger = require('../logger');
const MyStreams = require('./streams');
const Utils = require('./utils');
const Utils = require('../utils');
const zlib = require('zlib');
const encode = function(thing) {
return encodeURIComponent(thing).replace(/^%40/, '@');
@ -58,10 +57,10 @@ class ProxyStorage {
}
// a bunch of different configurable timers
this.maxage = parseInterval(setConfig(this.config, 'maxage', '2m' ));
this.timeout = parseInterval(setConfig(this.config, 'timeout', '30s'));
this.maxage = Utils.parseInterval(setConfig(this.config, 'maxage', '2m' ));
this.timeout = Utils.parseInterval(setConfig(this.config, 'timeout', '30s'));
this.max_fails = Number(setConfig(this.config, 'max_fails', 2 ));
this.fail_timeout = parseInterval(setConfig(this.config, 'fail_timeout', '5m' ));
this.fail_timeout = Utils.parseInterval(setConfig(this.config, 'fail_timeout', '5m' ));
}
/**

View file

@ -277,6 +277,44 @@ function normalize_dist_tags(data) {
}
}
const parseIntervalTable = {
'': 1000,
'ms': 1,
's': 1000,
'm': 60*1000,
'h': 60*60*1000,
'd': 86400000,
'w': 7*86400000,
'M': 30*86400000,
'y': 365*86400000,
};
/**
* Parse an internal string to number
* @param {*} interval
* @return {Number}
*/
function parseInterval(interval) {
if (typeof(interval) === 'number') {
return interval * 1000;
}
let result = 0;
let last_suffix = Infinity;
interval.split(/\s+/).forEach(function(x) {
if (!x) return;
let m = x.match(/^((0|[1-9][0-9]*)(\.[0-9]+)?)(ms|s|m|h|d|w|M|y|)$/);
if (!m
|| parseIntervalTable[m[4]] >= last_suffix
|| (m[4] === '' && last_suffix !== Infinity)) {
throw Error('invalid interval: ' + interval);
}
last_suffix = parseIntervalTable[m[4]];
result += Number(m[1]) * parseIntervalTable[m[4]];
});
return result;
}
module.exports.parseInterval = parseInterval;
module.exports.semver_sort = semverSort;
module.exports.parse_address = parse_address;
module.exports.get_version = get_version;

View file

@ -1,6 +1,6 @@
'use strict';
let ReadTarball = require('../../lib/streams').ReadTarball;
let ReadTarball = require('../../lib/storage/streams').ReadTarball;
describe('mystreams', function() {
it('should delay events', function(cb) {

View file

@ -1,7 +1,7 @@
'use strict';
let assert = require('assert');
let Storage = require('../../lib/up-storage');
let Storage = require('../../lib/storage/up-storage');
require('../../lib/logger').setup([]);

View file

@ -1,17 +1,17 @@
'use strict';
let assert = require('assert');
let parse_interval = require('../../lib/config').parse_interval;
let parseInterval = require('../../lib/utils').parseInterval;
describe('Parse interval', function() {
function add_test(str, res) {
it('parse ' + str, function() {
if (res === null) {
assert.throws(function() {
console.log(parse_interval(str));
console.log(parseInterval(str));
});
} else {
assert.strictEqual(parse_interval(str), res);
assert.strictEqual(parseInterval(str), res);
}
});
}