mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-03-04 02:02:39 -05:00
refactor: load storage as plugin and as fallback use LocalStorage
This commit is contained in:
parent
f320d5eeb4
commit
d352c6c63f
15 changed files with 116 additions and 101 deletions
|
@ -15,10 +15,10 @@
|
|||
"verdaccio": "./bin/verdaccio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@verdaccio/file-locking": "^0.0.5",
|
||||
"@verdaccio/local-storage": "^0.1.0",
|
||||
"@verdaccio/streams": "^0.0.2",
|
||||
"@verdaccio/types": "^0.1.0",
|
||||
"@verdaccio/file-locking": "0.0.5",
|
||||
"@verdaccio/local-storage": "0.1.0",
|
||||
"@verdaccio/streams": "0.0.2",
|
||||
"@verdaccio/types": "0.1.0",
|
||||
"JSONStream": "^1.1.1",
|
||||
"apache-md5": "^1.1.2",
|
||||
"async": "^2.6.0",
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
'use strict';
|
||||
import express from 'express';
|
||||
import Error from 'http-errors';
|
||||
import compression from 'compression';
|
||||
import _ from 'lodash';
|
||||
import cors from 'cors';
|
||||
import Storage from '../lib/storage';
|
||||
import {loadPlugin} from '../lib/plugin-loader';
|
||||
|
||||
const express = require('express');
|
||||
const Error = require('http-errors');
|
||||
const compression = require('compression');
|
||||
const Auth = require('../lib/auth');
|
||||
const Logger = require('../lib/logger');
|
||||
const Config = require('../lib/config');
|
||||
const Middleware = require('./web/middleware');
|
||||
const Cats = require('../lib/status-cats');
|
||||
const Storage = require('../lib/storage');
|
||||
const _ = require('lodash');
|
||||
const cors = require('cors');
|
||||
const load_plugins = require('../lib/plugin-loader').load_plugins;
|
||||
|
||||
module.exports = function(config_hash) {
|
||||
module.exports = function(configHash) {
|
||||
// Config
|
||||
Logger.setup(config_hash.logs);
|
||||
const config = new Config(config_hash);
|
||||
Logger.setup(configHash.logs);
|
||||
const config = new Config(configHash);
|
||||
const storage = new Storage(config);
|
||||
const auth = new Auth(config);
|
||||
const app = express();
|
||||
|
@ -86,7 +85,7 @@ module.exports = function(config_hash) {
|
|||
config: config,
|
||||
logger: Logger.logger,
|
||||
};
|
||||
const plugins = load_plugins(config, config.middlewares, plugin_params, function(plugin) {
|
||||
const plugins = loadPlugin(config, config.middlewares, plugin_params, function(plugin) {
|
||||
return plugin.register_middlewares;
|
||||
});
|
||||
plugins.forEach(function(plugin) {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
import Search from '../../lib/search';
|
||||
const bodyParser = require('body-parser');
|
||||
const express = require('express');
|
||||
const marked = require('marked');
|
||||
const _ = require('lodash');
|
||||
const Search = require('../../lib/search');
|
||||
const Middleware = require('./middleware');
|
||||
const match = Middleware.match;
|
||||
const validateName = Middleware.validate_name;
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
'use strict';
|
||||
import express from 'express';
|
||||
import _ from 'lodash';
|
||||
import fs from 'fs';
|
||||
import Search from '../../lib/search';
|
||||
import * as Utils from '../../lib/utils';
|
||||
|
||||
const express = require('express');
|
||||
const Search = require('../../lib/search');
|
||||
const Middleware = require('./middleware');
|
||||
const Utils = require('../../lib/utils');
|
||||
/* eslint new-cap:off */
|
||||
const router = express.Router();
|
||||
const _ = require('lodash');
|
||||
const env = require('../../config/env');
|
||||
const fs = require('fs');
|
||||
const template = fs.readFileSync(`${env.DIST_PATH}/index.html`).toString();
|
||||
const spliceURL = require('../../utils/string').spliceURL;
|
||||
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
/* eslint prefer-spread: "off" */
|
||||
/* eslint prefer-rest-params: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
import {loadPlugin} from '../lib/plugin-loader';
|
||||
const Crypto = require('crypto');
|
||||
const Error = require('http-errors');
|
||||
const Logger = require('./logger');
|
||||
const load_plugins = require('./plugin-loader').load_plugins;
|
||||
const pkgJson = require('../../package.json');
|
||||
const jwt = require('jsonwebtoken');
|
||||
/**
|
||||
|
@ -35,7 +33,7 @@ class Auth {
|
|||
}
|
||||
}
|
||||
|
||||
this.plugins = load_plugins(config, config.auth, plugin_params, function(p) {
|
||||
this.plugins = loadPlugin(config, config.auth, plugin_params, function(p) {
|
||||
return p.authenticate || p.allow_access || p.allow_publish;
|
||||
});
|
||||
|
||||
|
|
|
@ -551,7 +551,7 @@ class LocalStorage implements IStorage {
|
|||
return callback( Utils.ErrorCode.get404() );
|
||||
}
|
||||
|
||||
this._readJSON(storage, callback);
|
||||
this._readPackage(storage, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -574,6 +574,7 @@ class LocalStorage implements IStorage {
|
|||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
const listVersions: Array<string> = Object.keys(data.versions);
|
||||
const versions: Array<string> = Utils.semver_sort(listVersions);
|
||||
const latest: string = data['dist-tags'] && data['dist-tags'].latest ? data['dist-tags'].latest : versions.pop();
|
||||
|
@ -623,7 +624,7 @@ class LocalStorage implements IStorage {
|
|||
* @return {Object}
|
||||
*/
|
||||
_getLocalStorage(packageInfo: string): IPackageStorage {
|
||||
const path: string = this.__getLocalStoragePath(this.config.getMatchedPackagesSpec(packageInfo).storage);
|
||||
const path: string = this._getLocalStoragePath(this.config.getMatchedPackagesSpec(packageInfo).storage);
|
||||
|
||||
if (_.isString(path) === false) {
|
||||
this.logger.debug( {name: packageInfo}, 'this package has no storage defined: @{name}' );
|
||||
|
@ -638,7 +639,7 @@ class LocalStorage implements IStorage {
|
|||
* @param {Object} storage
|
||||
* @param {Function} callback
|
||||
*/
|
||||
_readJSON(storage: IPackageStorage, callback: Callback) {
|
||||
_readPackage(storage: IPackageStorage, callback: Callback) {
|
||||
storage.readPackage(pkgFileName, (err, result) => {
|
||||
if (err) {
|
||||
if (err.code === noSuchFile) {
|
||||
|
@ -658,7 +659,7 @@ class LocalStorage implements IStorage {
|
|||
* @return {String}
|
||||
* @private
|
||||
*/
|
||||
__getLocalStoragePath(path: string): string {
|
||||
_getLocalStoragePath(path: string): string {
|
||||
if (_.isNil(path) === false) {
|
||||
return path;
|
||||
}
|
||||
|
@ -850,4 +851,4 @@ class LocalStorage implements IStorage {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = LocalStorage;
|
||||
export default LocalStorage;
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
'use strict';
|
||||
|
||||
const Path = require('path');
|
||||
const logger = require('./logger');
|
||||
import Path from 'path';
|
||||
import logger from './logger';
|
||||
|
||||
/**
|
||||
* Requires a module.
|
||||
* @param {*} path the module's path
|
||||
* @return {Object}
|
||||
*/
|
||||
function try_load(path) {
|
||||
function tryLoad(path) {
|
||||
try {
|
||||
return require(path);
|
||||
} catch(err) {
|
||||
|
@ -30,29 +29,29 @@ function try_load(path) {
|
|||
* @param {*} sanity_check callback that check the shape that should fulfill the plugin
|
||||
* @return {Array} list of plugins
|
||||
*/
|
||||
function load_plugins(config, plugin_configs, params, sanity_check) {
|
||||
function loadPlugin(config, plugin_configs, params, sanity_check) {
|
||||
let plugins = Object.keys(plugin_configs || {}).map(function(p) {
|
||||
let plugin;
|
||||
|
||||
// try local plugins first
|
||||
plugin = try_load(Path.resolve(__dirname + '/..//plugins', p));
|
||||
plugin = tryLoad(Path.resolve(__dirname + '/..//plugins', p));
|
||||
|
||||
// npm package
|
||||
if (plugin === null && p.match(/^[^\.\/]/)) {
|
||||
plugin = try_load(`verdaccio-${p}`);
|
||||
plugin = tryLoad(`verdaccio-${p}`);
|
||||
// compatibility for old sinopia plugins
|
||||
if (!plugin) {
|
||||
plugin = try_load(`sinopia-${p}`);
|
||||
plugin = tryLoad(`sinopia-${p}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (plugin === null) {
|
||||
plugin = try_load(p);
|
||||
plugin = tryLoad(p);
|
||||
}
|
||||
|
||||
// relative to config path
|
||||
if (plugin === null && p.match(/^\.\.?($|\/)/)) {
|
||||
plugin = try_load(Path.resolve(Path.dirname(config.self_path), p));
|
||||
plugin = tryLoad(Path.resolve(Path.dirname(config.self_path), p));
|
||||
}
|
||||
|
||||
if (plugin === null) {
|
||||
|
@ -78,4 +77,4 @@ function load_plugins(config, plugin_configs, params, sanity_check) {
|
|||
return plugins;
|
||||
}
|
||||
|
||||
exports.load_plugins = load_plugins;
|
||||
export {loadPlugin};
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* eslint no-invalid-this: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const lunr = require('lunr');
|
||||
|
||||
/**
|
||||
|
@ -80,4 +78,4 @@ class Search {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = new Search();
|
||||
export default new Search();
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const assert = require('assert');
|
||||
const async = require('async');
|
||||
const Error = require('http-errors');
|
||||
const semver = require('semver');
|
||||
const Stream = require('stream');
|
||||
import _ from 'lodash';
|
||||
import assert from 'assert';
|
||||
import async from 'async';
|
||||
import Error from 'http-errors';
|
||||
import semver from 'semver';
|
||||
import Stream from 'stream';
|
||||
|
||||
const Search = require('./search');
|
||||
const Logger = require('./logger');
|
||||
const LocalStorage = require('./local-storage');
|
||||
const MyStreams = require('@verdaccio/streams');
|
||||
const Proxy = require('./up-storage');
|
||||
const Utils = require('./utils');
|
||||
import Search from './search';
|
||||
import LocalStorage from './local-storage';
|
||||
import {ReadTarball} from '@verdaccio/streams';
|
||||
import ProxyStorage from './up-storage';
|
||||
import * as Utils from './utils';
|
||||
|
||||
import {loadPlugin} from '../lib/plugin-loader';
|
||||
|
||||
const Logger = require('../lib/logger');
|
||||
const WHITELIST = ['_rev', 'name', 'versions', 'dist-tags', 'readme', 'time'];
|
||||
const getDefaultMetadata = (name) => {
|
||||
return {
|
||||
|
@ -36,8 +37,29 @@ class Storage {
|
|||
constructor(config) {
|
||||
this.config = config;
|
||||
this._setupUpLinks(this.config);
|
||||
this.localStorage = new LocalStorage(config, Logger.logger);
|
||||
this.logger = Logger.logger.child();
|
||||
this.localStorage = this._loadStorage();
|
||||
}
|
||||
|
||||
_loadStorage() {
|
||||
const Storage = this._loadStorePlugin();
|
||||
|
||||
if (_.isNil(Storage)) {
|
||||
return new LocalStorage(this.config, Logger.logger);
|
||||
} else {
|
||||
return new Storage(this.config, Logger.logger);
|
||||
}
|
||||
}
|
||||
|
||||
_loadStorePlugin() {
|
||||
const plugin_params = {
|
||||
config: this.config,
|
||||
logger: this.logger,
|
||||
};
|
||||
|
||||
return _.head(loadPlugin(this.config, this.config.store, plugin_params, function(plugin) {
|
||||
return plugin.getPackageStorage;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -236,7 +258,7 @@ class Storage {
|
|||
* @return {Stream}
|
||||
*/
|
||||
get_tarball(name, filename) {
|
||||
let readStream = new MyStreams.ReadTarball();
|
||||
let readStream = new ReadTarball();
|
||||
readStream.abort = function() {};
|
||||
|
||||
let self = this;
|
||||
|
@ -295,7 +317,7 @@ class Storage {
|
|||
}
|
||||
}
|
||||
if (uplink == null) {
|
||||
uplink = new Proxy({
|
||||
uplink = new ProxyStorage({
|
||||
url: file.url,
|
||||
cache: true,
|
||||
_autogenerated: true,
|
||||
|
@ -629,7 +651,7 @@ class Storage {
|
|||
for (let p in config.uplinks) {
|
||||
if (Object.prototype.hasOwnProperty.call(config.uplinks, p)) {
|
||||
// instance for each up-link definition
|
||||
this.uplinks[p] = new Proxy(config.uplinks[p], config);
|
||||
this.uplinks[p] = new ProxyStorage(config.uplinks[p], config);
|
||||
this.uplinks[p].upname = p;
|
||||
}
|
||||
}
|
||||
|
@ -653,12 +675,14 @@ class Storage {
|
|||
}
|
||||
|
||||
// refresh dist-tags
|
||||
for (let i in up['dist-tags']) {
|
||||
if (local['dist-tags'][i] !== up['dist-tags'][i]) {
|
||||
if (!local['dist-tags'][i] || semver.lte(local['dist-tags'][i], up['dist-tags'][i])) {
|
||||
local['dist-tags'][i] = up['dist-tags'][i];
|
||||
const distTag = 'dist-tags';
|
||||
|
||||
for (let i in up[distTag]) {
|
||||
if (local[distTag][i] !== up[distTag][i]) {
|
||||
if (!local[distTag][i] || semver.lte(local[distTag][i], up[distTag][i])) {
|
||||
local[distTag][i] = up[distTag][i];
|
||||
}
|
||||
if (i === 'latest' && local['dist-tags'][i] === up['dist-tags'][i]) {
|
||||
if (i === 'latest' && local[distTag][i] === up[distTag][i]) {
|
||||
// if remote has more fresh package, we should borrow its readme
|
||||
local.readme = up.readme;
|
||||
}
|
||||
|
@ -668,4 +692,4 @@ class Storage {
|
|||
|
||||
}
|
||||
|
||||
module.exports = Storage;
|
||||
export default Storage;
|
||||
|
|
|
@ -588,4 +588,4 @@ class ProxyStorage {
|
|||
|
||||
}
|
||||
|
||||
module.exports = ProxyStorage;
|
||||
export default ProxyStorage;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
let assert = require('assert');
|
||||
let Storage = require('../../src/lib/up-storage');
|
||||
import assert from 'assert';
|
||||
import Storage from '../../src/lib/up-storage';
|
||||
|
||||
require('../../src/lib/logger').setup([]);
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
import {loadPlugin} from '../../src/lib/plugin-loader';
|
||||
import assert from 'assert';
|
||||
import path from 'path';
|
||||
|
||||
require('../../src/lib/logger').setup([]);
|
||||
const assert = require('assert');
|
||||
const load_plugins = require('../../src/lib/plugin-loader').load_plugins;
|
||||
const path = require('path');
|
||||
|
||||
describe('plugin loader', () => {
|
||||
|
||||
|
@ -15,10 +15,10 @@ describe('plugin loader', () => {
|
|||
'./unit/partials/test-plugin-storage/verdaccio-plugin': {}
|
||||
}
|
||||
}
|
||||
let p = load_plugins(_config, _config.auth, {}, function (p) {
|
||||
let plugins = loadPlugin(_config, _config.auth, {}, function (p) {
|
||||
return p.authenticate || p.allow_access || p.allow_publish;
|
||||
});
|
||||
assert(p.length === 1);
|
||||
assert(plugins.length === 1);
|
||||
});
|
||||
|
||||
test('testing auth plugin invalid plugin', () => {
|
||||
|
@ -29,7 +29,7 @@ describe('plugin loader', () => {
|
|||
}
|
||||
}
|
||||
try {
|
||||
load_plugins(_config, _config.auth, {}, function (p) {
|
||||
loadPlugin(_config, _config.auth, {}, function (p) {
|
||||
return p.authenticate || p.allow_access || p.allow_publish;
|
||||
});
|
||||
} catch(e) {
|
||||
|
@ -45,11 +45,11 @@ describe('plugin loader', () => {
|
|||
}
|
||||
}
|
||||
try {
|
||||
load_plugins(_config, _config.auth, {}, function (p) {
|
||||
return p.authenticate || p.allow_access || p.allow_publish;
|
||||
loadPlugin(_config, _config.auth, {}, function (plugin) {
|
||||
return plugin.authenticate || plugin.allow_access || plugin.allow_publish;
|
||||
});
|
||||
} catch(e) {
|
||||
assert(e.message === '"./unit/partials/test-plugin-storage/invalid-plugin-sanity" doesn\'t look like a valid plugin');
|
||||
} catch(err) {
|
||||
assert(err.message === '"./unit/partials/test-plugin-storage/invalid-plugin-sanity" doesn\'t look like a valid plugin');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -61,8 +61,8 @@ describe('plugin loader', () => {
|
|||
}
|
||||
}
|
||||
try {
|
||||
load_plugins(_config, _config.auth, {}, function (p) {
|
||||
return p.authenticate || p.allow_access || p.allow_publish;
|
||||
loadPlugin(_config, _config.auth, {}, function (plugin) {
|
||||
return plugin.authenticate || plugin.allow_access || plugin.allow_publish;
|
||||
});
|
||||
} catch(e) {
|
||||
assert(e.message === `"./unit/partials/test-plugin-storage/invalid-package" plugin not found\ntry "npm install verdaccio-./unit/partials/test-plugin-storage/invalid-package"`);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
let assert = require('assert');
|
||||
let Search = require('../../src/lib/search');
|
||||
let Storage = require('../../src/lib/storage');
|
||||
|
||||
import assert from 'assert';
|
||||
import Search from '../../src/lib/search';
|
||||
import Storage from '../../src/lib/storage';
|
||||
let config_hash = require('./partials/config');
|
||||
let Config = require('../../src/lib/config');
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
let assert = require('assert');
|
||||
let semver_sort = require('../../src/lib/utils').semver_sort;
|
||||
let merge = require('../../src/lib/storage')._merge_versions;
|
||||
import Storage from '../../src/lib/storage';
|
||||
|
||||
require('../../src/lib/logger').setup([]);
|
||||
|
||||
describe('merge versions', () => {
|
||||
describe('Storage._merge_versions versions', () => {
|
||||
|
||||
test('simple', () => {
|
||||
let pkg = {
|
||||
|
@ -14,7 +14,7 @@ describe('merge versions', () => {
|
|||
'dist-tags': {},
|
||||
};
|
||||
|
||||
merge(pkg, {versions: {a: 2, q: 2}});
|
||||
Storage._merge_versions(pkg, {versions: {a: 2, q: 2}});
|
||||
|
||||
assert.deepEqual(pkg, {
|
||||
'versions': {a: 1, b: 1, c: 1, q: 2},
|
||||
|
@ -28,7 +28,7 @@ describe('merge versions', () => {
|
|||
'dist-tags': {q: '1.1.1', w: '2.2.2'},
|
||||
};
|
||||
|
||||
merge(pkg, {'dist-tags': {q: '2.2.2', w: '3.3.3', t: '4.4.4'}});
|
||||
Storage._merge_versions(pkg, {'dist-tags': {q: '2.2.2', w: '3.3.3', t: '4.4.4'}});
|
||||
|
||||
assert.deepEqual(pkg, {
|
||||
'versions': {},
|
||||
|
@ -48,7 +48,7 @@ describe('merge versions', () => {
|
|||
// against our local 1.1.10, which may end up published as 1.1.3 in the
|
||||
// future
|
||||
|
||||
merge(pkg, {'dist-tags':{q:'1.1.2',w:'3.3.3',t:'4.4.4'}})
|
||||
Storage._merge_versions(pkg, {'dist-tags':{q:'1.1.2',w:'3.3.3',t:'4.4.4'}})
|
||||
|
||||
assert.deepEqual(pkg, {
|
||||
versions: {},
|
||||
|
|
|
@ -59,14 +59,14 @@
|
|||
version "8.5.1"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-8.5.1.tgz#4ec3020bcdfe2abffeef9ba3fbf26fca097514b5"
|
||||
|
||||
"@verdaccio/file-locking@^0.0.5":
|
||||
"@verdaccio/file-locking@0.0.5", "@verdaccio/file-locking@^0.0.5":
|
||||
version "0.0.5"
|
||||
resolved "https://registry.npmjs.org/@verdaccio/file-locking/-/file-locking-0.0.5.tgz#6172dfa2f7094a1da8e4c14906bfa33836b5713d"
|
||||
dependencies:
|
||||
lockfile "1.0.3"
|
||||
lodash "4.17.4"
|
||||
|
||||
"@verdaccio/local-storage@^0.1.0":
|
||||
"@verdaccio/local-storage@0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.npmjs.org/@verdaccio/local-storage/-/local-storage-0.1.0.tgz#bab877e5d07bea926c97f251bddf2bfa9edd7026"
|
||||
dependencies:
|
||||
|
@ -77,11 +77,11 @@
|
|||
lodash "4.17.4"
|
||||
mkdirp "0.5.1"
|
||||
|
||||
"@verdaccio/streams@^0.0.2":
|
||||
"@verdaccio/streams@0.0.2", "@verdaccio/streams@^0.0.2":
|
||||
version "0.0.2"
|
||||
resolved "https://registry.npmjs.org/@verdaccio/streams/-/streams-0.0.2.tgz#72cd65449e657b462a1ca094f663cad9ea872427"
|
||||
|
||||
"@verdaccio/types@^0.1.0":
|
||||
"@verdaccio/types@0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.npmjs.org/@verdaccio/types/-/types-0.1.0.tgz#2a0a6066bbbb7841d29298463e761147fb1f7f00"
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue