mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-30 22:34:10 -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) {
|
allow_access(package_name, user, callback) {
|
||||||
let plugins = this.plugins.slice(0);
|
let plugins = this.plugins.slice(0);
|
||||||
let pkg = Object.assign({name: package_name},
|
let pkg = Object.assign({name: package_name},
|
||||||
this.config.get_package_spec(package_name))
|
this.config.getMatchedPackagesSpec(package_name))
|
||||||
|
|
||||||
;(function next() {
|
;(function next() {
|
||||||
let p = plugins.shift();
|
let p = plugins.shift();
|
||||||
|
@ -183,7 +183,7 @@ class Auth {
|
||||||
allow_publish(package_name, user, callback) {
|
allow_publish(package_name, user, callback) {
|
||||||
let plugins = this.plugins.slice(0);
|
let plugins = this.plugins.slice(0);
|
||||||
let pkg = Object.assign({name: package_name},
|
let pkg = Object.assign({name: package_name},
|
||||||
this.config.get_package_spec(package_name))
|
this.config.getMatchedPackagesSpec(package_name))
|
||||||
|
|
||||||
;(function next() {
|
;(function next() {
|
||||||
let p = plugins.shift();
|
let p = plugins.shift();
|
||||||
|
|
|
@ -8,6 +8,7 @@ const _ = require('lodash');
|
||||||
const Error = require('http-errors');
|
const Error = require('http-errors');
|
||||||
const Crypto = require('crypto');
|
const Crypto = require('crypto');
|
||||||
const minimatch = require('minimatch');
|
const minimatch = require('minimatch');
|
||||||
|
|
||||||
const Utils = require('./utils');
|
const Utils = require('./utils');
|
||||||
const pkginfo = require('pkginfo')(module); // eslint-disable-line no-unused-vars
|
const pkginfo = require('pkginfo')(module); // eslint-disable-line no-unused-vars
|
||||||
const pkgVersion = module.exports.version;
|
const pkgVersion = module.exports.version;
|
||||||
|
@ -30,50 +31,12 @@ function flatten(array) {
|
||||||
return result;
|
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
|
* Coordinates the application configuration
|
||||||
*/
|
*/
|
||||||
class Config {
|
class Config {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
|
||||||
* @param {*} config config the content
|
* @param {*} config config the content
|
||||||
*/
|
*/
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
|
@ -214,23 +177,25 @@ class Config {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether an uplink can proxy
|
* Check whether an uplink can proxy
|
||||||
* @param {*} pkg
|
* @param {String} pkg package anem
|
||||||
* @param {*} uplink
|
* @param {*} upLink
|
||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
*/
|
*/
|
||||||
can_proxy_to(pkg, uplink) {
|
hasProxyTo(pkg, upLink) {
|
||||||
return (this.get_package_spec(pkg).proxy || []).reduce(function(prev, curr) {
|
return (this.getMatchedPackagesSpec(pkg).proxy || []).reduce(function(prev, curr) {
|
||||||
if (uplink === curr) return true;
|
if (upLink === curr) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return prev;
|
return prev;
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for package spec
|
* Check for package spec
|
||||||
* @param {*} pkg
|
* @param {String} pkg package name
|
||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
get_package_spec(pkg) {
|
getMatchedPackagesSpec(pkg) {
|
||||||
for (let i in this.packages) {
|
for (let i in this.packages) {
|
||||||
if (minimatch.makeRe(i).exec(pkg)) {
|
if (minimatch.makeRe(i).exec(pkg)) {
|
||||||
return this.packages[i];
|
return this.packages[i];
|
||||||
|
@ -257,4 +222,3 @@ class Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Config;
|
module.exports = Config;
|
||||||
module.exports.parse_interval = parse_interval;
|
|
||||||
|
|
|
@ -8,10 +8,10 @@ const semver = require('semver');
|
||||||
const Stream = require('stream');
|
const Stream = require('stream');
|
||||||
|
|
||||||
const Search = require('./search');
|
const Search = require('./search');
|
||||||
const LocalStorage = require('./local-storage');
|
const LocalStorage = require('./storage/local/local-storage');
|
||||||
const Logger = require('./logger');
|
const Logger = require('./logger');
|
||||||
const MyStreams = require('./streams');
|
const MyStreams = require('./storage/streams');
|
||||||
const Proxy = require('./up-storage');
|
const Proxy = require('./storage/up-storage');
|
||||||
const Utils = require('./utils');
|
const Utils = require('./utils');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,7 +67,7 @@ class Storage {
|
||||||
* Check whether a package exist in any of the uplinks.
|
* Check whether a package exist in any of the uplinks.
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
const check_package_remote = () => {
|
const checkPackageRemote = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
self._sync_package_with_uplinks(name, null, {}, (err, results, err_results) => {
|
self._sync_package_with_uplinks(name, null, {}, (err, results, err_results) => {
|
||||||
// something weird
|
// something weird
|
||||||
|
@ -97,7 +97,7 @@ class Storage {
|
||||||
* Add a package to the local database
|
* Add a package to the local database
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
const publish_package = () => {
|
const publishPackage = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
self.localStorage.addPackage(name, metadata, (err, latest) => {
|
self.localStorage.addPackage(name, metadata, (err, latest) => {
|
||||||
if (!_.isNull(err)) {
|
if (!_.isNull(err)) {
|
||||||
|
@ -116,8 +116,8 @@ class Storage {
|
||||||
// so all requests are necessary
|
// so all requests are necessary
|
||||||
checkPackageLocal()
|
checkPackageLocal()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return check_package_remote().then(() => {
|
return checkPackageRemote().then(() => {
|
||||||
return publish_package().then(() => {
|
return publishPackage().then(() => {
|
||||||
callback();
|
callback();
|
||||||
}, (err) => callback(err));
|
}, (err) => callback(err));
|
||||||
}, (err) => callback(err));
|
}, (err) => callback(err));
|
||||||
|
@ -499,7 +499,7 @@ class Storage {
|
||||||
|
|
||||||
let uplinks = [];
|
let uplinks = [];
|
||||||
for (let i in self.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]);
|
uplinks.push(self.uplinks[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const createError = require('http-errors');
|
const createError = require('http-errors');
|
||||||
const mkdirp = require('mkdirp');
|
const mkdirp = require('mkdirp');
|
||||||
const MyStream = require('./streams');
|
const MyStream = require('../streams');
|
||||||
const locker = require('./file-locking');
|
const locker = require('../../file-locking');
|
||||||
const fileExist = 'EEXISTS';
|
const fileExist = 'EEXISTS';
|
||||||
const noSuchFile = 'ENOENT';
|
const noSuchFile = 'ENOENT';
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
/* eslint prefer-rest-params: "off" */
|
/* eslint prefer-rest-params: "off" */
|
||||||
/* eslint prefer-spread: "off" */
|
/* eslint prefer-spread: "off" */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const Crypto = require('crypto');
|
const Crypto = require('crypto');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const Path = require('path');
|
const Path = require('path');
|
||||||
const Stream = require('stream');
|
const Stream = require('stream');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
|
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const createError = require('http-errors');
|
const createError = require('http-errors');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
const fsStorage = require('./local-fs');
|
const fsStorage = require('./local-fs');
|
||||||
const LocalData = require('./local-data');
|
const LocalData = require('./local-data');
|
||||||
const Logger = require('./logger');
|
const Logger = require('../../logger');
|
||||||
const customStream = require('./streams');
|
const customStream = require('../streams');
|
||||||
const Utils = require('./utils');
|
const Utils = require('../../utils');
|
||||||
|
|
||||||
const pkgFileName = 'package.json';
|
const pkgFileName = 'package.json';
|
||||||
const fileExist = 'EEXISTS';
|
const fileExist = 'EEXISTS';
|
||||||
const noSuchFile = 'ENOENT';
|
const noSuchFile = 'ENOENT';
|
||||||
const resourceNotAvailable = 'EAGAIN';
|
const resourceNotAvailable = 'EAGAIN';
|
||||||
|
|
||||||
// returns the minimal package file
|
const generatePackageTemplate = function(name) {
|
||||||
const get_boilerplate = function(name) {
|
|
||||||
return {
|
return {
|
||||||
// standard things
|
// standard things
|
||||||
'name': name,
|
'name': name,
|
||||||
|
@ -47,15 +47,24 @@ class LocalStorage {
|
||||||
*/
|
*/
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
// local data handler is linked with the configuration handler
|
this.localList = new LocalData(this._buildStoragePath(this.config));
|
||||||
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.logger = Logger.logger.child({sub: 'fs'});
|
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.
|
* Add a package.
|
||||||
|
@ -66,11 +75,12 @@ class LocalStorage {
|
||||||
*/
|
*/
|
||||||
addPackage(name, info, callback) {
|
addPackage(name, info, callback) {
|
||||||
const storage = this.storage(name);
|
const storage = this.storage(name);
|
||||||
|
|
||||||
if (!storage) {
|
if (!storage) {
|
||||||
return callback( createError(404, 'this package cannot be added'));
|
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) {
|
if (err && err.code === fileExist) {
|
||||||
return callback( createError(409, 'this package is already present'));
|
return callback( createError(409, 'this package is already present'));
|
||||||
}
|
}
|
||||||
|
@ -607,7 +617,7 @@ class LocalStorage {
|
||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
storage(pkg) {
|
storage(pkg) {
|
||||||
let path = this.config.get_package_spec(pkg).storage;
|
let path = this.config.getMatchedPackagesSpec(pkg).storage;
|
||||||
if (_.isNil(path)) {
|
if (_.isNil(path)) {
|
||||||
path = this.config.storage;
|
path = this.config.storage;
|
||||||
}
|
}
|
||||||
|
@ -709,7 +719,7 @@ class LocalStorage {
|
||||||
_readCreatePackage(name, callback) {
|
_readCreatePackage(name, callback) {
|
||||||
const storage = this.storage(name);
|
const storage = this.storage(name);
|
||||||
if (!storage) {
|
if (!storage) {
|
||||||
const data = get_boilerplate(name);
|
const data = generatePackageTemplate(name);
|
||||||
this._normalizePackage(data);
|
this._normalizePackage(data);
|
||||||
return callback(null, data);
|
return callback(null, data);
|
||||||
}
|
}
|
||||||
|
@ -718,7 +728,7 @@ class LocalStorage {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err.code === noSuchFile) {
|
if (err.code === noSuchFile) {
|
||||||
// if package doesn't exist, we create it here
|
// if package doesn't exist, we create it here
|
||||||
data = get_boilerplate(name);
|
data = generatePackageTemplate(name);
|
||||||
} else {
|
} else {
|
||||||
return callback(this._internalError(err, pkgFileName, 'error reading'));
|
return callback(this._internalError(err, pkgFileName, 'error reading'));
|
||||||
}
|
}
|
|
@ -6,10 +6,9 @@ const _ = require('lodash');
|
||||||
const request = require('request');
|
const request = require('request');
|
||||||
const Stream = require('stream');
|
const Stream = require('stream');
|
||||||
const URL = require('url');
|
const URL = require('url');
|
||||||
const parseInterval = require('./config').parse_interval;
|
const Logger = require('../logger');
|
||||||
const Logger = require('./logger');
|
|
||||||
const MyStreams = require('./streams');
|
const MyStreams = require('./streams');
|
||||||
const Utils = require('./utils');
|
const Utils = require('../utils');
|
||||||
const zlib = require('zlib');
|
const zlib = require('zlib');
|
||||||
const encode = function(thing) {
|
const encode = function(thing) {
|
||||||
return encodeURIComponent(thing).replace(/^%40/, '@');
|
return encodeURIComponent(thing).replace(/^%40/, '@');
|
||||||
|
@ -58,10 +57,10 @@ class ProxyStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
// a bunch of different configurable timers
|
// a bunch of different configurable timers
|
||||||
this.maxage = parseInterval(setConfig(this.config, 'maxage', '2m' ));
|
this.maxage = Utils.parseInterval(setConfig(this.config, 'maxage', '2m' ));
|
||||||
this.timeout = parseInterval(setConfig(this.config, 'timeout', '30s'));
|
this.timeout = Utils.parseInterval(setConfig(this.config, 'timeout', '30s'));
|
||||||
this.max_fails = Number(setConfig(this.config, 'max_fails', 2 ));
|
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.semver_sort = semverSort;
|
||||||
module.exports.parse_address = parse_address;
|
module.exports.parse_address = parse_address;
|
||||||
module.exports.get_version = get_version;
|
module.exports.get_version = get_version;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let ReadTarball = require('../../lib/streams').ReadTarball;
|
let ReadTarball = require('../../lib/storage/streams').ReadTarball;
|
||||||
|
|
||||||
describe('mystreams', function() {
|
describe('mystreams', function() {
|
||||||
it('should delay events', function(cb) {
|
it('should delay events', function(cb) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let assert = require('assert');
|
let assert = require('assert');
|
||||||
let Storage = require('../../lib/up-storage');
|
let Storage = require('../../lib/storage/up-storage');
|
||||||
|
|
||||||
require('../../lib/logger').setup([]);
|
require('../../lib/logger').setup([]);
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let assert = require('assert');
|
let assert = require('assert');
|
||||||
let parse_interval = require('../../lib/config').parse_interval;
|
let parseInterval = require('../../lib/utils').parseInterval;
|
||||||
|
|
||||||
describe('Parse interval', function() {
|
describe('Parse interval', function() {
|
||||||
function add_test(str, res) {
|
function add_test(str, res) {
|
||||||
it('parse ' + str, function() {
|
it('parse ' + str, function() {
|
||||||
if (res === null) {
|
if (res === null) {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
console.log(parse_interval(str));
|
console.log(parseInterval(str));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
assert.strictEqual(parse_interval(str), res);
|
assert.strictEqual(parseInterval(str), res);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue