1
0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-02-21 07:29:37 +01: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

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

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

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

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

6
test/e2e/.eslintrc Normal file

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

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

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

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const nock = require('nock'); const nock = require('nock');
function Plugin(config) { function Plugin(config) {
@ -6,13 +7,14 @@ function Plugin(config) {
return self; 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) { app.get('/test-uplink-timeout-*', function (req, res, next) {
// https://github.com/nock/nock#readme // https://github.com/nock/nock#readme
nock('http://localhost:55552') nock('http://localhost:55552')
.get(req.path) .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) .socketDelay(50000)
// http-status 200 OK // http-status 200 OK
.reply(200); .reply(200);

@ -1,24 +1,36 @@
import express from 'express'; import express from 'express';
import bodyParser from 'body-parser'; 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 { export default class ExpressServer {
app: any; private app: any;
server: any; private server: any;
constructor() { public constructor() {
this.app = express(); this.app = express();
} }
start(port: number): Promise<any> { public start(port: number): Promise<ExpressServer> {
return new Promise((resolve) => { return new Promise((resolve) => {
this.app.use(bodyParser.json()); this.app.use(bodyParser.json());
this.app.use(bodyParser.urlencoded({ this.app.use(bodyParser.urlencoded({
extended: true extended: true
})); }));
this.server = this.app.listen(port, () => { this.server = this.app.listen(port, () => resolve(this));
resolve(this);
});
}); });
} }
} }

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

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

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

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

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

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

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

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

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

@ -7,7 +7,7 @@ export class VerdaccioConfig implements IVerdaccioConfig {
public domainPath: string; public domainPath: string;
public port: number; 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.storagePath = storagePath;
this.configPath = configPath; this.configPath = configPath;
this.domainPath = domainPath; this.domainPath = domainPath;

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

@ -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.

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

@ -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 Config from '../../../../src/lib/config';
import {generatePackageTemplate} from '../../../../src/lib/storage-utils'; import {generatePackageTemplate} from '../../../../src/lib/storage-utils';
import {readFile} from '../../../functional/lib/test.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 { import {
Config as AppConfig, Config as AppConfig,
@ -15,9 +17,10 @@ import {
IBasicAuth, IBasicAuth,
} from '@verdaccio/types'; } from '@verdaccio/types';
import { IUploadTarball, IReadTarball } from '@verdaccio/streams'; import { IUploadTarball, IReadTarball } from '@verdaccio/streams';
import { generateVersion } from "../../../unit/__helper/utils";
export default class ExampleMiddlewarePlugin implements IPluginMiddleware { export default class ExampleMiddlewarePlugin implements IPluginMiddleware<{}> {
register_middlewares(app: any, auth: IBasicAuth, storage: IStorageManager): void { register_middlewares(app: any, auth: IBasicAuth<{}>, storage: IStorageManager<{}>): void {
const remoteUser: RemoteUser = { const remoteUser: RemoteUser = {
groups: [], groups: [],
real_groups: [], real_groups: [],
@ -29,13 +32,12 @@ export default class ExampleMiddlewarePlugin implements IPluginMiddleware {
auth.aesEncrypt(new Buffer('pass')); auth.aesEncrypt(new Buffer('pass'));
// storage // storage
storage.addPackage('name', generatePackageTemplate('test'), () => {}); 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.mergeTags('name', {'latest': '1.0.0'}, () => {});
storage.changePackage('name', readMetadata(), 'revision', () => {}); storage.changePackage('name', readMetadata('metadata'), 'revision', () => {});
storage.removePackage('name', () => {}); storage.removePackage('name', () => {});
storage.mergeTags('name', {'latest': '1.0.0'}, () => {}); storage.mergeTags('name', {'latest': '1.0.0'}, () => {});
storage.removeTarball('name', 'filename', 'revision', () => {}); storage.removeTarball('name', 'filename', 'revision', () => {});
/* eslint no-unused-vars: 0 */
const config1: AppConfig = new Config({ const config1: AppConfig = new Config({
storage: './storage', storage: './storage',
self_path: '/home/sotrage' self_path: '/home/sotrage'
@ -43,8 +45,7 @@ export default class ExampleMiddlewarePlugin implements IPluginMiddleware {
const add: IUploadTarball = storage.addTarball('name', 'filename'); const add: IUploadTarball = storage.addTarball('name', 'filename');
storage.getTarball('name', 'filename'); storage.getTarball('name', 'filename');
const read: IReadTarball = storage.getTarball('name', 'filename'); const read: IReadTarball = storage.getTarball('name', 'filename');
const search: IReadTarball = storage.search('test'); const search: IReadTarball = storage.search('test', {});
/* eslint no-unused-vars: 0 */
} }
} }

@ -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');
}

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

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

@ -1,6 +1,6 @@
import { Package } from "@verdaccio/types"; import { Package } from "@verdaccio/types";
export function generateAttachment(pkgName, version) { export function generateAttachment() {
return { return {
"content_type": "application\/octet-stream", "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=", "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) => { const attachtment = _versions.reduce((cat, version) => {
cat[`${pkgName}-${version}.tgz`] = generateAttachment(pkgName, version); cat[`${pkgName}-${version}.tgz`] = generateAttachment();
return cat; return cat;
}, {}); }, {});
@ -106,7 +106,7 @@ export function generateStarMedatada(pkgName: string, users): any {
} }
} }
export function generatePackageMetadata(pkgName: string, version: string = '1.0.0'): Package { export function generatePackageMetadata(pkgName: string, version = '1.0.0'): Package {
// @ts-ignore // @ts-ignore
return { return {
"_id": pkgName, "_id": pkgName,

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

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

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

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

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

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

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

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

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

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

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

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

@ -4,7 +4,7 @@ import {readFile} from "../../../functional/lib/test.utils";
import {Package} from '@verdaccio/types'; 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('Storage Utils', () => {
describe('normalizePackage', () => { describe('normalizePackage', () => {

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

@ -156,7 +156,7 @@ describe('UpStorge', () => {
describe('valid use cases', () => { describe('valid use cases', () => {
const validateUpLink = ( const validateUpLink = (
url: string, 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 uplinkConf = { url };
const proxy: IProxy = generateProxy(uplinkConf); const proxy: IProxy = generateProxy(uplinkConf);

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

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

@ -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.

@ -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.

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

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

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