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

chore: fix eslint warnings (#1471)

This commit is contained in:
Juan Picado @jotadeveloper 2019-09-26 18:22:14 +02:00 committed by GitHub
parent 9006aefea7
commit 5612c13e9e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 402 additions and 151 deletions

View file

@ -14,7 +14,7 @@ import { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandl
import { logger } from '../../../lib/logger';
import {isPublishablePackage} from "../../../lib/storage-utils";
export default function publish(router: Router, auth: IAuth, storage: IStorageHandler, config: Config) {
export default function publish(router: Router, auth: IAuth, storage: IStorageHandler, config: Config): void {
const can = allow(auth);
/**
@ -101,9 +101,9 @@ export default function publish(router: Router, auth: IAuth, storage: IStorageHa
/**
* Publish a package
*/
export function publishPackage(storage: IStorageHandler, config: Config, auth: IAuth) {
export function publishPackage(storage: IStorageHandler, config: Config, auth: IAuth): any {
const starApi = star(storage);
return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const packageName = req.params.package;
logger.debug({packageName} , `publishing or updating a new version for @{packageName}`);
@ -111,7 +111,7 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I
/**
* Write tarball of stream data from package clients.
*/
const createTarball = function(filename: string, data, cb: Callback) {
const createTarball = function(filename: string, data, cb: Callback): void {
const stream = storage.addTarball(packageName, filename);
stream.on('error', function(err) {
cb(err);
@ -128,18 +128,18 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I
/**
* Add new package version in storage
*/
const createVersion = function(version: string, metadata: Version, cb: Callback) {
const createVersion = function(version: string, metadata: Version, cb: Callback): void {
storage.addVersion(packageName, version, metadata, null, cb);
};
/**
* Add new tags in storage
*/
const addTags = function(tags: MergeTags, cb: Callback) {
const addTags = function(tags: MergeTags, cb: Callback): void {
storage.mergeTags(packageName, tags, cb);
};
const afterChange = function(error, okMessage, metadata) {
const afterChange = function(error, okMessage, metadata): void {
const metadataCopy: Package = { ...metadata };
const { _attachments, versions } = metadataCopy;
@ -218,7 +218,7 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I
logger.debug({packageName} , `updating a new version for @{packageName}`);
// we check unpublish permissions, an update is basically remove versions
const remote = req.remote_user;
auth.allow_unpublish({packageName}, remote, (error, allowed) => {
auth.allow_unpublish({packageName}, remote, (error) => {
if (error) {
logger.debug({packageName} , `not allowed to unpublish a version for @{packageName}`);
return next(error);
@ -245,7 +245,7 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I
* un-publish a package
*/
export function unPublishPackage(storage: IStorageHandler) {
return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const packageName = req.params.package;
logger.debug({packageName} , `unpublishing @{packageName}`);
@ -263,7 +263,7 @@ export function unPublishPackage(storage: IStorageHandler) {
* Delete tarball
*/
export function removeTarball(storage: IStorageHandler) {
return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const packageName = req.params.package;
const {filename, revision} = req.params;
@ -283,7 +283,7 @@ export function removeTarball(storage: IStorageHandler) {
* Adds a new version
*/
export function addVersion(storage: IStorageHandler) {
return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const { version, tag } = req.params;
const packageName = req.params.package;

View file

@ -1,8 +1,3 @@
/**
* @prettier
* @flow
*/
import fs from 'fs';
import _ from 'lodash';
import Path from 'path';
@ -16,18 +11,24 @@ const CONFIG_FILE = 'config.yaml';
const XDG = 'xdg';
const WIN = 'win';
const WIN32 = 'win32';
// eslint-disable-next-line
const pkgJSON = require('../../package.json');
export type SetupDirectory = {
path: string;
type: string
};
/**
* Find and get the first config file that match.
* @return {String} the config file path
*/
function findConfigFile(configPath: any) {
function findConfigFile(configPath: string): string {
if (_.isNil(configPath) === false) {
return Path.resolve(configPath);
}
const configPaths = getConfigPaths();
const configPaths: SetupDirectory[] = getConfigPaths();
if (_.isEmpty(configPaths)) {
throw new Error('no configuration files can be processed');
@ -41,7 +42,7 @@ function findConfigFile(configPath: any) {
return createConfigFile(_.head(configPaths)).path;
}
function createConfigFile(configLocation: any) {
function createConfigFile(configLocation: any): SetupDirectory {
createConfigFolder(configLocation);
const defaultConfig = updateStorageLinks(configLocation, readDefaultConfig());
@ -51,16 +52,16 @@ function createConfigFile(configLocation: any) {
return configLocation;
}
function readDefaultConfig() {
function readDefaultConfig(): string {
return fs.readFileSync(require.resolve('../../conf/default.yaml'), CHARACTER_ENCODING.UTF8);
}
function createConfigFolder(configLocation) {
function createConfigFolder(configLocation): void {
mkdirp.sync(Path.dirname(configLocation.path));
logger.info({ file: configLocation.path }, 'Creating default config file in @{file}');
}
function updateStorageLinks(configLocation, defaultConfig) {
function updateStorageLinks(configLocation, defaultConfig): string {
if (configLocation.type !== XDG) {
return defaultConfig;
}
@ -77,13 +78,19 @@ function updateStorageLinks(configLocation, defaultConfig) {
}
}
function getConfigPaths() {
return [getXDGDirectory(), getWindowsDirectory(), getRelativeDefaultDirectory(), getOldDirectory()].filter(
path => !!path
);
function getConfigPaths(): SetupDirectory[] {
const listPaths: SetupDirectory[] = [getXDGDirectory(), getWindowsDirectory(), getRelativeDefaultDirectory(), getOldDirectory()].reduce(
function(acc, currentValue: any): SetupDirectory[] {
if (_.isUndefined(currentValue) === false) {
acc.push(currentValue);
}
return acc;
}, [] as SetupDirectory[]);
return listPaths;
}
const getXDGDirectory = () => {
const getXDGDirectory = (): SetupDirectory | void => {
const XDGConfig = getXDGHome() || (process.env.HOME && Path.join(process.env.HOME, '.config'));
if (XDGConfig && folderExists(XDGConfig)) {
@ -94,9 +101,9 @@ const getXDGDirectory = () => {
}
};
const getXDGHome = () => process.env.XDG_CONFIG_HOME;
const getXDGHome = (): string | void => process.env.XDG_CONFIG_HOME;
const getWindowsDirectory = () => {
const getWindowsDirectory = (): SetupDirectory | void => {
if (process.platform === WIN32 && process.env.APPDATA && folderExists(process.env.APPDATA)) {
return {
path: Path.resolve(Path.join(process.env.APPDATA, pkgJSON.name, CONFIG_FILE)),
@ -105,14 +112,14 @@ const getWindowsDirectory = () => {
}
};
const getRelativeDefaultDirectory = () => {
const getRelativeDefaultDirectory = (): SetupDirectory => {
return {
path: Path.resolve(Path.join('.', pkgJSON.name, CONFIG_FILE)),
type: 'def',
};
};
const getOldDirectory = () => {
const getOldDirectory = (): SetupDirectory => {
return {
path: Path.resolve(Path.join('.', CONFIG_FILE)),
type: 'old',

View file

@ -1,4 +1,4 @@
import { createDecipher, createCipher, createHash, pseudoRandomBytes } from 'crypto';
import { createDecipher, createCipher, createHash, pseudoRandomBytes, Hash } from 'crypto';
import jwt from 'jsonwebtoken';
import { JWTSignOptions, RemoteUser } from '@verdaccio/types';
@ -16,7 +16,7 @@ export function aesEncrypt(buf: Buffer, secret: string): Buffer {
return Buffer.concat([b1, b2]);
}
export function aesDecrypt(buf: Buffer, secret: string) {
export function aesDecrypt(buf: Buffer, secret: string): Buffer {
try {
// deprecated (it will be migrated in Verdaccio 5), it is a breaking change
// https://nodejs.org/api/crypto.html#crypto_crypto_createdecipher_algorithm_password_options
@ -30,7 +30,7 @@ export function aesDecrypt(buf: Buffer, secret: string) {
}
}
export function createTarballHash() {
export function createTarballHash(): Hash {
return createHash(defaultTarballHashAlgorithm);
}
@ -47,12 +47,12 @@ export function stringToMD5(data: Buffer | string): string {
.digest('hex');
}
export function generateRandomHexString(length: number = 8) {
export function generateRandomHexString(length = 8): string {
return pseudoRandomBytes(length).toString('hex');
}
export async function signPayload(payload: RemoteUser, secretOrPrivateKey: string, options: JWTSignOptions): Promise<string> {
return new Promise(function(resolve, reject) {
return new Promise(function(resolve, reject): Promise<string> {
return jwt.sign(
payload,
secretOrPrivateKey,
@ -65,6 +65,6 @@ export async function signPayload(payload: RemoteUser, secretOrPrivateKey: strin
});
}
export function verifyPayload(token: string, secretOrPrivateKey: string) {
export function verifyPayload(token: string, secretOrPrivateKey: string): RemoteUser {
return jwt.verify(token, secretOrPrivateKey);
}

View file

@ -38,8 +38,11 @@ import {
} from '@verdaccio/commons-api';
import { IncomingHttpHeaders } from 'http2';
const Logger = require('./logger');
const pkginfo = require('pkginfo')(module); // eslint-disable-line no-unused-vars
import { logger } from './logger';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('pkginfo')(module);
const pkgVersion = module.exports.version;
const pkgName = module.exports.name;
@ -287,7 +290,7 @@ export function semverSort(listVersions: string[]): string[] {
listVersions
.filter(function(x): boolean {
if (!semver.parse(x, true)) {
Logger.logger.warn({ ver: x }, 'ignoring bad version @{ver}');
logger.warn({ ver: x }, 'ignoring bad version @{ver}');
return false;
}
return true;
@ -525,7 +528,7 @@ export function parseReadme(packageName: string, readme: string): string | void
}
// logs readme not found error
Logger.logger.error({ packageName }, '@{packageName}: No readme found');
logger.error({ packageName }, '@{packageName}: No readme found');
return sanitizyReadme('ERROR: No README data found!');
}
@ -606,15 +609,15 @@ export function pad(str, max): string {
* @param {Number} charNum
* @returns {String}
*/
export function mask(str: string, charNum = 3) {
export function mask(str: string, charNum = 3): string {
return `${str.substr(0, charNum)}...${str.substr(-charNum)}`;
}
export function encodeScopedUri(packageName) {
export function encodeScopedUri(packageName): string {
return packageName.replace(/\//g, '%2f');
}
export function hasDiffOneKey(versions) {
export function hasDiffOneKey(versions): boolean {
return Object.keys(versions).length !== 1;
}

6
test/e2e/.eslintrc Normal file
View file

@ -0,0 +1,6 @@
{
"rules": {
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/explicit-member-accessibility": 0
}
}

View file

@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/explicit-member-accessibility */
/**
* Original plugin in ES6
*
@ -34,9 +36,10 @@ class PluginES6 {
constructor(config, stuff) {
this._config = config;
this._logger = stuff.logger;
}
register_middlewares(app, auth, storage) {
register_middlewares(app, /* auth, storage */) {
const message = this._config.message;

View file

@ -1,11 +1,12 @@
function Plugin(config, stuff) {
function Plugin(config, pluginOptions) {
const self = Object.create(Plugin.prototype);
self._config = config;
self._logger = pluginOptions.logger;
return self;
}
Plugin.prototype.register_middlewares = function (app, auth, storage) {
Plugin.prototype.register_middlewares = function (app) {
const {message} = this._config;
app.get('/test/route', function (req, res, next) {
@ -13,7 +14,6 @@ Plugin.prototype.register_middlewares = function (app, auth, storage) {
return next({ ok: message })
});
}
};
module.exports = Plugin;

View file

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const nock = require('nock');
function Plugin(config) {
@ -6,13 +7,14 @@ function Plugin(config) {
return self;
}
Plugin.prototype.register_middlewares = function (app, auth, storage) {
Plugin.prototype.register_middlewares = function (app) {
app.get('/test-uplink-timeout-*', function (req, res, next) {
// https://github.com/nock/nock#readme
nock('http://localhost:55552')
.get(req.path)
// 31s is greater than the default 30s connection timeout
// note: we use 50s due hardware reasons small threshold is not enough to make fails
// 50s is greater than the default 30s connection timeout
.socketDelay(50000)
// http-status 200 OK
.reply(200);

View file

@ -1,24 +1,36 @@
import express from 'express';
import bodyParser from 'body-parser';
/**
* Simple Server
*
* A emtpy express server with the objetive to emumate any external API.
*
* eg: test/functional/tags/tags.ts
*
* express.get('/testexp_tags', function(req, res) {
let f = readTags().toString().replace(/__NAME__/g, 'testexp_tags');
res.send(JSON.parse(f));
});
*
* or at test/functional/package/gzip.ts
*/
export default class ExpressServer {
app: any;
server: any;
private app: any;
private server: any;
constructor() {
public constructor() {
this.app = express();
}
start(port: number): Promise<any> {
public start(port: number): Promise<ExpressServer> {
return new Promise((resolve) => {
this.app.use(bodyParser.json());
this.app.use(bodyParser.urlencoded({
extended: true
}));
this.server = this.app.listen(port, () => {
resolve(this);
});
this.server = this.app.listen(port, () => resolve(this));
});
}
}

View file

@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-var-requires */
require('@babel/register')({
extensions: [".ts", ".js"]
});

View file

@ -1,5 +1,8 @@
import {DEFAULT_NO_README, HTTP_STATUS} from '../../../src/lib/constants';
import pkgReadmeJSON from './pkg-readme.json';
import pkgNoReadmeJSON from './pkg-no-readme.json';
export default function (server, server2) {
describe('should test readme', () => {
@ -8,9 +11,9 @@ export default function (server, server2) {
const README_MESSAGE = 'this is a readme';
beforeAll(async function() {
await server.putPackage('readme-test', require('./pkg-readme.json'))
await server.putPackage('readme-test', pkgReadmeJSON)
.status(HTTP_STATUS.CREATED);
await server.putPackage(README_PKG2, require('./pkg-no-readme.json'))
await server.putPackage(README_PKG2, pkgNoReadmeJSON)
.status(HTTP_STATUS.CREATED);
});

View file

@ -1,6 +1,5 @@
import {API_MESSAGE, HTTP_STATUS} from '../../../src/lib/constants';
const pkgExample = require('./search.json');
import pkgExample from './search.json';
export default function(server, server2, express) {

View file

@ -2,9 +2,7 @@ import {generateSha} from '../lib/test.utils';
import {API_MESSAGE, HTTP_STATUS} from '../../../src/lib/constants';
import {DOMAIN_SERVERS, PORT_SERVER_1, PORT_SERVER_2, PORT_SERVER_3} from '../config.functional';
import {DIST_TAGS} from '../../../src/lib/constants';
const pkgExample = require('./dist-tags-merge.json');
import pkgExample from './dist-tags-merge.json';
export default function(server, server2, server3) {

View file

@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-var-requires */
require('@babel/register')({
extensions: [".ts", ".js"]
});

View file

@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-var-requires */
require('@babel/register')({
sourceMap: 'inline',
});

View file

@ -148,19 +148,20 @@ export default class Server implements IServerBridge {
}).send(JSON.stringify(version));
}
public putTarballIncomplete(name: string, filename: string, data: any, size: number, cb: Function): Promise<any> {
public putTarballIncomplete(pkgName: string, filename: string, data: any, headerContentSize: number): Promise<any> {
let promise = this.request({
uri: `/${encodeURIComponent(name)}/-/${encodeURIComponent(filename)}/whatever`,
uri: `/${encodeURIComponent(pkgName)}/-/${encodeURIComponent(filename)}/whatever`,
method: 'PUT',
headers: {
[HEADERS.CONTENT_TYPE]: HEADERS.OCTET_STREAM,
[HEADERS.CONTENT_LENGTH]: size,
[HEADERS.CONTENT_LENGTH]: headerContentSize,
},
timeout: 1000,
});
promise.request(function(req) {
req.write(data);
// it auto abort the request
setTimeout(function() {
req.req.abort();
}, 20);

View file

@ -8,18 +8,18 @@ import {IVerdaccioConfig, IServerBridge, IServerProcess} from '../types';
export default class VerdaccioProcess implements IServerProcess {
bridge: IServerBridge;
config: IVerdaccioConfig;
childFork: any;
isDebug: boolean;
silence: boolean;
cleanStore: boolean;
private bridge: IServerBridge;
private config: IVerdaccioConfig;
private childFork: any;
private isDebug: boolean;
private silence: boolean;
private cleanStore: boolean;
public constructor(config: IVerdaccioConfig,
bridge: IServerBridge,
silence: boolean = true,
isDebug: boolean = false,
cleanStore: boolean = true) {
silence = true,
isDebug = false,
cleanStore = true) {
this.config = config;
this.bridge = bridge;
this.silence = silence;
@ -27,7 +27,7 @@ export default class VerdaccioProcess implements IServerProcess {
this.cleanStore = cleanStore;
}
public init(verdaccioPath: string = '../../bin/verdaccio'): Promise<any> {
public init(verdaccioPath = '../../bin/verdaccio'): Promise<any> {
return new Promise((resolve, reject) => {
if(this.cleanStore) {
rimRaf(this.config.storagePath, (err) => {

View file

@ -3,7 +3,7 @@ import { Version } from "@verdaccio/types";
export function generateNewVersion(
pkgName: string,
version: string,
shashum: string = '238e7641e59508dc9c20eb4ad37a8aa57ab777b4'): Version {
shashum = '238e7641e59508dc9c20eb4ad37a8aa57ab777b4'): Version {
// $FlowFixMe
return {
"name": pkgName,

View file

@ -7,7 +7,7 @@ export class VerdaccioConfig implements IVerdaccioConfig {
public domainPath: string;
public port: number;
constructor(storagePath: string, configPath: string, domainPath: string, port: number) {
public constructor(storagePath: string, configPath: string, domainPath: string, port: number) {
this.storagePath = storagePath;
this.configPath = configPath;
this.domainPath = domainPath;

View file

@ -0,0 +1,5 @@
{
"rules": {
"@typescript-eslint/explicit-member-accessibility": 0
}
}

View file

@ -0,0 +1,7 @@
# Types smoke test
This folder is intended to check whether any type update might break plugin implementations
## Contribute
- Add more scenarios, middleware, plugins, filters etc.

View file

@ -1,42 +1,37 @@
/**
* @prettier
*/
// @flow
// this file is not aim to be tested, just to check flow definitions
import Config from '../../../../src/lib/config';
import LoggerApi from '../../../../src/lib/logger';
import { logger } from '../../../../src/lib/logger';
import { Callback } from '@verdaccio/types';
import { Config as AppConfig, PackageAccess, IPluginAuth, RemoteUser, Logger, PluginOptions } from '@verdaccio/types';
class ExampleAuthPlugin implements IPluginAuth {
class ExampleAuthPlugin implements IPluginAuth<{}> {
config: AppConfig;
logger: Logger;
constructor(config: AppConfig, options: PluginOptions) {
constructor(config: AppConfig, options: PluginOptions<{}>) {
this.config = config;
this.logger = options.logger;
}
adduser(user: string, password: string, cb: verdaccio$Callback): void {
adduser(user: string, password: string, cb: Callback): void {
cb();
}
changePassword(username, password, newPassword, cb: verdaccio$Callback): void {
changePassword(username, password, newPassword, cb: Callback): void {
cb();
}
authenticate(user: string, password: string, cb: verdaccio$Callback): void {
authenticate(user: string, password: string, cb: Callback): void {
cb();
}
allow_access(user: RemoteUser, pkg: PackageAccess, cb: verdaccio$Callback): void {
allow_access(user: RemoteUser, pkg: PackageAccess, cb: Callback): void {
cb();
}
allow_publish(user: RemoteUser, pkg: PackageAccess, cb: verdaccio$Callback): void {
allow_publish(user: RemoteUser, pkg: PackageAccess, cb: Callback): void {
cb();
}
}
@ -45,32 +40,32 @@ type SubTypePackageAccess = PackageAccess & {
sub?: boolean;
};
class ExampleAuthCustomPlugin implements IPluginAuth {
class ExampleAuthCustomPlugin implements IPluginAuth<{}> {
config: AppConfig;
logger: Logger;
constructor(config: AppConfig, options: PluginOptions) {
constructor(config: AppConfig, options: PluginOptions<{}>) {
this.config = config;
this.logger = options.logger;
}
adduser(user: string, password: string, cb: verdaccio$Callback): void {
adduser(user: string, password: string, cb: Callback): void {
cb();
}
changePassword(username, password, newPassword, cb: verdaccio$Callback): void {
changePassword(username, password, newPassword, cb: Callback): void {
cb();
}
authenticate(user: string, password: string, cb: verdaccio$Callback): void {
authenticate(user: string, password: string, cb: Callback): void {
cb();
}
allow_access(user: RemoteUser, pkg: SubTypePackageAccess, cb: verdaccio$Callback): void {
allow_access(user: RemoteUser, pkg: SubTypePackageAccess, cb: Callback): void {
cb();
}
allow_publish(user: RemoteUser, pkg: SubTypePackageAccess, cb: verdaccio$Callback): void {
allow_publish(user: RemoteUser, pkg: SubTypePackageAccess, cb: Callback): void {
cb();
}
}
@ -80,9 +75,9 @@ const config1: AppConfig = new Config({
self_path: '/home/sotrage',
});
const options: PluginOptions = {
const options: PluginOptions<{}> = {
config: config1,
logger: LoggerApi.logger.child(),
logger: logger.child(),
};
const auth = new ExampleAuthPlugin(config1, options);

View file

@ -1,11 +1,13 @@
// @flow
// this file is not aim to be tested, just to check typescript definitions
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-unused-vars */
// this file is not aim to be tested, just to check flow definitions
import Config from '../../../../src/lib/config';
import {generatePackageTemplate} from '../../../../src/lib/storage-utils';
import {readFile} from '../../../functional/lib/test.utils';
import { Package } from '@verdaccio/types';
const readMetadata = (fileName: string = 'metadata') => readFile(`../../unit/partials/${fileName}`);
const readMetadata = (fileName: string): Package => JSON.parse(readFile(`../../unit/partials/${fileName}`).toString()) as Package;
import {
Config as AppConfig,
@ -15,9 +17,10 @@ import {
IBasicAuth,
} from '@verdaccio/types';
import { IUploadTarball, IReadTarball } from '@verdaccio/streams';
import { generateVersion } from "../../../unit/__helper/utils";
export default class ExampleMiddlewarePlugin implements IPluginMiddleware {
register_middlewares(app: any, auth: IBasicAuth, storage: IStorageManager): void {
export default class ExampleMiddlewarePlugin implements IPluginMiddleware<{}> {
register_middlewares(app: any, auth: IBasicAuth<{}>, storage: IStorageManager<{}>): void {
const remoteUser: RemoteUser = {
groups: [],
real_groups: [],
@ -29,13 +32,12 @@ export default class ExampleMiddlewarePlugin implements IPluginMiddleware {
auth.aesEncrypt(new Buffer('pass'));
// storage
storage.addPackage('name', generatePackageTemplate('test'), () => {});
storage.addVersion('name', 'version', readMetadata(), 'tag', () => {});
storage.addVersion('name', 'version', generateVersion('name', '1.0.0'), 'tag', () => {});
storage.mergeTags('name', {'latest': '1.0.0'}, () => {});
storage.changePackage('name', readMetadata(), 'revision', () => {});
storage.changePackage('name', readMetadata('metadata'), 'revision', () => {});
storage.removePackage('name', () => {});
storage.mergeTags('name', {'latest': '1.0.0'}, () => {});
storage.removeTarball('name', 'filename', 'revision', () => {});
/* eslint no-unused-vars: 0 */
const config1: AppConfig = new Config({
storage: './storage',
self_path: '/home/sotrage'
@ -43,8 +45,7 @@ export default class ExampleMiddlewarePlugin implements IPluginMiddleware {
const add: IUploadTarball = storage.addTarball('name', 'filename');
storage.getTarball('name', 'filename');
const read: IReadTarball = storage.getTarball('name', 'filename');
const search: IReadTarball = storage.search('test');
/* eslint no-unused-vars: 0 */
const search: IReadTarball = storage.search('test', {});
}
}

View file

@ -0,0 +1,171 @@
// this file is not aim to be tested, just to check typescript definitions
import {
Callback,
Config as AppConfig,
Logger,
Package,
Token,
TokenFilter,
IUploadTarball, IReadTarball
} from '@verdaccio/types';
import {
IPluginStorage,
IPackageStorageManager,
IPackageStorage
} from '@verdaccio/types';
import { UploadTarball, ReadTarball} from '@verdaccio/streams';
import Config from '../../../../src/lib/config';
import {logger} from '../../../../src/lib/logger';
import {generatePackageTemplate} from '../../../../src/lib/storage-utils';
class PackageStorage implements IPackageStorageManager {
path: string;
logger: Logger;
constructor(path: string, logger: Logger) {
this.path = path;
this.logger = logger;
}
updatePackage(name: string, updateHandler: Callback,
onWrite: Callback,
transformPackage: Function,
onEnd: Callback) {
onEnd();
}
deletePackage(fileName: string, callback: Callback) {
callback();
}
removePackage(callback: Callback): void {
callback();
}
createPackage(name: string, value: Package, cb: Callback) {
cb();
}
savePackage(name: string, value: Package, cb: Callback) {
cb();
}
readPackage(name: string, cb: Callback) {
cb();
}
writeTarball(name): IUploadTarball {
this.logger.debug({name}, 'some name @name');
const uploadStream = new UploadTarball({});
uploadStream.on('close', () => {});
if (uploadStream.abort) {
uploadStream.abort();
}
if (uploadStream.done) {
uploadStream.done();
}
return uploadStream;
}
readTarball(name): IReadTarball {
this.logger.debug({name}, 'some name @name');
const readTarballStream: IReadTarball = new ReadTarball({});
if (readTarballStream.abort) {
readTarballStream.abort();
}
return readTarballStream;
}
}
class ExampleStoragePlugin implements IPluginStorage<{}> {
logger: Logger;
config: AppConfig;
constructor(config: AppConfig, logger: Logger) {
this.config = config;
this.logger = logger;
}
saveToken(token: Token): Promise<any> {
return Promise.resolve(token)
}
deleteToken(user: string, tokenKey: string): Promise<any>{
return Promise.resolve([user, tokenKey]);
}
readTokens(filter: TokenFilter): Promise<Token[]> {
const token: Token = {
user: filter.user,
key: '12312',
token: '12321',
readonly: false,
created: '123232'
}
return Promise.resolve([token, token]);
}
getSecret(): Promise<any> {
return Promise.resolve();
}
setSecret(secret: string): Promise<any> {
return Promise.resolve(secret);
}
add(name: string, cb: Callback) {
cb();
}
remove(name: string, cb: Callback) {
cb();
}
get(cb: Callback) {
cb();
}
getPackageStorage(packageInfo: string): IPackageStorage {
return new PackageStorage(packageInfo, this.logger);
}
search(onPackage: Callback, onEnd: Callback, validateName: any): void {
onPackage(onEnd(validateName()));
}
}
export default ExampleStoragePlugin;
const config1: AppConfig = new Config({
storage: './storage',
self_path: '/home/sotrage'
});
const storage = new ExampleStoragePlugin(config1, logger.child());
storage.add('test', () => {});
storage.remove('test', () => {});
storage.getSecret().then(() => {});
storage.setSecret('newSecret').then(() => {});
storage.search(() => {}, () => {}, 'validateName');
storage.get(() => {});
const storageManager: IPackageStorage = storage.getPackageStorage('test');
if (storageManager) {
storageManager.createPackage('test', generatePackageTemplate('test'), () => {});
storageManager.savePackage('fileName', generatePackageTemplate('test'), () => {});
storageManager.updatePackage('pkgFileName', () =>{}, () => {}, () => {}, () => {});
storageManager.deletePackage('test', () => {});
storageManager.removePackage(() => {});
storageManager.readPackage('test', () => {});
storageManager.writeTarball('test');
}

View file

@ -15,11 +15,6 @@ export interface IRequestPromise {
}
export interface IServerProcess {
bridge: IServerBridge;
config: IVerdaccioConfig;
childFork: any;
isDebug: boolean;
silence: boolean;
init(): Promise<any>;
stop(): void;
}

View file

@ -19,8 +19,7 @@ export function putPackage(
request: any,
pkgName: string,
publishMetadata: Package,
token?: string,
httpStatus: number = HTTP_STATUS.CREATED): Promise<any[]> {
token?: string): Promise<any[]> {
return new Promise((resolve) => {
let put = request.put(pkgName)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)

View file

@ -1,6 +1,6 @@
import { Package } from "@verdaccio/types";
export function generateAttachment(pkgName, version) {
export function generateAttachment() {
return {
"content_type": "application\/octet-stream",
"data": "H4sIAAAAAAAAE+2W32vbMBDH85y\/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo\/\/79KPeQsnIw5KUDX\/9IOvurLuz\/DHSjK\/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1aW8eML+Vv10m9oF\/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0ScCdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI\/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yoEHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS\/pLQe+D+FIv\/agIWI6GX66kFuIhT+1gDjrp\/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0\/jWiAK8OcMjt8MW3OlfQppcuhhQ6k+2OgkK2Q8DssFPi\/IHpU9fz3\/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6\/f88f\/Pu47zomiPk2Lv\/dOv8h+P\/34\/D\/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=",
@ -54,7 +54,7 @@ export function generatePackageBody(pkgName: string, _versions: string[] = ['1.0
}, {});
const attachtment = _versions.reduce((cat, version) => {
cat[`${pkgName}-${version}.tgz`] = generateAttachment(pkgName, version);
cat[`${pkgName}-${version}.tgz`] = generateAttachment();
return cat;
}, {});
@ -106,8 +106,8 @@ export function generateStarMedatada(pkgName: string, users): any {
}
}
export function generatePackageMetadata(pkgName: string, version: string = '1.0.0'): Package {
// @ts-ignore
export function generatePackageMetadata(pkgName: string, version = '1.0.0'): Package {
// @ts-ignore
return {
"_id": pkgName,
"name": pkgName,

View file

@ -101,7 +101,7 @@ describe('api with no limited access configuration', () => {
.set(HEADERS.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HEADERS.CONTENT_TYPE, /json/)
.expect(HTTP_STATUS.OK)
.end(function(err, res) {
.end(function(err) {
if (err) {
return done(err);
}

View file

@ -405,7 +405,7 @@ describe('endpoint unit test', () => {
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.NOT_FOUND)
.end(function(err, res) {
.end(function(err) {
if (err) {
return done(err);
}
@ -437,7 +437,7 @@ describe('endpoint unit test', () => {
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.NOT_FOUND)
.end(function(err, res) {
.end(function(err) {
if (err) {
return done(err);
}
@ -716,7 +716,7 @@ describe('endpoint unit test', () => {
}
const deletePayload = generatePackageUnpublish(pkgName, ['2.0.0']);
const [err2, res2] = await putPackage(request(app), generateUnPublishURI(pkgName), deletePayload, token, HTTP_STATUS.FORBIDDEN);
const [err2, res2] = await putPackage(request(app), generateUnPublishURI(pkgName), deletePayload, token);
expect(err2).not.toBeNull();
expect(res2.body.error).toMatch(/user jota_unpublish_fail is not allowed to unpublish package non-unpublish/);

View file

@ -1,9 +1,10 @@
class FilterPlugin {
constructor(config) {
private _config;
public constructor(config) {
this._config = config;
}
filter_metadata(pkg) {
public filter_metadata(pkg) {
return new Promise((resolve, reject) => {
// We use this to test what happens when a filter rejects
if(pkg.name === 'trigger-filter-failure') {

View file

@ -270,7 +270,7 @@ describe('Publish endpoints - publish package', () => {
test('should star a package', () => {
const storage = {
changePackage: jest.fn(),
getPackage({ name, req, callback }) {
getPackage({ callback }) {
callback(null, {
users: {},
});

View file

@ -162,7 +162,7 @@ describe('endpoint unit test', () => {
.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token))
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK)
.end(function(err, resp) {
.end(function(err) {
if (err) {
return done(err);
}

View file

@ -6,8 +6,7 @@ import config from '../../partials/config';
import {DEFAULT_DOMAIN, DEFAULT_PORT, DEFAULT_PROTOCOL} from '../../../../src/lib/constants';
import {getListListenAddresses} from '../../../../src/lib/cli/utils';
import {parseConfigFile} from '../../../../src/lib/utils';
const logger = require('../../../../src/lib/logger');
import { logger } from '../../../../src/lib/logger';
jest.mock('../../../../src/lib/logger', () => ({
setup: jest.fn(),
@ -132,8 +131,8 @@ describe('startServer via API', () => {
// @ts-ignore
global.process = { ...realProcess, exit: exitMock };
await startServer(conf, address, store, version, serverName, () => {
expect(logger.logger.fatal).toHaveBeenCalled();
expect(logger.logger.fatal).toHaveBeenCalledTimes(2);
expect(logger.fatal).toHaveBeenCalled();
expect(logger.fatal).toHaveBeenCalledTimes(2);
done();
});
expect(exitMock).toHaveBeenCalledWith(2);

View file

@ -1,4 +1,5 @@
import { HTTP_STATUS, API_ERROR } from '../../../../src/lib/constants';
/* eslint-disable @typescript-eslint/no-var-requires */
/**
* Mocks Logger Service

View file

@ -0,0 +1,5 @@
{
"rules": {
"@typescript-eslint/no-empty-function": 0
}
}

View file

@ -1,6 +1,7 @@
function ValidVerdaccioPlugin() {
return {
// not valid method
// eslint-disable-next-line @typescript-eslint/no-empty-function
authenticate__: function(){}
}
}

View file

@ -1,3 +1,5 @@
// this is how a Babel.js transpiled plugin looks like
"use strict";
Object.defineProperty(exports, "__esModule", {
@ -19,10 +21,10 @@ var Dummy = function () {
_createClass(Dummy, [{
key: "getPackageStorage",
value: function getPackageStorage(packageInfo, packagePath) {}
value: function getPackageStorage() {}
}]);
return Dummy;
}();
exports.default = Dummy;
exports.default = Dummy;

View file

@ -1,4 +1,5 @@
'use strict';
/* eslint-disable @typescript-eslint/no-var-requires */
Object.defineProperty(exports, "__esModule", {
value: true

View file

@ -10,7 +10,7 @@ import {readFile} from '../../../functional/lib/test.utils';
import {generatePackageTemplate} from '../../../../src/lib/storage-utils';
import {generateNewVersion} from '../../../lib/utils-test';
const readMetadata = (fileName: string = 'metadata') => readFile(`../../unit/partials/${fileName}`).toString();
const readMetadata = (fileName = 'metadata') => readFile(`../../unit/partials/${fileName}`).toString();
import {Config, MergeTags, Package} from '@verdaccio/types';
import {IStorage} from '../../../../types';
@ -216,7 +216,7 @@ describe('LocalStorage', () => {
await addPackageToStore(pkgName, generatePackageTemplate(pkgName));
await addNewVersion(pkgName, version);
storage.addVersion(pkgName, version, generateNewVersion(pkgName, version), '', (err, data) => {
storage.addVersion(pkgName, version, generateNewVersion(pkgName, version), '', err => {
expect(err).not.toBeNull();
expect(err.statusCode).toEqual(HTTP_STATUS.CONFLICT);
expect(err.message).toMatch(API_ERROR.PACKAGE_EXIST);
@ -231,7 +231,7 @@ describe('LocalStorage', () => {
const tarballName = `${pkgName}-${version}.tgz`;
await addTarballToStore(pkgName, tarballName);
storage.addVersion(pkgName, version, generateNewVersion(pkgName, version, 'fake'), '', (err, data) => {
storage.addVersion(pkgName, version, generateNewVersion(pkgName, version, 'fake'), '', err => {
expect(err).not.toBeNull();
expect(err.statusCode).toEqual(HTTP_STATUS.BAD_REQUEST);
expect(err.message).toMatch(/shasum error/);
@ -503,7 +503,7 @@ describe('LocalStorage', () => {
test('should fails with package not found', (done) => {
const pkgName = 'npm_test_fake';
storage.removePackage(pkgName, (err, data) => {
storage.removePackage(pkgName, err => {
expect(err).not.toBeNull();
expect(err.message).toMatch(/no such package available/);
done();
@ -511,7 +511,7 @@ describe('LocalStorage', () => {
});
test('should fails with @scoped package not found', (done) => {
storage.removePackage(pkgNameScoped, (err, data) => {
storage.removePackage(pkgNameScoped, err => {
expect(err).not.toBeNull();
expect(err.message).toMatch(API_ERROR.NO_PACKAGE);
done();

View file

@ -4,7 +4,7 @@ import {readFile} from "../../../functional/lib/test.utils";
import {Package} from '@verdaccio/types';
const readMetadata = (fileName: string = 'metadata') => readFile(`../../unit/partials/${fileName}`);
const readMetadata = (fileName = 'metadata') => readFile(`../../unit/partials/${fileName}`);
describe('Storage Utils', () => {
describe('normalizePackage', () => {

View file

@ -60,7 +60,7 @@ describe('StorageTest', () => {
const storage: IStorageHandler = await generateStorage();
// @ts-ignore
storage._syncUplinksMetadata('jquery', null, {}, (err, metadata, errors) => {
storage._syncUplinksMetadata('jquery', null, {}, (err, metadata) => {
expect(err).toBeNull();
expect(metadata).toBeDefined();
expect(metadata).toBeInstanceOf(Object);

View file

@ -156,7 +156,7 @@ describe('UpStorge', () => {
describe('valid use cases', () => {
const validateUpLink = (
url: string,
tarBallUrl: string = `${url}/artifactory/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz`) => {
tarBallUrl = `${url}/artifactory/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz`) => {
const uplinkConf = { url };
const proxy: IProxy = generateProxy(uplinkConf);

View file

@ -20,7 +20,7 @@ import { DIST_TAGS, DEFAULT_USER } from '../../../../src/lib/constants';
import { logger, setup } from '../../../../src/lib/logger';
import { readFile } from '../../../functional/lib/test.utils';
const readmeFile = (fileName: string = 'markdown.md') =>
const readmeFile = (fileName = 'markdown.md') =>
readFile(`../../unit/partials/readme/${fileName}`);
setup([]);

View file

@ -1,12 +1,15 @@
import _ from 'lodash';
import path from 'path';
import {parseConfigFile} from '../../../../src/lib/utils';
/**
* Override the default.yaml configuration file with any new config provided.
*/
export default (options, url = 'default.yaml') => {
const locationFile = path.join(__dirname, `../config/yaml/${url}`);
const config = parseConfigFile(locationFile);
return _.assign({}, _.cloneDeep(config), options);
}

View file

@ -0,0 +1,7 @@
# JSON Configurations
This folder host all sort of JSON configurations for testing. **It should not include many scenarios, since we use `yaml` for testing. JSON files on this folder aims to verify a verdaccio JSON config file works properly.
## Contribute
- Don't add new scenarios unless is discussed with the core team.

View file

@ -0,0 +1,16 @@
# Yaml Configurations
This folder host all sort of configurations for testing. We use `yaml` instead json configuration files for different reasons, maintenability, avoid polute with non use data and contributors can easily understand them.
The files on this folder should be small as possible, **there is a custom config file for all tests (`default.yaml`)** and the following configuration aims to override those part are need it for the test.
## Contribute
- Each topic ideally should have his **own folder** if many scenarios might be part of the test. **eg: profile, security**
- Include different scenarios inside of the folder with enough context to indenty the use case.
- Foder or file, should be **named** as the test that used them. *eg: `api.spec.yaml` -> `api.spec.ts`*
- **Don't use the same config file in multiple test**, it increase maintenance complexity.
- Try to **include only the props are require for the test**:
- Comment the config files, don't be shy, add as much context you think is need it for future contributors.
> Note: Some configurations might be not aligned with this rules, but in the future all files should be follow them for consistency.

View file

@ -7,6 +7,7 @@ security:
jwt:
sign:
expiresIn: 5m
# to avoid invalid verification token, more info on JWT page
notBefore: 0
packages:
'@token/*':
@ -18,5 +19,5 @@ packages:
logs:
- { type: stdout, format: pretty, level: trace }
experiments:
## Enable token for testing
## enable token for testing
token: true

View file

@ -6,6 +6,7 @@
"noImplicitAny": false,
"strict": true,
"strictNullChecks": true,
"resolveJsonModule": true,
"outDir": "lib",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,

View file

@ -187,7 +187,7 @@ export interface IStorageHandler extends IStorageManager<Config>, ITokenActions
init(config: Config, filters: IPluginFilters): Promise<string>;
saveToken(token: Token): Promise<any>;
deleteToken(user: string, tokenKey: string): Promise<any>;
readTokens(filter: TokenFilter): Promise<Array<Token>>;
readTokens(filter: TokenFilter): Promise<Token[]>;
_syncUplinksMetadata(name: string, packageInfo: Package, options: any, callback: Callback): void;
_updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy): void;
}