refactor: config file using flow

This commit is contained in:
Juan Picado @jotadeveloper 2018-07-02 08:24:45 +02:00
parent 3917b19976
commit dd3a937ac9
No known key found for this signature in database
GPG Key ID: 18AC54485952D158
11 changed files with 116 additions and 68 deletions

View File

@ -52,7 +52,7 @@
"devDependencies": {
"@commitlint/cli": "6.1.3",
"@commitlint/config-conventional": "6.1.3",
"@verdaccio/types": "3.0.0",
"@verdaccio/types": "3.0.1",
"babel-cli": "6.26.0",
"babel-core": "6.26.0",
"babel-eslint": "8.2.2",

View File

@ -15,13 +15,13 @@ import type {$ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler,
import type {Config as IConfig} from '@verdaccio/types';
import {ErrorCode} from '../lib/utils';
import {API_ERROR, HTTP_STATUS} from '../lib/constants';
import AppConfig from '../lib/config';
const LoggerApp = require('../lib/logger');
const Config = require('../lib/config');
const Middleware = require('./middleware');
const Cats = require('../lib/status-cats');
const defineAPI = function(config: Config, storage: IStorageHandler) {
const defineAPI = function(config: IConfig, storage: IStorageHandler) {
const auth: IAuth = new Auth(config);
const app: $Application = express();
// run in production mode by default, just in case
@ -103,7 +103,7 @@ const defineAPI = function(config: Config, storage: IStorageHandler) {
export default async function(configHash: any) {
LoggerApp.setup(configHash.logs);
const config: IConfig = new Config(configHash);
const config: IConfig = new AppConfig(configHash);
const storage: IStorageHandler = new Storage(config);
// waits until init calls have been intialized
await storage.init(config);

View File

@ -9,6 +9,7 @@ import type {Config, Logger, Callback} from '@verdaccio/types';
import type {$Response, NextFunction} from 'express';
import type {$RequestExtend, JWTPayload} from '../../types';
import {API_ERROR, ROLES} from './constants';
import {getMatchedPackagesSpec} from './config-utils';
const LoggerApi = require('./logger');
@ -146,7 +147,7 @@ class Auth {
allow_access(packageName: string, user: string, callback: Callback) {
let plugins = this.plugins.slice(0);
// $FlowFixMe
let pkg = Object.assign({name: packageName}, this.config.getMatchedPackagesSpec(packageName));
let pkg = Object.assign({name: packageName}, getMatchedPackagesSpec(packageName, this.config.packages));
(function next() {
const plugin = plugins.shift();
@ -175,7 +176,7 @@ class Auth {
allow_publish(packageName: string, user: string, callback: Callback) {
let plugins = this.plugins.slice(0);
// $FlowFixMe
let pkg = Object.assign({name: packageName}, this.config.getMatchedPackagesSpec(packageName));
let pkg = Object.assign({name: packageName}, getMatchedPackagesSpec(packageName, this.config.packages));
(function next() {
const plugin = plugins.shift();

View File

@ -64,9 +64,12 @@ export function getListListenAddresses(argListen: string, configListen: mixed) {
* @param {String} pkgVersion
* @param {String} pkgName
*/
function startVerdaccio(config: any, cliListen: string,
configPath: string, pkgVersion: string,
pkgName: string, callback: Callback) {
function startVerdaccio(config: any,
cliListen: string,
configPath: string,
pkgVersion: string,
pkgName: string,
callback: Callback) {
if (isObject(config) === false) {
throw new Error('config file must be an object');
}

View File

@ -1,10 +1,12 @@
// @flow
import _ from 'lodash';
import minimatch from 'minimatch';
import assert from 'assert';
import minimatch from 'minimatch';
import {ErrorCode} from './utils';
import type {PackageList} from '@verdaccio/types';
import type {MatchedPackage} from '../../types';
const BLACKLIST = {
all: true,
anonymous: true,
@ -38,17 +40,6 @@ export function normalizeUserlist(oldFormat: any, newFormat: any) {
return _.flatten(result);
}
export function getMatchedPackagesSpec(packages: any, pkg: any) {
for (let i in packages) {
// $FlowFixMe
if (minimatch.makeRe(i).exec(pkg)) {
return packages[i];
}
}
return {};
}
export function uplinkSanityCheck(uplinks: any, users: any = BLACKLIST) {
const newUplinks = _.clone(uplinks);
let newUsers = _.clone(users);
@ -88,8 +79,36 @@ export function sanityCheckUplinksProps(configUpLinks: any) {
return uplinks;
}
export function normalisePackageAccess(packages: any): any {
const normalizedPkgs: any = {...packages};
/**
* Check whether an uplink can proxy
*/
export function hasProxyTo(pkg: string, upLink: string, packages: PackageList): boolean {
const matchedPkg: MatchedPackage = (getMatchedPackagesSpec(pkg, packages): MatchedPackage);
const proxyList = typeof matchedPkg !== 'undefined' ? matchedPkg.proxy : [];
if (proxyList) {
return proxyList.reduce((prev, curr) => {
if (upLink === curr) {
return true;
}
return prev;
}, false);
}
return false;
}
export function getMatchedPackagesSpec(pkg: string, packages: PackageList): MatchedPackage {
for (let i in packages) {
// $FlowFixMe
if (minimatch.makeRe(i).exec(pkg)) {
return packages[i];
}
}
return;
}
export function normalisePackageAccess(packages: PackageList): PackageList {
const normalizedPkgs: PackageList = {...packages};
// add a default rule for all packages to make writing plugins easier
if (_.isNil(normalizedPkgs['**'])) {
normalizedPkgs['**'] = {};

View File

@ -1,12 +1,25 @@
// @flow
import _ from 'lodash';
import assert from 'assert';
import minimatch from 'minimatch';
import {generateRandomHexString} from './crypto-utils';
import {normalisePackageAccess, sanityCheckUplinksProps, uplinkSanityCheck} from './config-utils';
import {
getMatchedPackagesSpec,
normalisePackageAccess,
sanityCheckUplinksProps,
uplinkSanityCheck} from './config-utils';
import {getUserAgent, isObject} from './utils';
import {APP_ERROR} from './constants';
import type {
PackageList,
Config as AppConfig,
Logger,
} from '@verdaccio/types';
import type {MatchedPackage, StartUpConfig} from '../../types';
const LoggerApi = require('./logger');
const strategicConfigProps = ['uplinks', 'packages'];
const allowedEnvConfig = ['http_proxy', 'https_proxy', 'no_proxy'];
@ -14,10 +27,24 @@ const allowedEnvConfig = ['http_proxy', 'https_proxy', 'no_proxy'];
/**
* Coordinates the application configuration
*/
class Config {
constructor(config) {
class Config implements AppConfig {
logger: Logger;
user_agent: string;
secret: string;
uplinks: any;
packages: PackageList;
users: any;
server_id: string;
self_path: string;
storage: string | void;
$key: any;
$value: any;
constructor(config: StartUpConfig) {
const self = this;
this.logger = LoggerApi.logger;
this.self_path = config.self_path;
this.storage = config.storage;
for (let configProp in config) {
if (self[configProp] == null) {
@ -44,7 +71,7 @@ class Config {
this.uplinks = sanityCheckUplinksProps(uplinkSanityCheck(this.uplinks));
if (_.isNil(this.users) === false) {
this.logger.warn(`[users]: property on configuration file
this.logger.warn(`[users]: property on configuration file
is not longer supported, property being ignored`);
}
@ -63,42 +90,18 @@ class Config {
}
}
/**
* Check whether an uplink can proxy
* @param {String} pkg package anem
* @param {*} upLink
* @return {Boolean}
*/
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 {String} pkg package name
* @return {Object}
*/
getMatchedPackagesSpec(pkg) {
for (let i in this.packages) {
if (minimatch.makeRe(i).exec(pkg)) {
return this.packages[i];
}
}
return {};
getMatchedPackagesSpec(pkg: string): MatchedPackage {
return getMatchedPackagesSpec(pkg, this.packages);
}
/**
* Store or create whether recieve a secret key
* @param {String} secret
* @return {String}
*/
checkSecretKey(secret) {
if (_.isString(secret) && secret !== '') {
checkSecretKey(secret: string): string {
if (_.isString(secret) && _.isEmpty(secret) === false) {
this.secret = secret;
return secret;
}
@ -109,4 +112,4 @@ class Config {
}
}
module.exports = Config;
export default Config;

View File

@ -26,6 +26,7 @@ Callback,
Logger,
} from '@verdaccio/types';
import type {IReadTarball, IUploadTarball} from '@verdaccio/streams';
import {hasProxyTo} from './config-utils';
const LoggerApi = require('../lib/logger');
@ -412,9 +413,9 @@ class Storage implements IStorageHandler {
packageInfo = generatePackageTemplate(name);
}
for (let up in this.uplinks) {
if (this.config.hasProxyTo(name, up)) {
upLinks.push(this.uplinks[up]);
for (let uplink in this.uplinks) {
if (hasProxyTo(name, uplink, this.config.packages)) {
upLinks.push(this.uplinks[uplink]);
}
}

View File

@ -11,7 +11,7 @@ describe('Config Utilities', () => {
return path.join(__dirname, `../partials/config/yaml/${name}.yaml`);
};
describe('getMatchedPackagesSpec', () => {
describe('normalisePackageAccess', () => {
test('should test basic conversion', ()=> {
const {packages} = parseConfigFile(parsePartial('pkgs-basic'));
const access = normalisePackageAccess(packages);
@ -58,8 +58,14 @@ describe('Config Utilities', () => {
const react = access['react-*'];
expect(react).toBeDefined();
expect(react.access).toBeDefined();
// $FlowFixMe
expect(react.access[0]).toBe(ROLES.$ALL);
expect(react.publish).toBeDefined();
// $FlowFixMe);
expect(react.publish[0]).toBe('admin');
expect(react.proxy).toBeDefined();
// $FlowFixMe
expect(react.proxy[0]).toBe('uplink2');
expect(react.storage).toBeDefined();

View File

@ -1,10 +1,10 @@
import assert from 'assert';
import Search from '../../../src/lib/search';
import Config from '../../../src/lib/config';
import Storage from '../../../src/lib/storage';
let config_hash = require('../partials/config/index');
let Config = require('../../../src/lib/config');
require('../../../src/lib/logger').setup([]);

View File

@ -8,6 +8,7 @@ import type {
MergeTags,
Config,
Logger,
PackageAccess,
Package} from '@verdaccio/types';
import type {
IUploadTarball,
@ -95,6 +96,20 @@ export interface IStorageHandler {
_updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy): void;
}
// export interface ConfigHandler {
// checkSecretKey(token: string): string;
// hasProxyTo(pkg: string, upLink: string): boolean;
// getMatchedPackagesSpec(storage: string): verdaccio$PackageAccess | void;
// [key: string]: number;
// }
export type StartUpConfig = {
storage: string;
self_path: string;
}
export type MatchedPackage = PackageAccess | void;
export interface IStorage {
config: Config;
localData: ILocalData;

View File

@ -234,9 +234,9 @@
version "1.0.0"
resolved "https://registry.npmjs.org/@verdaccio/streams/-/streams-1.0.0.tgz#d5d24c6747208728b9fd16b908e3932c3fb1f864"
"@verdaccio/types@3.0.0":
version "3.0.0"
resolved "https://registry.npmjs.org/@verdaccio/types/-/types-3.0.0.tgz#1f5ad5c959955b320181ac9968dd894f209985bc"
"@verdaccio/types@3.0.1":
version "3.0.1"
resolved "https://registry.npmjs.org/@verdaccio/types/-/types-3.0.1.tgz#8cdfd74a8a070ad797a056652f257f9ead3717f9"
"@webassemblyjs/ast@1.5.9":
version "1.5.9"