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:
parent
d2a4cf3264
commit
2ee4f38743
12 changed files with 96 additions and 85 deletions
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
|
@ -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'));
|
||||
}
|
|
@ -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' ));
|
||||
}
|
||||
|
||||
/**
|
38
lib/utils.js
38
lib/utils.js
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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([]);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue