1
0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-11-08 23:25:51 +01:00

chore: eslint config module (#2263)

* build: eslint config as package

* chore: fix formatting
This commit is contained in:
Juan Picado 2021-05-16 17:11:08 +02:00 committed by GitHub
parent d2c65da9c7
commit f3f00052d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 924 additions and 674 deletions

102
.eslintrc

@ -1,102 +0,0 @@
{
"extends": [
"eslint:recommended",
"google",
"plugin:react/recommended",
"plugin:jest/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:import/typescript",
"plugin:jsx-a11y/recommended",
"prettier"
],
"plugins": ["import", "jest", "jsx-a11y", "react-hooks"],
"env": {
"es6": true,
"node": true,
"jest": true
},
"globals": {
"__APP_VERSION__": true
},
"parserOptions": {
"allowImportExportEverywhere": true,
"sourceType": "module",
"ecmaVersion": 11,
"ecmaFeatures": {
"impliedStrict": true,
"jsx": true
}
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".jsx", ".ts", ".tsx"]
}
}
},
"parser": "@typescript-eslint/parser",
"rules": {
"curly": ["error", "all"],
"react/prop-types": 0,
"jest/no-export": 0,
"jest/no-test-callback": 0,
"jest/expect-expect": 0,
"jest/no-try-expect": 0,
"jest/no-done-callback": "off",
"jest/no-conditional-expect": "off",
"keyword-spacing": "off",
"no-tabs": "off",
"no-useless-escape": "off",
"padded-blocks": "off",
"require-jsdoc": "off",
"valid-jsdoc": "off",
"import/order": ["error"],
"eol-last": "error",
"no-irregular-whitespace": "error",
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
"no-trailing-spaces": "error",
"camelcase": "off",
"guard-for-in": "error",
"new-cap": "error",
"max-len": ["error", 100],
"no-console": ["error", { "allow": ["warn"] }],
"no-constant-condition": "error",
"no-debugger": "error",
"no-empty": "error",
"no-fallthrough": "error",
"no-invalid-this": "error",
"no-new-require": "error",
"no-undef": "error",
"no-unreachable": "error",
"no-var": "error",
"one-var": "error",
"prefer-rest-params": "error",
"prefer-spread": "error",
"handle-callback-err": 0,
"prefer-const": 0,
"@typescript-eslint/camelcase": 0,
"@typescript-eslint/ban-ts-ignore": 0,
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/no-inferrable-types": 0,
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-this-alias": 0,
"@typescript-eslint/no-use-before-define": 0,
"@typescript-eslint/array-type": ["error"],
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/indent": 0,
"@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/ban-types": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
// rules to fix
"no-unused-vars": ["warn", { "vars": "all", "args": "none" }],
"jest/no-identical-title": ["warn"],
"prefer-promise-reject-errors": ["warn"],
"jest/no-disabled-tests": ["warn"],
"jest/no-commented-out-tests": ["warn"],
"@typescript-eslint/prefer-optional-chain": ["warn"],
"@typescript-eslint/explicit-member-accessibility": ["warn"],
"@typescript-eslint/no-unused-vars": ["warn"]
}
}

3
.eslintrc.js Normal file

@ -0,0 +1,3 @@
module.exports = {
extends: ['@verdaccio/eslint-config'],
};

@ -10,7 +10,7 @@ let _localMemory = require('./local-memory');
let _localMemory2 = _interopRequireDefault(_localMemory); let _localMemory2 = _interopRequireDefault(_localMemory);
function _interopRequireDefault(obj) { function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj }; return obj && obj.__esModule ? obj : {default: obj};
} }
exports.LocalMemory = _localMemory2.default; exports.LocalMemory = _localMemory2.default;

@ -9,7 +9,7 @@ let _memoryHandler = require('./memory-handler');
let _memoryHandler2 = _interopRequireDefault(_memoryHandler); let _memoryHandler2 = _interopRequireDefault(_memoryHandler);
function _interopRequireDefault(obj) { function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj }; return obj && obj.__esModule ? obj : {default: obj};
} }
const DEFAULT_LIMIT = 1000; const DEFAULT_LIMIT = 1000;
@ -43,8 +43,8 @@ class LocalMemory {
cb(null); cb(null);
} else { } else {
this.logger.info( this.logger.info(
{ limit: this.limit }, {limit: this.limit},
'Storage memory has reached limit of @{limit} packages' 'Storage memory has reached limit of @{limit} packages',
); );
cb(new Error('Storage memory has reached limit of limit packages')); cb(new Error('Storage memory has reached limit of limit packages'));
} }

@ -16,7 +16,7 @@ let _memoryFs2 = _interopRequireDefault(_memoryFs);
let _streams = require('@verdaccio/streams'); let _streams = require('@verdaccio/streams');
function _interopRequireDefault(obj) { function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj }; return obj && obj.__esModule ? obj : {default: obj};
} }
// $FlowFixMe // $FlowFixMe
@ -111,8 +111,8 @@ class MemoryHandler {
const uploadStream = new _streams.UploadTarball(); const uploadStream = new _streams.UploadTarball();
const temporalName = `/${name}`; const temporalName = `/${name}`;
process.nextTick(function () { process.nextTick(function() {
fs.exists(temporalName, function (exists) { fs.exists(temporalName, function(exists) {
if (exists) { if (exists) {
return uploadStream.emit('error', fSError(fileExist)); return uploadStream.emit('error', fSError(fileExist));
} }
@ -122,7 +122,7 @@ class MemoryHandler {
uploadStream.pipe(file); uploadStream.pipe(file);
uploadStream.done = function () { uploadStream.done = function() {
const onEnd = function onEnd() { const onEnd = function onEnd() {
uploadStream.emit('success'); uploadStream.emit('success');
}; };
@ -130,7 +130,7 @@ class MemoryHandler {
uploadStream.on('end', onEnd); uploadStream.on('end', onEnd);
}; };
uploadStream.abort = function () { uploadStream.abort = function() {
uploadStream.emit('error', fSError('transmision aborted', 400)); uploadStream.emit('error', fSError('transmision aborted', 400));
file.end(); file.end();
}; };
@ -150,8 +150,8 @@ class MemoryHandler {
const readTarballStream = new _streams.ReadTarball(); const readTarballStream = new _streams.ReadTarball();
process.nextTick(function () { process.nextTick(function() {
fs.exists(pathName, function (exists) { fs.exists(pathName, function(exists) {
if (!exists) { if (!exists) {
readTarballStream.emit('error', noPackageFoundError()); readTarballStream.emit('error', noPackageFoundError());
} else { } else {
@ -164,7 +164,7 @@ class MemoryHandler {
readTarballStream.emit('error', error); readTarballStream.emit('error', error);
}); });
readTarballStream.abort = function () { readTarballStream.abort = function() {
readStream.destroy(fSError('read has been aborted', 400)); readStream.destroy(fSError('read has been aborted', 400));
}; };
} }

@ -39,8 +39,8 @@
"@babel/register": "7.13.14", "@babel/register": "7.13.14",
"@babel/runtime": "7.13.10", "@babel/runtime": "7.13.10",
"@changesets/changelog-github": "^0.2.8", "@changesets/changelog-github": "^0.2.8",
"@changesets/cli": "^2.15.0", "@changesets/cli": "^2.16.0",
"@changesets/get-dependents-graph": "^1.2.0", "@changesets/get-dependents-graph": "^1.2.1",
"@commitlint/cli": "8.3.5", "@commitlint/cli": "8.3.5",
"@commitlint/config-conventional": "8.2.0", "@commitlint/config-conventional": "8.2.0",
"@octokit/rest": "17.0.0", "@octokit/rest": "17.0.0",
@ -71,6 +71,7 @@
"@typescript-eslint/parser": "4.13.0", "@typescript-eslint/parser": "4.13.0",
"@verdaccio/types": "workspace:*", "@verdaccio/types": "workspace:*",
"@verdaccio/ui-theme": "workspace:*", "@verdaccio/ui-theme": "workspace:*",
"@verdaccio/eslint-config": "workspace:*",
"babel-core": "7.0.0-bridge.0", "babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.1.0", "babel-eslint": "10.1.0",
"babel-jest": "26.6.3", "babel-jest": "26.6.3",
@ -78,20 +79,21 @@
"babel-plugin-emotion": "11.0.0", "babel-plugin-emotion": "11.0.0",
"codecov": "3.8.1", "codecov": "3.8.1",
"concurrently": "^5.3.0", "concurrently": "^5.3.0",
"core-js": "^3.10.1", "core-js": "^3.12.1",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"detect-secrets": "1.0.6", "detect-secrets": "1.0.6",
"eslint": "7.19.0", "eslint": "7.26.0",
"eslint-config-google": "0.14.0", "eslint-config-google": "0.14.0",
"eslint-config-prettier": "7.2.0", "eslint-config-prettier": "8.3.0",
"eslint-plugin-babel": "5.3.1", "eslint-plugin-babel": "5.3.1",
"eslint-plugin-import": "2.22.1", "eslint-plugin-import": "2.23.2",
"eslint-plugin-jest": "24.1.3", "eslint-plugin-jest": "24.3.6",
"eslint-plugin-jsx-a11y": "6.4.1", "eslint-plugin-jsx-a11y": "6.4.1",
"eslint-plugin-react": "7.22.0", "eslint-plugin-react": "7.23.2",
"eslint-plugin-react-hooks": "4.2.0", "eslint-plugin-react-hooks": "4.2.0",
"eslint-plugin-simple-import-sort": "7.0.0", "eslint-plugin-simple-import-sort": "7.0.0",
"eslint-plugin-verdaccio": "9.6.1", "eslint-plugin-verdaccio": "10.0.0",
"eslint-plugin-prettier": "3.4.0",
"fs-extra": "9.1.0", "fs-extra": "9.1.0",
"get-stdin": "7.0.0", "get-stdin": "7.0.0",
"husky": "2.7.0", "husky": "2.7.0",
@ -107,14 +109,14 @@
"nock": "12.0.3", "nock": "12.0.3",
"nodemon": "^2.0.7", "nodemon": "^2.0.7",
"npm-run-all": "4.1.5", "npm-run-all": "4.1.5",
"prettier": "2.2.1", "prettier": "2.3.0",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"selfsigned": "1.10.8", "selfsigned": "1.10.8",
"supertest": "4.0.2", "supertest": "4.0.2",
"ts-node": "^9.1.1", "ts-node": "^9.1.1",
"typescript": "^4.2.4", "typescript": "^4.2.4",
"update-ts-references": "2.3.0", "update-ts-references": "2.3.0",
"verdaccio": "^5.0.1", "verdaccio": "^5.0.4",
"verdaccio-audit": "workspace:*", "verdaccio-audit": "workspace:*",
"verdaccio-auth-memory": "workspace:*", "verdaccio-auth-memory": "workspace:*",
"verdaccio-htpasswd": "workspace:*", "verdaccio-htpasswd": "workspace:*",

@ -41,7 +41,7 @@ export default function (route, auth, storage): void {
route.get('/-/v1/search', (req, res) => { route.get('/-/v1/search', (req, res) => {
// TODO: implement proper result scoring weighted by quality, popularity and // TODO: implement proper result scoring weighted by quality, popularity and
// maintenance query parameters // maintenance query parameters
let [text, size, from /* , quality, popularity, maintenance */] = [ let [text, size, from] = [
'text', 'text',
'size', 'size',
'from' /* , 'quality', 'popularity', 'maintenance' */, 'from' /* , 'quality', 'popularity', 'maintenance' */,

@ -5,10 +5,11 @@ import { $ResponseExtend, $RequestExtend } from '../../types/custom';
import { initializeServer, publishTaggedVersion, publishVersion } from './_helper'; import { initializeServer, publishTaggedVersion, publishVersion } from './_helper';
const mockApiJWTmiddleware = jest.fn( const mockApiJWTmiddleware = jest.fn(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { () =>
req.remote_user = { name: 'foo', groups: [], real_groups: [] }; (req: $RequestExtend, res: $ResponseExtend, _next): void => {
_next(); req.remote_user = { name: 'foo', groups: [], real_groups: [] };
} _next();
}
); );
jest.mock('@verdaccio/auth', () => ({ jest.mock('@verdaccio/auth', () => ({

@ -11,10 +11,11 @@ import { $ResponseExtend, $RequestExtend } from '../../types/custom';
import { initializeServer, publishVersion } from './_helper'; import { initializeServer, publishVersion } from './_helper';
const mockApiJWTmiddleware = jest.fn( const mockApiJWTmiddleware = jest.fn(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { () =>
req.remote_user = { name: 'foo', groups: [], real_groups: [] }; (req: $RequestExtend, res: $ResponseExtend, _next): void => {
_next(); req.remote_user = { name: 'foo', groups: [], real_groups: [] };
} _next();
}
); );
jest.setTimeout(50000000); jest.setTimeout(50000000);

@ -16,10 +16,11 @@ import { $RequestExtend, $ResponseExtend } from '../../types/custom';
import { initializeServer } from './_helper'; import { initializeServer } from './_helper';
const mockApiJWTmiddleware = jest.fn( const mockApiJWTmiddleware = jest.fn(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { () =>
req.remote_user = { name: 'test', groups: [], real_groups: [] }; (req: $RequestExtend, res: $ResponseExtend, _next): void => {
_next(); req.remote_user = { name: 'test', groups: [], real_groups: [] };
} _next();
}
); );
const mockAuthenticate = jest.fn(() => (_name, _password, callback): void => { const mockAuthenticate = jest.fn(() => (_name, _password, callback): void => {
@ -53,10 +54,11 @@ describe('user', () => {
test('should test add a new user', async (done) => { test('should test add a new user', async (done) => {
mockApiJWTmiddleware.mockImplementationOnce( mockApiJWTmiddleware.mockImplementationOnce(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { () =>
req.remote_user = { name: undefined }; (req: $RequestExtend, res: $ResponseExtend, _next): void => {
_next(); req.remote_user = { name: undefined };
} _next();
}
); );
mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => { mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => {
@ -85,10 +87,11 @@ describe('user', () => {
test('should test fails on add a existing user with login', async (done) => { test('should test fails on add a existing user with login', async (done) => {
mockApiJWTmiddleware.mockImplementationOnce( mockApiJWTmiddleware.mockImplementationOnce(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { () =>
req.remote_user = { name: undefined }; (req: $RequestExtend, res: $ResponseExtend, _next): void => {
_next(); req.remote_user = { name: undefined };
} _next();
}
); );
supertest(await initializeServer('user.yaml')) supertest(await initializeServer('user.yaml'))
.put('/-/user/org.couchdb.user:jotaNew') .put('/-/user/org.couchdb.user:jotaNew')
@ -124,10 +127,11 @@ describe('user', () => {
test('should test fails add a new user with missing name', async (done) => { test('should test fails add a new user with missing name', async (done) => {
mockApiJWTmiddleware.mockImplementationOnce( mockApiJWTmiddleware.mockImplementationOnce(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { () =>
req.remote_user = { name: undefined }; (req: $RequestExtend, res: $ResponseExtend, _next): void => {
_next(); req.remote_user = { name: undefined };
} _next();
}
); );
mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => { mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => {
return callback(getBadRequest(API_ERROR.USERNAME_PASSWORD_REQUIRED)); return callback(getBadRequest(API_ERROR.USERNAME_PASSWORD_REQUIRED));
@ -153,10 +157,11 @@ describe('user', () => {
test('should test fails add a new user with missing password', async (done) => { test('should test fails add a new user with missing password', async (done) => {
mockApiJWTmiddleware.mockImplementationOnce( mockApiJWTmiddleware.mockImplementationOnce(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { () =>
req.remote_user = { name: undefined }; (req: $RequestExtend, res: $ResponseExtend, _next): void => {
_next(); req.remote_user = { name: undefined };
} _next();
}
); );
const credentialsShort = _.cloneDeep(credentials); const credentialsShort = _.cloneDeep(credentials);
delete credentialsShort.password; delete credentialsShort.password;
@ -181,10 +186,11 @@ describe('user', () => {
test('should test fails add a new user with wrong password', async (done) => { test('should test fails add a new user with wrong password', async (done) => {
mockApiJWTmiddleware.mockImplementationOnce( mockApiJWTmiddleware.mockImplementationOnce(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { () =>
req.remote_user = { name: 'test' }; (req: $RequestExtend, res: $ResponseExtend, _next): void => {
_next(); req.remote_user = { name: 'test' };
} _next();
}
); );
mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => { mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => {
return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD)); return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD));
@ -210,10 +216,11 @@ describe('user', () => {
test('should be able to logout an user', async (done) => { test('should be able to logout an user', async (done) => {
mockApiJWTmiddleware.mockImplementationOnce( mockApiJWTmiddleware.mockImplementationOnce(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { () =>
req.remote_user = { name: 'test' }; (req: $RequestExtend, res: $ResponseExtend, _next): void => {
_next(); req.remote_user = { name: 'test' };
} _next();
}
); );
mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => { mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => {
return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD)); return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD));

@ -6,10 +6,11 @@ import { $RequestExtend, $ResponseExtend } from '../../types/custom';
import { initializeServer } from './_helper'; import { initializeServer } from './_helper';
const mockApiJWTmiddleware = jest.fn( const mockApiJWTmiddleware = jest.fn(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { () =>
req.remote_user = { name: 'foo', groups: [], real_groups: [] }; (req: $RequestExtend, res: $ResponseExtend, _next): void => {
_next(); req.remote_user = { name: 'foo', groups: [], real_groups: [] };
} _next();
}
); );
jest.mock('@verdaccio/auth', () => ({ jest.mock('@verdaccio/auth', () => ({

@ -31,7 +31,7 @@ describe('HTPasswd', () => {
let wrapper; let wrapper;
beforeEach(() => { beforeEach(() => {
wrapper = new HTPasswd(getDefaultConfig(), (stuff as unknown) as VerdaccioConfigApp); wrapper = new HTPasswd(getDefaultConfig(), stuff as unknown as VerdaccioConfigApp);
jest.resetModules(); jest.resetModules();
crypto.randomBytes = jest.fn(() => { crypto.randomBytes = jest.fn(() => {

@ -59,86 +59,84 @@ export function loadPlugin<T extends IPlugin<T>>(
sanityCheck: any, sanityCheck: any,
prefix: string = 'verdaccio' prefix: string = 'verdaccio'
): any[] { ): any[] {
return Object.keys(pluginConfigs).map( return Object.keys(pluginConfigs).map((pluginId: string): IPlugin<T> => {
(pluginId: string): IPlugin<T> => { let plugin;
let plugin;
const localPlugin = Path.resolve(__dirname + '/../plugins', pluginId); const localPlugin = Path.resolve(__dirname + '/../plugins', pluginId);
// try local plugins first // try local plugins first
plugin = tryLoad(localPlugin); plugin = tryLoad(localPlugin);
// try the external plugin directory // try the external plugin directory
if (plugin === null && config.plugins) { if (plugin === null && config.plugins) {
const pluginDir = config.plugins; const pluginDir = config.plugins;
const externalFilePlugin = Path.resolve(pluginDir, pluginId); const externalFilePlugin = Path.resolve(pluginDir, pluginId);
plugin = tryLoad(externalFilePlugin); plugin = tryLoad(externalFilePlugin);
// npm package
if (plugin === null && pluginId.match(/^[^\.\/]/)) {
plugin = tryLoad(Path.resolve(pluginDir, `${prefix}-${pluginId}`));
// compatibility for old sinopia plugins
if (!plugin) {
plugin = tryLoad(Path.resolve(pluginDir, `sinopia-${pluginId}`));
}
}
}
// npm package // npm package
if (plugin === null && pluginId.match(/^[^\.\/]/)) { if (plugin === null && pluginId.match(/^[^\.\/]/)) {
plugin = tryLoad(`${prefix}-${pluginId}`); plugin = tryLoad(Path.resolve(pluginDir, `${prefix}-${pluginId}`));
// compatibility for old sinopia plugins // compatibility for old sinopia plugins
if (!plugin) { if (!plugin) {
plugin = tryLoad(`sinopia-${pluginId}`); plugin = tryLoad(Path.resolve(pluginDir, `sinopia-${pluginId}`));
} }
} }
if (plugin === null) {
plugin = tryLoad(pluginId);
}
// relative to config path
if (plugin === null && pluginId.match(/^\.\.?($|\/)/)) {
plugin = tryLoad(Path.resolve(Path.dirname(config.config_path), pluginId));
}
if (plugin === null) {
logger.error(
{ content: pluginId, prefix },
'plugin not found. try npm install @{prefix}-@{content}'
);
throw Error(`
${prefix}-${pluginId} plugin not found. try "npm install ${prefix}-${pluginId}"`);
}
if (!isValid(plugin)) {
logger.error(
{ content: pluginId },
'@{prefix}-@{content} plugin does not have the right code structure'
);
throw Error(`"${pluginId}" plugin does not have the right code structure`);
}
/* eslint new-cap:off */
try {
plugin = isES6(plugin)
? new plugin.default(mergeConfig(config, pluginConfigs[pluginId]), params)
: plugin(pluginConfigs[pluginId], params);
} catch (error) {
plugin = null;
logger.error({ error, pluginId }, 'error loading a plugin @{pluginId}: @{error}');
}
/* eslint new-cap:off */
if (plugin === null || !sanityCheck(plugin)) {
logger.error(
{ content: pluginId, prefix },
"@{prefix}-@{content} doesn't look like a valid plugin"
);
throw Error(`sanity check has failed, "${pluginId}" is not a valid plugin`);
}
debug('Plugin successfully loaded: %o-%o', pluginId, prefix);
return plugin;
} }
);
// npm package
if (plugin === null && pluginId.match(/^[^\.\/]/)) {
plugin = tryLoad(`${prefix}-${pluginId}`);
// compatibility for old sinopia plugins
if (!plugin) {
plugin = tryLoad(`sinopia-${pluginId}`);
}
}
if (plugin === null) {
plugin = tryLoad(pluginId);
}
// relative to config path
if (plugin === null && pluginId.match(/^\.\.?($|\/)/)) {
plugin = tryLoad(Path.resolve(Path.dirname(config.config_path), pluginId));
}
if (plugin === null) {
logger.error(
{ content: pluginId, prefix },
'plugin not found. try npm install @{prefix}-@{content}'
);
throw Error(`
${prefix}-${pluginId} plugin not found. try "npm install ${prefix}-${pluginId}"`);
}
if (!isValid(plugin)) {
logger.error(
{ content: pluginId },
'@{prefix}-@{content} plugin does not have the right code structure'
);
throw Error(`"${pluginId}" plugin does not have the right code structure`);
}
/* eslint new-cap:off */
try {
plugin = isES6(plugin)
? new plugin.default(mergeConfig(config, pluginConfigs[pluginId]), params)
: plugin(pluginConfigs[pluginId], params);
} catch (error) {
plugin = null;
logger.error({ error, pluginId }, 'error loading a plugin @{pluginId}: @{error}');
}
/* eslint new-cap:off */
if (plugin === null || !sanityCheck(plugin)) {
logger.error(
{ content: pluginId, prefix },
"@{prefix}-@{content} doesn't look like a valid plugin"
);
throw Error(`sanity check has failed, "${pluginId}" is not a valid plugin`);
}
debug('Plugin successfully loaded: %o-%o', pluginId, prefix);
return plugin;
});
} }

@ -51,7 +51,7 @@ class ActiveDirectoryPlugin implements IPluginAuth<ActiveDirectoryConfig> {
connection.getGroupMembershipForUser(username, (err, groups: object[]): void => { connection.getGroupMembershipForUser(username, (err, groups: object[]): void => {
if (err) { if (err) {
this.logger.warn(`AD - Active Directory group check failed with error: ${err}`); this.logger.warn(`AD - Active Directory group check failed with error: ${err}`);
return cb(getInternalError((err as unknown) as string)); return cb(getInternalError(err as unknown as string));
} }
const requestedGroups = Array.isArray(groupName) ? groupName : [groupName]; const requestedGroups = Array.isArray(groupName) ? groupName : [groupName];

@ -83,7 +83,7 @@ describe('Active Directory Plugin', () => {
const errorMessage = 'Unknown error retrieving groups'; const errorMessage = 'Unknown error retrieving groups';
ActiveDirectory.prototype.authenticate = jest.fn((_1, _2, cb) => cb(null, true)); ActiveDirectory.prototype.authenticate = jest.fn((_1, _2, cb) => cb(null, true));
ActiveDirectory.prototype.getGroupMembershipForUser = jest.fn((_, cb) => ActiveDirectory.prototype.getGroupMembershipForUser = jest.fn((_, cb) =>
cb((errorMessage as unknown) as object, null) cb(errorMessage as unknown as object, null)
) as jest.Mock; ) as jest.Mock;
adPluginSingleGroup.authenticate('', '', (error, authUser) => { adPluginSingleGroup.authenticate('', '', (error, authUser) => {

@ -29,14 +29,8 @@ export default class S3PackageManager implements ILocalPackageManager {
this.config = config; this.config = config;
this.packageName = packageName; this.packageName = packageName;
this.logger = logger; this.logger = logger;
const { const { endpoint, region, s3ForcePathStyle, accessKeyId, secretAccessKey, sessionToken } =
endpoint, config;
region,
s3ForcePathStyle,
accessKeyId,
secretAccessKey,
sessionToken,
} = config;
this.s3 = new S3({ this.s3 = new S3({
endpoint, endpoint,

@ -79,7 +79,7 @@ describe.skip('S3 package manager', () => {
describe('savePackage() group', () => { describe('savePackage() group', () => {
test('savePackage()', (done) => { test('savePackage()', (done) => {
const data = ('{data:5}' as unknown) as Package; const data = '{data:5}' as unknown as Package;
const packageManager = new S3PackageManager(config, 'first-package', logger); const packageManager = new S3PackageManager(config, 'first-package', logger);
packageManager.savePackage('pkg.1.0.0.tar.gz', data, (err) => { packageManager.savePackage('pkg.1.0.0.tar.gz', data, (err) => {

@ -118,14 +118,12 @@ class GoogleCloudDatabase implements IPluginStorage<VerdaccioConfigGoogleStorage
// "{\"secret\":\"181bc38698078f880564be1e4d7ec107ac8a3b344a924c6d86cea4a84a885ae0\"}" // "{\"secret\":\"181bc38698078f880564be1e4d7ec107ac8a3b344a924c6d86cea4a84a885ae0\"}"
return entities.secret; return entities.secret;
}) })
.catch( .catch((err: Error): Promise<string> => {
(err: Error): Promise<string> => { const error: VerdaccioError = getInternalError(err.message);
const error: VerdaccioError = getInternalError(err.message);
this.logger.warn({ error }, 'gcloud: [datastore getSecret] init error @{error}'); this.logger.warn({ error }, 'gcloud: [datastore getSecret] init error @{error}');
return Promise.reject(getServiceUnavailable('[getSecret] permissions error')); return Promise.reject(getServiceUnavailable('[getSecret] permissions error'));
} });
);
} }
public setSecret(secret: string): Promise<CommitResponse> { public setSecret(secret: string): Promise<CommitResponse> {
@ -194,17 +192,15 @@ class GoogleCloudDatabase implements IPluginStorage<VerdaccioConfigGoogleStorage
// }; // };
this.helper this.helper
.getEntities(this.kind) .getEntities(this.kind)
.then( .then(async (entities: any): Promise<void> => {
async (entities: any): Promise<void> => { for (const item of entities) {
for (const item of entities) { if (item.name === name) {
if (item.name === name) { await this._deleteItem(name, item);
await this._deleteItem(name, item); // deletedItems.push(deletedItem);
// deletedItems.push(deletedItem);
}
} }
cb(null);
} }
) cb(null);
})
.catch((err: Error): void => { .catch((err: Error): void => {
cb(getInternalError(err.message)); cb(getInternalError(err.message));
}); });

@ -90,16 +90,14 @@ class GoogleCloudStorageHandler implements IPackageStorageManager {
onEnd(getInternalError(err.message)); onEnd(getInternalError(err.message));
} }
) )
.catch( .catch((err: Error): Callback => {
(err: Error): Callback => { this.logger.error(
this.logger.error( { name, error: err },
{ name, error: err }, 'gcloud: trying to update @{name} and was not found on storage err: @{error}'
'gcloud: trying to update @{name} and was not found on storage err: @{error}' );
); // @ts-ignore
// @ts-ignore return onEnd(getNotFound());
return onEnd(getNotFound()); });
}
);
} }
public deletePackage(fileName: string, cb: CallbackAction): void { public deletePackage(fileName: string, cb: CallbackAction): void {
@ -197,28 +195,26 @@ class GoogleCloudStorageHandler implements IPackageStorageManager {
/* eslint-disable no-async-promise-executor */ /* eslint-disable no-async-promise-executor */
private _savePackage(name: string, metadata: Package): Promise<null | VerdaccioError> { private _savePackage(name: string, metadata: Package): Promise<null | VerdaccioError> {
return new Promise( return new Promise(async (resolve, reject): Promise<void> => {
async (resolve, reject): Promise<void> => { const file = this.helper.buildFilePath(name, pkgFileName);
const file = this.helper.buildFilePath(name, pkgFileName); try {
try { await file.save(this._convertToString(metadata), {
await file.save(this._convertToString(metadata), { validation: this.config.validation || defaultValidation,
validation: this.config.validation || defaultValidation, /**
/** * When resumable is `undefined` - it will default to `true`as
* When resumable is `undefined` - it will default to `true`as * per GC Storage documentation:
* per GC Storage documentation: * `Resumable uploads are automatically enabled and must be shut
* `Resumable uploads are automatically enabled and must be shut * off explicitly by setting options.resumable to false`
* off explicitly by setting options.resumable to false` * @see
* @see * https://cloud.google.com/nodejs/docs/reference/storage/2.5.x/File#createWriteStream
* https://cloud.google.com/nodejs/docs/reference/storage/2.5.x/File#createWriteStream */
*/ resumable: this.config.resumable,
resumable: this.config.resumable, });
}); resolve(null);
resolve(null); } catch (err) {
} catch (err) { reject(getInternalError(err.message));
reject(getInternalError(err.message));
}
} }
); });
} }
/* eslint-enable no-async-promise-executor */ /* eslint-enable no-async-promise-executor */
@ -244,48 +240,44 @@ class GoogleCloudStorageHandler implements IPackageStorageManager {
/* eslint-disable no-async-promise-executor */ /* eslint-disable no-async-promise-executor */
private _fileExist(name: string, fileName: string): Promise<boolean> { private _fileExist(name: string, fileName: string): Promise<boolean> {
return new Promise( return new Promise(async (resolve, reject): Promise<void> => {
async (resolve, reject): Promise<void> => { const file: File = this.helper.buildFilePath(name, fileName);
const file: File = this.helper.buildFilePath(name, fileName); try {
try { // @ts-ignore
// @ts-ignore const data = await file.exists();
const data = await file.exists(); const exist = data[0];
const exist = data[0];
resolve(exist); resolve(exist);
this.logger.debug( this.logger.debug(
{ name: name, exist }, { name: name, exist },
'gcloud: check whether @{name} exist successfully: @{exist}' 'gcloud: check whether @{name} exist successfully: @{exist}'
); );
} catch (err) { } catch (err) {
this.logger.error( this.logger.error(
{ name: file.name, err: err.message }, { name: file.name, err: err.message },
'gcloud: check exist package @{name} has failed, cause: @{err}' 'gcloud: check exist package @{name} has failed, cause: @{err}'
); );
reject(getInternalError(err.message)); reject(getInternalError(err.message));
}
} }
); });
} }
private async _readPackage(name: string): Promise<Package> { private async _readPackage(name: string): Promise<Package> {
return new Promise( return new Promise(async (resolve, reject): Promise<void> => {
async (resolve, reject): Promise<void> => { const file = this.helper.buildFilePath(name, pkgFileName);
const file = this.helper.buildFilePath(name, pkgFileName);
try { try {
const content: DownloadResponse = await file.download(); const content: DownloadResponse = await file.download();
this.logger.debug({ name: this.name }, 'gcloud: @{name} was found on storage'); this.logger.debug({ name: this.name }, 'gcloud: @{name} was found on storage');
const response: Package = JSON.parse(content[0].toString('utf8')); const response: Package = JSON.parse(content[0].toString('utf8'));
resolve(response); resolve(response);
} catch (err) { } catch (err) {
this.logger.debug({ name: this.name }, 'gcloud: @{name} package not found on storage'); this.logger.debug({ name: this.name }, 'gcloud: @{name} package not found on storage');
reject(getNotFound()); reject(getNotFound());
}
} }
); });
} }
/* eslint-disable no-async-promise-executor */ /* eslint-disable no-async-promise-executor */

@ -21,8 +21,13 @@ export interface FilterOptionsState<Option> {
} }
function createFilterOptions(config?: CreateFilterOptionsConfig) { function createFilterOptions(config?: CreateFilterOptionsConfig) {
const { ignoreAccents = true, ignoreCase = true, trim = false, limit, matchFrom = 'any' } = const {
config || {}; ignoreAccents = true,
ignoreCase = true,
trim = false,
limit,
matchFrom = 'any',
} = config || {};
return <Option extends {}>( return <Option extends {}>(
options: Option[], options: Option[],

@ -6,9 +6,10 @@ import { Theme } from './theme';
const resetStyles = makeStyles(({ theme }: { theme?: Theme }) => ({ const resetStyles = makeStyles(({ theme }: { theme?: Theme }) => ({
'@global': { '@global': {
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
'html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video': { 'html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video':
fontFamily: '"Roboto", Helvetica Neue, Arial, sans-serif', {
}, fontFamily: '"Roboto", Helvetica Neue, Arial, sans-serif',
},
strong: { strong: {
fontWeight: theme && theme.fontWeight.semiBold, fontWeight: theme && theme.fontWeight.semiBold,
}, },

@ -22,18 +22,8 @@ const cache = new CellMeasurerCache({
/* eslint-disable verdaccio/jsx-no-style */ /* eslint-disable verdaccio/jsx-no-style */
const PackageList: React.FC<Props> = ({ packages }) => { const PackageList: React.FC<Props> = ({ packages }) => {
const renderRow = ({ index, key, parent, style }: ListRowProps) => { const renderRow = ({ index, key, parent, style }: ListRowProps) => {
const { const { name, version, description, time, keywords, dist, homepage, bugs, author, license } =
name, packages[index];
version,
description,
time,
keywords,
dist,
homepage,
bugs,
author,
license,
} = packages[index];
// TODO: move format license to API side. // TODO: move format license to API side.
const formattedLicense = formatLicense(license); const formattedLicense = formatLicense(license);

@ -1,24 +1,24 @@
import { SyntheticEvent } from 'react'; import { SyntheticEvent } from 'react';
export const copyToClipBoardUtility = (str: string): ((e: SyntheticEvent<HTMLElement>) => void) => ( export const copyToClipBoardUtility =
event: SyntheticEvent<HTMLElement> (str: string): ((e: SyntheticEvent<HTMLElement>) => void) =>
): void => { (event: SyntheticEvent<HTMLElement>): void => {
event.preventDefault(); event.preventDefault();
const node = document.createElement('div'); const node = document.createElement('div');
node.innerText = str; node.innerText = str;
if (document.body) { if (document.body) {
document.body.appendChild(node); document.body.appendChild(node);
const range = document.createRange(); const range = document.createRange();
const selection = window.getSelection() as Selection; const selection = window.getSelection() as Selection;
range.selectNodeContents(node); range.selectNodeContents(node);
selection.removeAllRanges(); selection.removeAllRanges();
selection.addRange(range); selection.addRange(range);
document.execCommand('copy'); document.execCommand('copy');
document.body.removeChild(node); document.body.removeChild(node);
} }
}; };
export function getCLISetConfigRegistry( export function getCLISetConfigRegistry(
command: string, command: string,

@ -41,8 +41,7 @@ const json = {
_attachments: { _attachments: {
'forbidden-place-1.0.6.tgz': { 'forbidden-place-1.0.6.tgz': {
content_type: 'application/octet-stream', content_type: 'application/octet-stream',
data: 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=',
'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=',
length: 512, length: 512,
}, },
}, },

@ -41,8 +41,7 @@ const json = {
_attachments: { _attachments: {
'@scope/pk1-test-1.0.6.tgz': { '@scope/pk1-test-1.0.6.tgz': {
content_type: 'application/octet-stream', content_type: 'application/octet-stream',
data: 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=',
'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=',
length: 512, length: 512,
}, },
}, },

@ -0,0 +1,20 @@
{
"name": "@verdaccio/eslint-config",
"version": "1.0.0",
"private": "true",
"description": "verdaccio eslint config",
"main": "src/index.js",
"scripts": {
"lint": "eslint . --ext .js"
},
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com"
},
"repository": {
"type": "https",
"url": "https://github.com/verdaccio/verdaccio"
},
"homepage": "https://verdaccio.org",
"license": "MIT"
}

@ -0,0 +1,27 @@
module.exports = {
extends: ['./rules/base.js', './rules/prettier.js', './rules/react.js', './rules/jest.js'],
env: {
es6: true,
node: true,
},
globals: {
__APP_VERSION__: true,
},
parserOptions: {
allowImportExportEverywhere: true,
sourceType: 'module',
ecmaVersion: 11,
ecmaFeatures: {
impliedStrict: true,
jsx: true,
},
},
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
},
parser: '@typescript-eslint/parser',
};

@ -0,0 +1,64 @@
module.exports = {
extends: [
'eslint:recommended',
'google',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:import/typescript',
],
plugins: ['import'],
rules: {
curly: ['error', 'all'],
'keyword-spacing': 'off',
'no-tabs': 'off',
'no-useless-escape': 'off',
'padded-blocks': 'off',
'require-jsdoc': 'off',
'valid-jsdoc': 'off',
'import/order': ['error'],
'eol-last': 'error',
'no-irregular-whitespace': 'error',
'no-mixed-spaces-and-tabs': ['error', 'smart-tabs'],
'no-trailing-spaces': 'error',
camelcase: 'off',
'guard-for-in': 'error',
'new-cap': 'error',
'max-len': ['error', 100],
'no-console': ['error', { allow: ['warn'] }],
'no-constant-condition': 'error',
'no-debugger': 'error',
'no-empty': 'error',
'no-fallthrough': 'error',
'no-invalid-this': 'error',
'no-new-require': 'error',
'no-undef': 'error',
'no-unreachable': 'error',
'no-var': 'error',
'one-var': 'error',
'prefer-rest-params': 'error',
'prefer-spread': 'error',
'handle-callback-err': 0,
'prefer-const': 0,
// typescript
'@typescript-eslint/camelcase': 0,
'@typescript-eslint/ban-ts-ignore': 0,
'@typescript-eslint/no-var-requires': 0,
'@typescript-eslint/no-inferrable-types': 0,
'@typescript-eslint/no-empty-function': 0,
'@typescript-eslint/no-this-alias': 0,
'@typescript-eslint/no-use-before-define': 0,
'@typescript-eslint/array-type': ['error'],
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/indent': 0,
'@typescript-eslint/ban-ts-comment': 0,
'@typescript-eslint/ban-types': 0,
'@typescript-eslint/explicit-module-boundary-types': 0,
// rules to fix
'no-unused-vars': ['warn', { vars: 'all', args: 'none' }],
'prefer-promise-reject-errors': ['warn'],
'@typescript-eslint/prefer-optional-chain': ['warn'],
'@typescript-eslint/explicit-member-accessibility': ['warn'],
'@typescript-eslint/no-unused-vars': ['warn'],
},
};

@ -0,0 +1,19 @@
module.exports = {
extends: ['plugin:jest/recommended'],
plugins: ['jest'],
env: {
jest: true,
},
rules: {
'jest/no-export': 0,
'jest/no-test-callback': 0,
'jest/expect-expect': 0,
'jest/no-try-expect': 0,
'jest/no-done-callback': 'off',
'jest/no-conditional-expect': 'off',
// rules to fix
'jest/no-identical-title': ['warn'],
'jest/no-disabled-tests': ['warn'],
'jest/no-commented-out-tests': ['warn'],
},
};

@ -0,0 +1,4 @@
module.exports = {
extends: ['plugin:prettier/recommended'],
plugins: ['prettier'],
};

@ -0,0 +1,15 @@
module.exports = {
extends: [
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
'plugin:jsx-a11y/recommended',
],
plugins: ['import'],
env: {
browser: true,
},
rules: {
'react/prop-types': 0,
},
};

@ -41,8 +41,7 @@ const json = {
_attachments: { _attachments: {
'forbidden-place-1.0.6.tgz': { 'forbidden-place-1.0.6.tgz': {
content_type: 'application/octet-stream', content_type: 'application/octet-stream',
data: 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=',
'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=',
length: 512, length: 512,
}, },
}, },

@ -15,25 +15,21 @@ function addUserAuthApi(route: Router, auth: IAuth, config: Config): void {
route.post('/login', function (req: Request, res: Response, next: $NextFunctionVer): void { route.post('/login', function (req: Request, res: Response, next: $NextFunctionVer): void {
const { username, password } = req.body; const { username, password } = req.body;
debug('authenticate %o', username); debug('authenticate %o', username);
auth.authenticate( auth.authenticate(username, password, async (err, user: RemoteUser): Promise<void> => {
username, if (err) {
password, const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR;
async (err, user: RemoteUser): Promise<void> => { debug('error authenticate %o', errorCode);
if (err) { next(ErrorCode.getCode(errorCode, err.message));
const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR; } else {
debug('error authenticate %o', errorCode); req.remote_user = user;
next(ErrorCode.getCode(errorCode, err.message)); const jWTSignOptions: JWTSignOptions = config.security.web.sign;
} else {
req.remote_user = user;
const jWTSignOptions: JWTSignOptions = config.security.web.sign;
next({ next({
token: await auth.jwtEncrypt(user, jWTSignOptions), token: await auth.jwtEncrypt(user, jWTSignOptions),
username: req.remote_user.name, username: req.remote_user.name,
}); });
}
} }
); });
}); });
if (config?.flags?.changePassword === true) { if (config?.flags?.changePassword === true) {

@ -45,21 +45,19 @@ export function addGravatarSupport(pkgInfo: Package, online = true): AuthorAvata
// for contributors // for contributors
if (_.isEmpty(contributors) === false) { if (_.isEmpty(contributors) === false) {
pkgInfoCopy.latest.contributors = contributors.map( pkgInfoCopy.latest.contributors = contributors.map((contributor): AuthorAvatar => {
(contributor): AuthorAvatar => { if (isObject(contributor)) {
if (isObject(contributor)) { contributor.avatar = generateGravatarUrl(contributor.email, online);
contributor.avatar = generateGravatarUrl(contributor.email, online); } else if (_.isString(contributor)) {
} else if (_.isString(contributor)) { contributor = {
contributor = { avatar: GENERIC_AVATAR,
avatar: GENERIC_AVATAR, email: contributor,
email: contributor, name: contributor,
name: contributor, };
};
}
return contributor;
} }
);
return contributor;
});
} }
// for maintainers // for maintainers

760
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,7 @@
packages: packages:
- packages/* - packages/*
- packages/core/* - packages/core/*
- packages/tools/*
- packages/plugins/* - packages/plugins/*
- website - website
- test/e2e-* - test/e2e-*

@ -41,8 +41,7 @@ const json = {
_attachments: { _attachments: {
'protected-pkg-5.0.5.tgz': { 'protected-pkg-5.0.5.tgz': {
content_type: 'application/octet-stream', content_type: 'application/octet-stream',
data: 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=',
'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=',
length: 512, length: 512,
}, },
}, },

@ -41,8 +41,7 @@ const json = {
_attachments: { _attachments: {
'@scope/pk1-test-1.0.6.tgz': { '@scope/pk1-test-1.0.6.tgz': {
content_type: 'application/octet-stream', content_type: 'application/octet-stream',
data: 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=',
'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=',
length: 512, length: 512,
}, },
}, },