Compare commits

..

12 Commits

Author SHA1 Message Date
github-actions[bot]
1ef60915e6 chore: update versions (6-next) (#2245)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2021-05-24 09:01:22 +02:00
Juan Picado
55ee3fdd97 [Fastify] Add ping endpoint (#2246)
* chore: add ping endpoint

* Update package.json

* rebase from master

* add debug code and logger

* Update index.ts

* Create heavy-ravens-lay.md

* endpoint as plugin

* chore: format

* Update packages/core/server/debug/index.ts

Co-authored-by: Manuel Spigolon <behemoth89@gmail.com>

* add logger instance to fastify

* 4873 port

* format file

* add logger

Co-authored-by: Manuel Spigolon <behemoth89@gmail.com>
2021-05-22 06:56:37 +02:00
Juan Picado
4ebf18816a chore: restore changesets version 2021-05-16 19:03:39 +02:00
Juan Picado
276a0a63a7 chore: set max eslint warnings
this will avoid increase number of warnings, only reduce this number along the warnings are being fixed
2021-05-16 17:26:26 +02:00
Juan Picado
f3f00052d8 chore: eslint config module (#2263)
* build: eslint config as package

* chore: fix formatting
2021-05-16 17:11:08 +02:00
Leonardo Metzger
d2c65da9c7 fix: Fix the name validation of a package tarball (#2242)
Co-authored-by: Juan Picado <juanpicado19@gmail.com>
2021-05-15 16:58:06 +02:00
Juan Picado
2924ffa235 chore: remove website (#2244) 2021-05-13 08:38:18 +02:00
Leonardo Metzger
6b1a28deb8 fix: Fix the prefix used to delete from s3 when unpublishing packages (#2243) 2021-05-12 20:15:18 +02:00
Juan Picado
a54c18c02a additional tests for config pkg (#2237)
* add test config

* add test for home creation

* more checks

* add test

* skip peer platform

* lint

* fix windows
2021-05-09 00:44:07 +02:00
Juan Picado
52b47868e3 add more test proxy (#2236)
* add more test proxy

* test tarball and search

* format

* refactor uplinks
2021-05-08 19:21:21 +02:00
Juan Picado
8582548559 chore: add test for proxy (#2235)
* chore: add test for proxy

* format
2021-05-08 09:47:30 +02:00
Juan Picado
32f66cc2c7 chore: update format 2021-05-07 07:42:46 +02:00
362 changed files with 4197 additions and 31882 deletions

View File

@@ -0,0 +1,5 @@
---
'verdaccio-aws-s3-storage': patch
---
Fix the prefix used to delete from s3 when unpublishing packages

View File

@@ -0,0 +1,5 @@
---
'@verdaccio/utils': patch
---
Fixed the validation of the name when searching for a tarball that have scoped package name

View File

@@ -0,0 +1,6 @@
---
'@verdaccio/cli': minor
'@verdaccio/fastify-migration': minor
---
[Fastify] Add ping endpoint

View File

@@ -33,24 +33,27 @@
"verdaccio-aws-s3-storage": "11.0.0-alpha.0",
"verdaccio-google-cloud": "11.0.0-alpha.0",
"verdaccio-memory": "11.0.0-alpha.0",
"@verdaccio/website": "0.0.1",
"@verdaccio/ui-theme": "6.0.0-alpha.1",
"@verdaccio/e2e-cli": "1.0.0",
"@verdaccio/e2e-ui": "1.0.0",
"@verdaccio/cli-standalone": "6.0.0-alpha.3",
"@verdaccio/tarball": "11.0.0-alpha.3",
"@verdaccio/url": "11.0.0-alpha.3",
"@verdaccio/fastify-migration": "6.0.0-6-next.9"
"@verdaccio/fastify-migration": "6.0.0-6-next.9",
"@verdaccio/eslint-config": "1.0.0"
},
"changesets": [
"afraid-mice-obey",
"big-lobsters-sin",
"calm-pants-impress",
"few-cooks-destroy",
"fifty-jars-rest",
"gentle-parrots-lay",
"gentle-trains-switch",
"gold-vans-tease",
"healthy-bikes-behave",
"healthy-poets-compare",
"heavy-ravens-lay",
"hip-hounds-destroy",
"late-adults-love",
"late-parents-act",

View File

@@ -9,4 +9,3 @@ Full package name queries was not finding anithing. It was happening
becouse of stemmer of [lunr.js](https://lunrjs.com/).
To fix this, the stemmer of [lunr.js](https://lunrjs.com/) was removed from search pipeline.

102
.eslintrc
View File

@@ -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
View File

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

View File

@@ -100,8 +100,6 @@ jobs:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
- name: Install
## we run scripts due gatsby needs it
## when website is excluded we can add --ignore-scripts
run: pnpm recursive install --frozen-lockfile --ignore-scripts
- name: build
run: pnpm build
@@ -194,27 +192,6 @@ jobs:
run: pnpm recursive install --frozen-lockfile
- name: Test CLI
run: pnpm test:e2e:cli
website:
needs: [format, lint]
runs-on: ubuntu-latest
name: website build node 14
steps:
- uses: actions/checkout@v2.3.1
- uses: actions/setup-node@v1
with:
node-version: 14
- name: Install pnpm
run: npm i pnpm@latest -g
- uses: actions/cache@v2
with:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
- name: Install
run: pnpm recursive install --frozen-lockfile
- name: Build website
run: |
cd website
pnpm build:website
test-windows:
needs: [format, lint]
runs-on: windows-latest

View File

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

View File

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

View File

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

View File

@@ -39,7 +39,7 @@
"@babel/register": "7.13.14",
"@babel/runtime": "7.13.10",
"@changesets/changelog-github": "^0.2.8",
"@changesets/cli": "^2.15.0",
"@changesets/cli": "2.15.0",
"@changesets/get-dependents-graph": "^1.2.0",
"@commitlint/cli": "8.3.5",
"@commitlint/config-conventional": "8.2.0",
@@ -71,6 +71,7 @@
"@typescript-eslint/parser": "4.13.0",
"@verdaccio/types": "workspace:*",
"@verdaccio/ui-theme": "workspace:*",
"@verdaccio/eslint-config": "workspace:*",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.1.0",
"babel-jest": "26.6.3",
@@ -78,20 +79,21 @@
"babel-plugin-emotion": "11.0.0",
"codecov": "3.8.1",
"concurrently": "^5.3.0",
"core-js": "^3.10.1",
"core-js": "^3.12.1",
"cross-env": "7.0.3",
"detect-secrets": "1.0.6",
"eslint": "7.19.0",
"eslint": "7.26.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-import": "2.22.1",
"eslint-plugin-jest": "24.1.3",
"eslint-plugin-import": "2.23.2",
"eslint-plugin-jest": "24.3.6",
"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-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",
"get-stdin": "7.0.0",
"husky": "2.7.0",
@@ -107,14 +109,14 @@
"nock": "12.0.3",
"nodemon": "^2.0.7",
"npm-run-all": "4.1.5",
"prettier": "2.2.1",
"prettier": "2.3.0",
"rimraf": "3.0.2",
"selfsigned": "1.10.8",
"supertest": "4.0.2",
"ts-node": "^9.1.1",
"typescript": "^4.2.4",
"update-ts-references": "2.3.0",
"verdaccio": "^5.0.1",
"verdaccio": "^5.0.4",
"verdaccio-audit": "workspace:*",
"verdaccio-auth-memory": "workspace:*",
"verdaccio-htpasswd": "workspace:*",
@@ -126,7 +128,7 @@
"docker": "docker build -t verdaccio/verdaccio:local . --no-cache",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md}\"",
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md}\"",
"lint": "eslint \"**/*.{js,jsx,ts,tsx}\"",
"lint": "eslint --max-warnings 165 \"**/*.{js,jsx,ts,tsx}\"",
"test": "pnpm recursive test --filter ./packages",
"test:e2e:cli": "pnpm test --filter ...@verdaccio/e2e-cli",
"test:e2e:ui": "pnpm test --filter ...@verdaccio/e2e-ui",
@@ -139,9 +141,6 @@
"start:ts": "ts-node packages/verdaccio/src/start.ts -- --listen 8000",
"debug": "node --inspect packages/verdaccio/debug/bootstrap.js",
"debug:break": "node --inspect-brk packages/verdaccio/debug/bootstrap.js",
"website:lint": "cd website && yarn lint",
"website:develop": "cd website && yarn develop",
"website:build": "cd website && yarn build",
"changeset": "changeset",
"changeset:check": "changeset status --since-master",
"ci:version": "run-s ci:version:changeset ci:version:install",

View File

@@ -1,5 +1,18 @@
# @verdaccio/api
## 6.0.0-6-next.12
### Patch Changes
- Updated dependencies [d2c65da9]
- @verdaccio/utils@6.0.0-6-next.5
- @verdaccio/auth@6.0.0-6-next.9
- @verdaccio/config@6.0.0-6-next.7
- @verdaccio/tarball@11.0.0-6-next.6
- @verdaccio/middleware@6.0.0-6-next.9
- @verdaccio/store@6.0.0-6-next.10
- @verdaccio/hooks@6.0.0-6-next.4
## 6.0.0-6-next.11
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/api",
"version": "6.0.0-6-next.11",
"version": "6.0.0-6-next.12",
"description": "loaders logic",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -39,15 +39,15 @@
},
"license": "MIT",
"dependencies": {
"@verdaccio/auth": "workspace:6.0.0-6-next.8",
"@verdaccio/auth": "workspace:6.0.0-6-next.9",
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/config": "workspace:6.0.0-6-next.6",
"@verdaccio/config": "workspace:6.0.0-6-next.7",
"@verdaccio/hooks": "workspace:6.0.0-6-next.4",
"@verdaccio/logger": "workspace:6.0.0-6-next.4",
"@verdaccio/middleware": "workspace:6.0.0-6-next.8",
"@verdaccio/store": "workspace:6.0.0-6-next.9",
"@verdaccio/tarball": "workspace:11.0.0-6-next.5",
"@verdaccio/utils": "workspace:6.0.0-6-next.4",
"@verdaccio/middleware": "workspace:6.0.0-6-next.9",
"@verdaccio/store": "workspace:6.0.0-6-next.10",
"@verdaccio/tarball": "workspace:11.0.0-6-next.6",
"@verdaccio/utils": "workspace:6.0.0-6-next.5",
"cookies": "0.8.0",
"debug": "^4.1.1",
"express": "4.17.1",
@@ -56,7 +56,7 @@
"semver": "7.3.2"
},
"devDependencies": {
"@verdaccio/server": "workspace:6.0.0-6-next.15",
"@verdaccio/server": "workspace:6.0.0-6-next.16",
"@verdaccio/types": "workspace:11.0.0-6-next.7",
"body-parser": "1.19.0",
"lodash": "^4.17.20",

View File

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

View File

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

View File

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

View File

@@ -16,10 +16,11 @@ import { $RequestExtend, $ResponseExtend } from '../../types/custom';
import { initializeServer } from './_helper';
const mockApiJWTmiddleware = jest.fn(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: 'test', groups: [], real_groups: [] };
_next();
}
() =>
(req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: 'test', groups: [], real_groups: [] };
_next();
}
);
const mockAuthenticate = jest.fn(() => (_name, _password, callback): void => {
@@ -53,10 +54,11 @@ describe('user', () => {
test('should test add a new user', async (done) => {
mockApiJWTmiddleware.mockImplementationOnce(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: undefined };
_next();
}
() =>
(req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: undefined };
_next();
}
);
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) => {
mockApiJWTmiddleware.mockImplementationOnce(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: undefined };
_next();
}
() =>
(req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: undefined };
_next();
}
);
supertest(await initializeServer('user.yaml'))
.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) => {
mockApiJWTmiddleware.mockImplementationOnce(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: undefined };
_next();
}
() =>
(req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: undefined };
_next();
}
);
mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => {
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) => {
mockApiJWTmiddleware.mockImplementationOnce(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: undefined };
_next();
}
() =>
(req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: undefined };
_next();
}
);
const credentialsShort = _.cloneDeep(credentials);
delete credentialsShort.password;
@@ -181,10 +186,11 @@ describe('user', () => {
test('should test fails add a new user with wrong password', async (done) => {
mockApiJWTmiddleware.mockImplementationOnce(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: 'test' };
_next();
}
() =>
(req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: 'test' };
_next();
}
);
mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => {
return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD));
@@ -210,10 +216,11 @@ describe('user', () => {
test('should be able to logout an user', async (done) => {
mockApiJWTmiddleware.mockImplementationOnce(
() => (req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: 'test' };
_next();
}
() =>
(req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: 'test' };
_next();
}
);
mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => {
return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD));

View File

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

View File

@@ -1,5 +1,14 @@
# @verdaccio/auth
## 6.0.0-6-next.9
### Patch Changes
- Updated dependencies [d2c65da9]
- @verdaccio/utils@6.0.0-6-next.5
- @verdaccio/config@6.0.0-6-next.7
- @verdaccio/loaders@6.0.0-6-next.4
## 6.0.0-6-next.8
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/auth",
"version": "6.0.0-6-next.8",
"version": "6.0.0-6-next.9",
"description": "logger",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -40,10 +40,10 @@
"license": "MIT",
"dependencies": {
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/config": "workspace:6.0.0-6-next.6",
"@verdaccio/config": "workspace:6.0.0-6-next.7",
"@verdaccio/loaders": "workspace:6.0.0-6-next.4",
"@verdaccio/logger": "workspace:6.0.0-6-next.4",
"@verdaccio/utils": "workspace:6.0.0-6-next.4",
"@verdaccio/utils": "workspace:6.0.0-6-next.5",
"verdaccio-htpasswd": "workspace:11.0.0-alpha.6",
"debug": "^4.1.1",
"express": "4.17.1",
@@ -51,7 +51,7 @@
"lodash": "4.17.15"
},
"devDependencies": {
"@verdaccio/mock": "workspace:6.0.0-6-next.6",
"@verdaccio/mock": "workspace:6.0.0-6-next.7",
"@verdaccio/types": "workspace:11.0.0-6-next.7"
},
"funding": {

View File

@@ -1,5 +1,18 @@
# @verdaccio/cli
## 6.0.0-6-next.17
### Minor Changes
- 55ee3fdd: [Fastify] Add ping endpoint
### Patch Changes
- Updated dependencies [55ee3fdd]
- @verdaccio/fastify-migration@6.0.0-6-next.10
- @verdaccio/config@6.0.0-6-next.7
- @verdaccio/node-api@6.0.0-6-next.17
## 6.0.0-6-next.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/cli",
"version": "6.0.0-6-next.16",
"version": "6.0.0-6-next.17",
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com"
@@ -40,19 +40,23 @@
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
"watch": "pnpm build:js --F --watch",
"build": "pnpm run build:js && pnpm run build:types"
"build": "pnpm run build:js && pnpm run build:types",
"start": "ts-node src/index.ts"
},
"dependencies": {
"@verdaccio/config": "workspace:6.0.0-6-next.6",
"@verdaccio/config": "workspace:6.0.0-6-next.7",
"@verdaccio/logger": "workspace:6.0.0-6-next.4",
"@verdaccio/node-api": "workspace:6.0.0-6-next.16",
"@verdaccio/fastify-migration": "workspace:6.0.0-6-next.9",
"@verdaccio/node-api": "workspace:6.0.0-6-next.17",
"@verdaccio/fastify-migration": "workspace:6.0.0-6-next.10",
"commander": "6.2.0",
"clipanion": "3.0.0-rc.11",
"envinfo": "7.4.0",
"kleur": "3.0.3",
"semver": "7.3.2"
},
"devDependencies": {
"ts-node": "9.1.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/verdaccio"

View File

@@ -1,6 +1,8 @@
import { Command, Option } from 'clipanion';
import { findConfigFile, parseConfigFile } from '@verdaccio/config';
import { setup, logger } from '@verdaccio/logger';
import server from '@verdaccio/fastify-migration';
import { ConfigRuntime } from '@verdaccio/types';
export const DEFAULT_PROCESS_NAME: string = 'verdaccio';
@@ -19,17 +21,29 @@ export class NewServer extends Command {
description: 'use this configuration file (default: ./config.yaml)',
});
private initLogger(logConfig: ConfigRuntime) {
try {
if (logConfig.logs) {
process.emitWarning('config.logs is deprecated, rename configuration to "config.log"');
}
// FUTURE: remove fallback when is ready
setup(logConfig.log || logConfig.logs);
} catch {
throw new Error('error on init logger');
}
}
public async execute() {
try {
const configPathLocation = findConfigFile(this.config as string);
const configParsed = parseConfigFile(configPathLocation);
const { web } = configParsed;
this.initLogger(configParsed);
process.title = web?.title || DEFAULT_PROCESS_NAME;
// const { version, name } = require('../../package.json');
const ser = await server();
await ser.listen(4000);
console.log('fastify running on port 4000');
const ser = await server({ logger });
await ser.listen(4873);
} catch (err) {
console.error(err);
process.exit(1);

View File

@@ -1,5 +1,12 @@
# @verdaccio/config
## 6.0.0-6-next.7
### Patch Changes
- Updated dependencies [d2c65da9]
- @verdaccio/utils@6.0.0-6-next.5
## 6.0.0-6-next.6
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/config",
"version": "6.0.0-6-next.6",
"version": "6.0.0-6-next.7",
"description": "logger",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -40,7 +40,7 @@
},
"dependencies": {
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/utils": "workspace:6.0.0-6-next.4",
"@verdaccio/utils": "workspace:6.0.0-6-next.5",
"debug": "^4.2.0",
"js-yaml": "3.14.0",
"lodash": "^4.17.20",

View File

@@ -1,6 +1,5 @@
import fs from 'fs';
import path from 'path';
import Path from 'path';
import _ from 'lodash';
import buildDebug from 'debug';
@@ -27,28 +26,34 @@ const debug = buildDebug('verdaccio:config');
* Find and get the first config file that match.
* @return {String} the config file path
*/
function findConfigFile(configPath: string | undefined): string {
function findConfigFile(configPath?: string): string {
// console.log(process.env);
if (typeof configPath !== 'undefined') {
return Path.resolve(configPath);
return path.resolve(configPath);
}
const configPaths: SetupDirectory[] = getConfigPaths();
debug('%o posible locations found', configPaths.length);
if (_.isEmpty(configPaths)) {
// this should never happens
throw new Error('no configuration files can be processed');
}
const primaryConf: any = _.find(configPaths, (configLocation: any) =>
// find the first location that already exist
const primaryConf: SetupDirectory | void = _.find(configPaths, (configLocation: SetupDirectory) =>
fileExists(configLocation.path)
);
if (_.isNil(primaryConf) === false) {
if (typeof primaryConf !== 'undefined') {
debug('previous location exist already %s', primaryConf?.path);
return primaryConf.path;
}
// @ts-ignore
return createConfigFile(_.head(configPaths)).path;
}
function createConfigFile(configLocation: any): SetupDirectory {
function createConfigFile(configLocation: SetupDirectory): SetupDirectory {
createConfigFolder(configLocation);
const defaultConfig = updateStorageLinks(configLocation, readDefaultConfig());
@@ -60,13 +65,18 @@ function createConfigFile(configLocation: any): SetupDirectory {
export function readDefaultConfig(): Buffer {
const pathDefaultConf: string = path.resolve(__dirname, 'conf/default.yaml');
try {
debug('default configuration file %s', pathDefaultConf);
fs.accessSync(pathDefaultConf, fs.constants.R_OK);
} catch {
throw new TypeError('configuration file does not have enough permissions for reading');
}
// @ts-ignore
return fs.readFileSync(pathDefaultConf, CHARACTER_ENCODING.UTF8);
}
function createConfigFolder(configLocation): void {
fs.mkdirSync(Path.dirname(configLocation.path), { recursive: true });
fs.mkdirSync(path.dirname(configLocation.path), { recursive: true });
debug(`Creating default config file in %o`, configLocation?.path);
}
@@ -78,64 +88,89 @@ function updateStorageLinks(configLocation, defaultConfig): string {
// $XDG_DATA_HOME defines the base directory relative to which user specific data
// files should be stored, If $XDG_DATA_HOME is either not set or empty, a default
// equal to $HOME/.local/share should be used.
// $FlowFixMe
let dataDir =
process.env.XDG_DATA_HOME || Path.join(process.env.HOME as string, '.local', 'share');
process.env.XDG_DATA_HOME || path.join(process.env.HOME as string, '.local', 'share');
if (folderExists(dataDir)) {
dataDir = Path.resolve(Path.join(dataDir, pkgJSON.name, 'storage'));
debug(`previous storage located`);
debug(`update storage links to %s`, dataDir);
dataDir = path.resolve(path.join(dataDir, pkgJSON.name, 'storage'));
return defaultConfig.replace(/^storage: .\/storage$/m, `storage: ${dataDir}`);
}
debug(`could not find a previous storage location, skip override`);
return defaultConfig;
}
/**
* Return a list of configuration locations by platform.
* @returns
*/
function getConfigPaths(): SetupDirectory[] {
const listPaths: SetupDirectory[] = [
const listPaths: (SetupDirectory | void)[] = [
getXDGDirectory(),
getWindowsDirectory(),
getRelativeDefaultDirectory(),
getOldDirectory(),
].reduce(function (acc, currentValue: any): SetupDirectory[] {
if (_.isUndefined(currentValue) === false) {
];
return listPaths.reduce(function (acc, currentValue: SetupDirectory | void): SetupDirectory[] {
if (typeof currentValue !== 'undefined') {
debug('directory detected path %s for type %s', currentValue?.path, currentValue.type);
acc.push(currentValue);
}
return acc;
}, [] as SetupDirectory[]);
return listPaths;
}
/**
* Get XDG_CONFIG_HOME or HOME location (usually unix)
* @returns
*/
const getXDGDirectory = (): SetupDirectory | void => {
const XDGConfig = getXDGHome() || (process.env.HOME && Path.join(process.env.HOME, '.config'));
if (XDGConfig && folderExists(XDGConfig)) {
const xDGConfigPath =
process.env.XDG_CONFIG_HOME || (process.env.HOME && path.join(process.env.HOME, '.config'));
if (xDGConfigPath && folderExists(xDGConfigPath)) {
debug('XDGConfig folder path %s', xDGConfigPath);
return {
path: Path.join(XDGConfig, pkgJSON.name, CONFIG_FILE),
path: path.join(xDGConfigPath, pkgJSON.name, CONFIG_FILE),
type: XDG,
};
}
};
const getXDGHome = (): string | void => process.env.XDG_CONFIG_HOME;
/**
* Detect windows location, APPDATA
* usually something like C:\User\<Build User>\AppData\Local
* @returns
*/
const getWindowsDirectory = (): SetupDirectory | void => {
if (process.platform === WIN32 && process.env.APPDATA && folderExists(process.env.APPDATA)) {
debug('is windows appdata: %s', process.env.APPDATA);
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)),
type: WIN,
};
}
};
/**
* Return relative directory, this is the default.
* It will cretate config in your {currentLocation/verdaccio/config.yaml}
* @returns
*/
const getRelativeDefaultDirectory = (): SetupDirectory => {
return {
path: Path.resolve(Path.join('.', pkgJSON.name, CONFIG_FILE)),
path: path.resolve(path.join('.', pkgJSON.name, CONFIG_FILE)),
type: 'def',
};
};
/**
* This should never happens, consider it DEPRECATED
* @returns
*/
const getOldDirectory = (): SetupDirectory => {
return {
path: Path.resolve(Path.join('.', CONFIG_FILE)),
path: path.resolve(path.join('.', CONFIG_FILE)),
type: 'old',
};
};

View File

@@ -106,7 +106,7 @@ class Config implements AppConfig {
/**
* Store or create whether receive a secret key
*/
public checkSecretKey(secret: string): string {
public checkSecretKey(secret?: string): string {
debug('check secret key');
if (_.isString(secret) && _.isEmpty(secret) === false) {
this.secret = secret;

View File

@@ -0,0 +1,105 @@
import os from 'os';
import { findConfigFile } from '../src/config-path';
const mockmkDir = jest.fn();
const mockaccessSync = jest.fn();
const mockwriteFile = jest.fn();
jest.mock('fs', () => {
const fsOri = jest.requireActual('fs');
return {
...fsOri,
statSync: (path) => ({
isDirectory: () => {
if (path.match(/fail/)) {
throw Error('file does not exist');
}
return true;
},
}),
accessSync: (a) => mockaccessSync(a),
mkdirSync: (a) => mockmkDir(a),
writeFileSync: (a) => mockwriteFile(a),
};
});
jest.mock('fs');
describe('config-path', () => {
beforeEach(() => {
jest.clearAllMocks();
jest.resetAllMocks();
});
describe('findConfigFile', () => {
if (os.platform() !== 'win32') {
describe('using defiled location from arguments', () => {
test('with custom location', () => {
expect(findConfigFile('/home/user/custom/location/config.yaml')).toEqual(
'/home/user/custom/location/config.yaml'
);
expect(mockwriteFile).not.toHaveBeenCalled();
expect(mockmkDir).not.toHaveBeenCalled();
});
});
describe('whith env variables', () => {
test('with XDG_CONFIG_HOME if directory exist but config file is missing', () => {
process.env.XDG_CONFIG_HOME = '/home/user';
expect(findConfigFile()).toEqual('/home/user/verdaccio/config.yaml');
expect(mockwriteFile).toHaveBeenCalledWith('/home/user/verdaccio/config.yaml');
expect(mockmkDir).toHaveBeenCalledWith('/home/user/verdaccio');
});
test('with HOME if directory exist but config file is missing', () => {
delete process.env.XDG_CONFIG_HOME;
process.env.HOME = '/home/user';
expect(findConfigFile()).toEqual('/home/user/.config/verdaccio/config.yaml');
expect(mockwriteFile).toHaveBeenCalledWith('/home/user/.config/verdaccio/config.yaml');
expect(mockmkDir).toHaveBeenCalledWith('/home/user/.config/verdaccio');
});
describe('error handling', () => {
test('XDG_CONFIG_HOME is not directory fallback to default', () => {
process.env.XDG_CONFIG_HOME = '/home/user/fail';
mockaccessSync.mockImplementation(() => {});
mockwriteFile.mockImplementation(() => {});
expect(findConfigFile()).toMatch('packages/config/verdaccio/config.yaml');
});
test('no permissions on read default config file', () => {
process.env.XDG_CONFIG_HOME = '/home/user';
mockaccessSync.mockImplementation(() => {
throw new Error('error on write file');
});
expect(function () {
findConfigFile();
}).toThrow(/configuration file does not have enough permissions for reading/);
});
});
});
describe('with no env variables', () => {
test('with relative location', () => {
mockaccessSync.mockImplementation(() => {});
delete process.env.XDG_CONFIG_HOME;
delete process.env.HOME;
process.env.APPDATA = '/app/data/';
expect(findConfigFile()).toMatch('packages/config/verdaccio/config.yaml');
expect(mockwriteFile).toHaveBeenCalled();
expect(mockmkDir).toHaveBeenCalled();
});
});
} else {
test('with windows as directory exist but config file is missing', () => {
delete process.env.XDG_CONFIG_HOME;
delete process.env.HOME;
process.env.APPDATA = '/app/data/';
expect(findConfigFile()).toEqual('D:\\app\\data\\verdaccio\\config.yaml');
expect(mockwriteFile).toHaveBeenCalledWith('D:\\app\\data\\verdaccio\\config.yaml');
expect(mockmkDir).toHaveBeenCalledWith('D:\\app\\data\\verdaccio');
});
}
});
});

View File

@@ -9,6 +9,7 @@ import {
parseConfigFile,
ROLES,
WEB_TITLE,
getMatchedPackagesSpec,
} from '../src';
import { parseConfigurationFile } from './utils';
@@ -23,56 +24,56 @@ const checkDefaultUplink = (config) => {
expect(config.uplinks[DEFAULT_UPLINK].url).toMatch(DEFAULT_REGISTRY);
};
const checkDefaultConfPackages = (config) => {
// auth
expect(_.isObject(config.auth)).toBeTruthy();
expect(_.isObject(config.auth.htpasswd)).toBeTruthy();
expect(config.auth.htpasswd.file).toMatch(/htpasswd/);
// web
expect(_.isObject(config.web)).toBeTruthy();
expect(config.web.title).toBe(WEB_TITLE);
expect(config.web.enable).toBeUndefined();
// packages
expect(_.isObject(config.packages)).toBeTruthy();
expect(Object.keys(config.packages).join('|')).toBe('@*/*|**');
expect(config.packages['@*/*'].access).toBeDefined();
expect(config.packages['@*/*'].access).toContainEqual(ROLES.$ALL);
expect(config.packages['@*/*'].publish).toBeDefined();
expect(config.packages['@*/*'].publish).toContainEqual(ROLES.$AUTH);
expect(config.packages['@*/*'].proxy).toBeDefined();
expect(config.packages['@*/*'].proxy).toContainEqual(DEFAULT_UPLINK);
expect(config.packages['**'].access).toBeDefined();
expect(config.packages['**'].access).toContainEqual(ROLES.$ALL);
expect(config.packages['**'].publish).toBeDefined();
expect(config.packages['**'].publish).toContainEqual(ROLES.$AUTH);
expect(config.packages['**'].proxy).toBeDefined();
expect(config.packages['**'].proxy).toContainEqual(DEFAULT_UPLINK);
// uplinks
expect(config.uplinks[DEFAULT_UPLINK]).toBeDefined();
expect(config.uplinks[DEFAULT_UPLINK].url).toEqual(DEFAULT_REGISTRY);
// audit
expect(config.middlewares).toBeDefined();
expect(config.middlewares.audit).toBeDefined();
expect(config.middlewares.audit.enabled).toBeTruthy();
// logs
expect(config.logs).toBeDefined();
expect(config.logs.type).toEqual('stdout');
expect(config.logs.format).toEqual('pretty');
expect(config.logs.level).toEqual('http');
// must not be enabled by default
expect(config.notify).toBeUndefined();
expect(config.store).toBeUndefined();
expect(config.publish).toBeUndefined();
expect(config.url_prefix).toBeUndefined();
expect(config.url_prefix).toBeUndefined();
expect(config.experiments).toBeUndefined();
expect(config.security).toEqual(defaultSecurity);
};
describe('check basic content parsed file', () => {
const checkDefaultConfPackages = (config) => {
// auth
expect(_.isObject(config.auth)).toBeTruthy();
expect(_.isObject(config.auth.htpasswd)).toBeTruthy();
expect(config.auth.htpasswd.file).toMatch(/htpasswd/);
// web
expect(_.isObject(config.web)).toBeTruthy();
expect(config.web.title).toBe(WEB_TITLE);
expect(config.web.enable).toBeUndefined();
// packages
expect(_.isObject(config.packages)).toBeTruthy();
expect(Object.keys(config.packages).join('|')).toBe('@*/*|**');
expect(config.packages['@*/*'].access).toBeDefined();
expect(config.packages['@*/*'].access).toContainEqual(ROLES.$ALL);
expect(config.packages['@*/*'].publish).toBeDefined();
expect(config.packages['@*/*'].publish).toContainEqual(ROLES.$AUTH);
expect(config.packages['@*/*'].proxy).toBeDefined();
expect(config.packages['@*/*'].proxy).toContainEqual(DEFAULT_UPLINK);
expect(config.packages['**'].access).toBeDefined();
expect(config.packages['**'].access).toContainEqual(ROLES.$ALL);
expect(config.packages['**'].publish).toBeDefined();
expect(config.packages['**'].publish).toContainEqual(ROLES.$AUTH);
expect(config.packages['**'].proxy).toBeDefined();
expect(config.packages['**'].proxy).toContainEqual(DEFAULT_UPLINK);
// uplinks
expect(config.uplinks[DEFAULT_UPLINK]).toBeDefined();
expect(config.uplinks[DEFAULT_UPLINK].url).toEqual(DEFAULT_REGISTRY);
// audit
expect(config.middlewares).toBeDefined();
expect(config.middlewares.audit).toBeDefined();
expect(config.middlewares.audit.enabled).toBeTruthy();
// logs
expect(config.logs).toBeDefined();
expect(config.logs.type).toEqual('stdout');
expect(config.logs.format).toEqual('pretty');
expect(config.logs.level).toEqual('http');
// must not be enabled by default
expect(config.notify).toBeUndefined();
expect(config.store).toBeUndefined();
expect(config.publish).toBeUndefined();
expect(config.url_prefix).toBeUndefined();
expect(config.url_prefix).toBeUndefined();
expect(config.experiments).toBeUndefined();
expect(config.security).toEqual(defaultSecurity);
};
test('parse default.yaml', () => {
const config = new Config(parseConfigFile(resolveConf('default')));
checkDefaultUplink(config);
@@ -81,6 +82,57 @@ describe('check basic content parsed file', () => {
checkDefaultConfPackages(config);
});
test('parse docker.yaml', () => {
const config = new Config(parseConfigFile(resolveConf('docker')));
checkDefaultUplink(config);
expect(config.storage).toBe('/verdaccio/storage/data');
expect(config.auth.htpasswd.file).toBe('/verdaccio/storage/htpasswd');
checkDefaultConfPackages(config);
});
});
describe('checkSecretKey', () => {
test('with default.yaml and pre selected secret', () => {
const config = new Config(parseConfigFile(resolveConf('default')));
expect(config.checkSecretKey('12345')).toEqual('12345');
});
test('with default.yaml and void secret', () => {
const config = new Config(parseConfigFile(resolveConf('default')));
expect(typeof config.checkSecretKey() === 'string').toBeTruthy();
});
test('with default.yaml and emtpy string secret', () => {
const config = new Config(parseConfigFile(resolveConf('default')));
expect(typeof config.checkSecretKey('') === 'string').toBeTruthy();
});
});
describe('getMatchedPackagesSpec', () => {
test('should match with react as defined in config file', () => {
const configParsed = parseConfigFile(parseConfigurationFile('config-getMatchedPackagesSpec'));
const config = new Config(configParsed);
expect(config.getMatchedPackagesSpec('react')).toEqual({
access: ['admin'],
proxy: ['facebook'],
publish: ['admin'],
unpublish: false,
});
});
test('should not match with react as defined in config file', () => {
const configParsed = parseConfigFile(parseConfigurationFile('config-getMatchedPackagesSpec'));
const config = new Config(configParsed);
expect(config.getMatchedPackagesSpec('somePackage')).toEqual({
access: [ROLES.$ALL],
proxy: ['npmjs'],
publish: [ROLES.$AUTH],
unpublish: false,
});
});
});
describe('VERDACCIO_STORAGE_PATH', () => {
test('should set storage to value set in VERDACCIO_STORAGE_PATH environment variable', () => {
const storageLocation = '/tmp/verdaccio';
process.env.VERDACCIO_STORAGE_PATH = storageLocation;
@@ -106,12 +158,4 @@ describe('check basic content parsed file', () => {
expect(config.storage).toBe(storageLocation);
delete process.env.VERDACCIO_STORAGE_PATH;
});
test('parse docker.yaml', () => {
const config = new Config(parseConfigFile(resolveConf('docker')));
checkDefaultUplink(config);
expect(config.storage).toBe('/verdaccio/storage/data');
expect(config.auth.htpasswd.file).toBe('/verdaccio/storage/htpasswd');
checkDefaultConfPackages(config);
});
});

View File

@@ -88,26 +88,17 @@ describe('Package access utilities', () => {
() => {
const { packages } = parseConfigFile(parseConfigurationFile('deprecated-pkgs-basic'));
const access = normalisePackageAccess(packages);
expect(access).toBeDefined();
const scoped = access[`${PACKAGE_ACCESS.SCOPE}`];
const all = access[`${PACKAGE_ACCESS.ALL}`];
const react = access['react-*'];
expect(react).toBeDefined();
expect(react.access).toBeDefined();
// Intended checks, Typescript should catch this, we test the runtime part
// @ts-ignore
expect(react.access).toEqual([]);
// @ts-ignore
expect(react.publish[0]).toBe('admin');
expect(react.proxy).toBeDefined();
// @ts-ignore
expect(react.proxy).toEqual([]);
expect(react.storage).toBeDefined();
expect(react.storage).toBe('react-storage');
expect(scoped).toBeDefined();
expect(scoped.storage).not.toBeDefined();
@@ -126,7 +117,6 @@ describe('Package access utilities', () => {
const scoped = access[`${PACKAGE_ACCESS.SCOPE}`];
expect(scoped).toBeUndefined();
// ** should be added by default **
const all = access[`${PACKAGE_ACCESS.ALL}`];
expect(all).toBeDefined();
@@ -141,23 +131,23 @@ describe('Package access utilities', () => {
describe('getMatchedPackagesSpec', () => {
test('should test basic config', () => {
const { packages } = parseConfigFile(parseConfigurationFile('pkgs-custom'));
// @ts-ignore
// @ts-expect-error
expect(getMatchedPackagesSpec('react', packages).proxy).toMatch('facebook');
// @ts-ignore
// @ts-expect-error
expect(getMatchedPackagesSpec('angular', packages).proxy).toMatch('google');
// @ts-ignore
// @ts-expect-error
expect(getMatchedPackagesSpec('vue', packages).proxy).toMatch('npmjs');
// @ts-ignore
// @ts-expect-error
expect(getMatchedPackagesSpec('@scope/vue', packages).proxy).toMatch('npmjs');
});
test('should test no ** wildcard on config', () => {
const { packages } = parseConfigFile(parseConfigurationFile('pkgs-nosuper-wildcard-custom'));
// @ts-ignore
// @ts-expect-error
expect(getMatchedPackagesSpec('react', packages).proxy).toMatch('facebook');
// @ts-ignore
// @ts-expect-error
expect(getMatchedPackagesSpec('angular', packages).proxy).toMatch('google');
// @ts-ignore
// @ts-expect-error
expect(getMatchedPackagesSpec('@fake/angular', packages).proxy).toMatch('npmjs');
expect(getMatchedPackagesSpec('vue', packages)).toBeUndefined();
expect(getMatchedPackagesSpec('@scope/vue', packages)).toBeUndefined();

View File

@@ -0,0 +1,17 @@
packages:
'react':
access: admin
publish: admin
proxy: facebook
'angular':
access: admin
publish: admin
proxy: google
'@*/*':
access: $all
publish: $authenticated
proxy: npmjs
'**':
access: $all
publish: $authenticated
proxy: npmjs

View File

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

View File

@@ -0,0 +1,6 @@
# @verdaccio/fastify-migration
## 6.0.0-6-next.10
### Minor Changes
- 55ee3fdd: [Fastify] Add ping endpoint

View File

@@ -0,0 +1,39 @@
storage: ./storage
plugins: ./plugins
web:
title: Verdaccio
auth:
htpasswd:
file: ./htpasswd
uplinks:
npmjs:
url: https://registry.npmjs.org/
packages:
'@*/*':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: npmjs
'**':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: npmjs
server:
keepAliveTimeout: 60
middlewares:
audit:
enabled: true
log: { type: stdout, format: pretty, level: http }
flags:
token: false
search: false
i18n:
web: en-US

View File

@@ -0,0 +1,30 @@
import path from 'path';
import buildDebug from 'debug';
import { parseConfigFile } from '@verdaccio/config';
import { setup, logger } from '@verdaccio/logger';
import server from '../src/index';
const debug = buildDebug('verdaccio:fastify:debug');
/**
* This file is intended for fast development and debug, it should
* be removed eventually and the app start from @verdaccio/cli package.
*/
(async () => {
try {
const configFile = path.join(__dirname, './fastify-conf.yaml');
debug('configFile %s', configFile);
const configParsed = parseConfigFile(configFile);
setup(configParsed.log);
logger.info(`config location ${configFile}`);
debug('configParsed %s', configParsed);
process.title = 'fastify-verdaccio';
const ser = await server({ logger });
await ser.listen(4873);
logger.info('fastify running on port 4873');
} catch (err) {
// eslint-disable-next-line no-console
console.error(err);
process.exit(1);
}
})();

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/fastify-migration",
"version": "6.0.0-6-next.9",
"version": "6.0.0-6-next.10",
"description": "Fastify server migration package",
"keywords": [
"private",
@@ -34,10 +34,15 @@
"access": "public"
},
"dependencies": {
"fastify": "3.14.2"
"@verdaccio/logger": "workspace:6.0.0-6-next.4",
"fastify": "3.15.1",
"fastify-plugin": "3.0.0",
"debug": "4.3.1"
},
"devDependencies": {
"@verdaccio/types": "workspace:11.0.0-6-next.7"
"@verdaccio/types": "workspace:11.0.0-6-next.7",
"@verdaccio/config": "workspace:6.0.0-6-next.7",
"ts-node": "9.1.1"
},
"scripts": {
"clean": "rimraf ./build",
@@ -45,7 +50,8 @@
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
"watch": "pnpm build:js -- --watch",
"build": "pnpm run build:js && pnpm run build:types"
"build": "pnpm run build:js && pnpm run build:types",
"start": "ts-node debug/index.ts"
},
"funding": {
"type": "opencollective",

View File

@@ -0,0 +1,10 @@
import { logger } from '@verdaccio/logger';
async function pingRoute(fastify) {
fastify.get('/-/ping', async () => {
logger.http('ping endpoint');
return {};
});
}
export default pingRoute;

View File

@@ -1,12 +1,14 @@
import fastify from 'fastify';
import buildDebug from 'debug';
async function startServer() {
const app = fastify();
import ping from './endpoints/ping';
app.get('/', async (request, reply) => {
return { hello: 'world' };
});
const debug = buildDebug('verdaccio:fastify');
async function startServer({ logger }) {
debug('start server');
const app = fastify({ logger });
app.register(ping);
return app;
}

View File

@@ -1,5 +1,12 @@
# Change Log
## 11.0.0-6-next.6
### Patch Changes
- Updated dependencies [d2c65da9]
- @verdaccio/utils@6.0.0-6-next.5
## 11.0.0-6-next.5
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/tarball",
"version": "11.0.0-6-next.5",
"version": "11.0.0-6-next.6",
"description": "tarball utilities resolver",
"keywords": [
"private",
@@ -38,12 +38,12 @@
"lodash": "^4.17.21",
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/url": "workspace:11.0.0-6-next.4",
"@verdaccio/utils": "workspace:6.0.0-6-next.4"
"@verdaccio/utils": "workspace:6.0.0-6-next.5"
},
"devDependencies": {
"@verdaccio/types": "workspace:11.0.0-6-next.7",
"express": "^4.17.1",
"node-mocks-http": "^1.10.1"
"express": "4.17.1",
"node-mocks-http": "1.10.1"
},
"scripts": {
"clean": "rimraf ./build",

View File

@@ -38,9 +38,9 @@
"request": "2.87.0"
},
"devDependencies": {
"@verdaccio/auth": "workspace:6.0.0-6-next.8",
"@verdaccio/auth": "workspace:6.0.0-6-next.9",
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/config": "workspace:6.0.0-6-next.6",
"@verdaccio/config": "workspace:6.0.0-6-next.7",
"@verdaccio/types": "workspace:11.0.0-6-next.7",
"nock": "^13.0.4"
},

View File

@@ -19,8 +19,8 @@
},
"devDependencies": {
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/config": "workspace:6.0.0-6-next.6",
"@verdaccio/mock": "workspace:6.0.0-6-next.6",
"@verdaccio/config": "workspace:6.0.0-6-next.7",
"@verdaccio/mock": "workspace:6.0.0-6-next.7",
"@verdaccio/types": "workspace:11.0.0-6-next.7"
},
"homepage": "https://verdaccio.org",

View File

@@ -59,86 +59,84 @@ export function loadPlugin<T extends IPlugin<T>>(
sanityCheck: any,
prefix: string = 'verdaccio'
): any[] {
return Object.keys(pluginConfigs).map(
(pluginId: string): IPlugin<T> => {
let plugin;
return Object.keys(pluginConfigs).map((pluginId: string): IPlugin<T> => {
let plugin;
const localPlugin = Path.resolve(__dirname + '/../plugins', pluginId);
// try local plugins first
plugin = tryLoad(localPlugin);
const localPlugin = Path.resolve(__dirname + '/../plugins', pluginId);
// try local plugins first
plugin = tryLoad(localPlugin);
// try the external plugin directory
if (plugin === null && config.plugins) {
const pluginDir = config.plugins;
const externalFilePlugin = Path.resolve(pluginDir, pluginId);
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}`));
}
}
}
// try the external plugin directory
if (plugin === null && config.plugins) {
const pluginDir = config.plugins;
const externalFilePlugin = Path.resolve(pluginDir, pluginId);
plugin = tryLoad(externalFilePlugin);
// npm package
if (plugin === null && pluginId.match(/^[^\.\/]/)) {
plugin = tryLoad(`${prefix}-${pluginId}`);
plugin = tryLoad(Path.resolve(pluginDir, `${prefix}-${pluginId}`));
// compatibility for old sinopia plugins
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;
});
}

View File

@@ -1,5 +1,13 @@
# @verdaccio/middleware
## 6.0.0-6-next.9
### Patch Changes
- Updated dependencies [d2c65da9]
- @verdaccio/utils@6.0.0-6-next.5
- @verdaccio/auth@6.0.0-6-next.9
## 6.0.0-6-next.8
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/middleware",
"version": "6.0.0-6-next.8",
"version": "6.0.0-6-next.9",
"description": "loaders logic",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -39,10 +39,10 @@
},
"dependencies": {
"debug": "^4.3.1",
"@verdaccio/auth": "workspace:6.0.0-6-next.8",
"@verdaccio/auth": "workspace:6.0.0-6-next.9",
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/logger": "workspace:6.0.0-6-next.4",
"@verdaccio/utils": "workspace:6.0.0-6-next.4",
"@verdaccio/utils": "workspace:6.0.0-6-next.5",
"lodash": "4.17.15"
},
"funding": {

View File

@@ -1,5 +1,13 @@
# @verdaccio/mock
## 6.0.0-6-next.7
### Patch Changes
- Updated dependencies [d2c65da9]
- @verdaccio/utils@6.0.0-6-next.5
- @verdaccio/config@6.0.0-6-next.7
## 6.0.0-6-next.6
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/mock",
"version": "6.0.0-6-next.6",
"version": "6.0.0-6-next.7",
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com"
@@ -40,8 +40,8 @@
},
"dependencies": {
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/config": "workspace:6.0.0-6-next.6",
"@verdaccio/utils": "workspace:6.0.0-6-next.4",
"@verdaccio/config": "workspace:6.0.0-6-next.7",
"@verdaccio/utils": "workspace:6.0.0-6-next.5",
"debug": "^4.2.0",
"fs-extra": "^8.1.0",
"lodash": "^4.17.20",

View File

@@ -1,5 +1,12 @@
# @verdaccio/node-api
## 6.0.0-6-next.17
### Patch Changes
- @verdaccio/config@6.0.0-6-next.7
- @verdaccio/server@6.0.0-6-next.16
## 6.0.0-6-next.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/node-api",
"version": "6.0.0-6-next.16",
"version": "6.0.0-6-next.17",
"description": "node API",
"main": "build/index.js",
"types": "build/index.d.ts",
@@ -40,15 +40,15 @@
"license": "MIT",
"dependencies": {
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/config": "workspace:6.0.0-6-next.6",
"@verdaccio/server": "workspace:6.0.0-6-next.15",
"@verdaccio/config": "workspace:6.0.0-6-next.7",
"@verdaccio/server": "workspace:6.0.0-6-next.16",
"@verdaccio/logger": "workspace:6.0.0-6-next.4",
"core-js": "^3.6.5",
"debug": "^4.2.0",
"lodash": "^4.17.20"
},
"devDependencies": {
"@verdaccio/mock": "workspace:6.0.0-6-next.6",
"@verdaccio/mock": "workspace:6.0.0-6-next.7",
"@verdaccio/types": "workspace:11.0.0-6-next.7",
"jest-mock-process": "^1.4.0",
"selfsigned": "1.10.7",

View File

@@ -51,7 +51,7 @@ class ActiveDirectoryPlugin implements IPluginAuth<ActiveDirectoryConfig> {
connection.getGroupMembershipForUser(username, (err, groups: object[]): void => {
if (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];

View File

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

View File

@@ -1,5 +1,11 @@
# Change Log
## 11.0.0-6-next.5
### Patch Changes
- 6b1a28de: Fix the prefix used to delete from s3 when unpublishing packages
## 11.0.0-6-next.4
### Major Changes

View File

@@ -1,6 +1,6 @@
{
"name": "verdaccio-aws-s3-storage",
"version": "11.0.0-6-next.4",
"version": "11.0.0-6-next.5",
"description": "AWS S3 storage implementation for Verdaccio",
"keywords": [
"private",

View File

@@ -29,14 +29,8 @@ export default class S3PackageManager implements ILocalPackageManager {
this.config = config;
this.packageName = packageName;
this.logger = logger;
const {
endpoint,
region,
s3ForcePathStyle,
accessKeyId,
secretAccessKey,
sessionToken,
} = config;
const { endpoint, region, s3ForcePathStyle, accessKeyId, secretAccessKey, sessionToken } =
config;
this.s3 = new S3({
endpoint,
@@ -172,7 +166,7 @@ export default class S3PackageManager implements ILocalPackageManager {
this.s3,
{
Bucket: this.config.bucket,
Prefix: `${this.packagePath}`,
Prefix: addTrailingSlash(this.packagePath),
},
function (err) {
if (err && is404Error(err as VerdaccioError)) {

View File

@@ -79,7 +79,7 @@ describe.skip('S3 package manager', () => {
describe('savePackage() group', () => {
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);
packageManager.savePackage('pkg.1.0.0.tar.gz', data, (err) => {

View File

@@ -231,7 +231,7 @@ describe('S3PackageManager with mocked s3', function () {
expect(mockListObject).toHaveBeenCalledWith(
{
Bucket: 'test-bucket',
Prefix: 'testKeyPrefix/@company/test-package',
Prefix: 'testKeyPrefix/@company/test-package/',
},
expect.any(Function)
);
@@ -270,7 +270,7 @@ describe('S3PackageManager with mocked s3', function () {
expect(mockListObject).toHaveBeenCalledWith(
{
Bucket: 'test-bucket',
Prefix: 'testKeyPrefix/customFolder/@company/test-package',
Prefix: 'testKeyPrefix/customFolder/@company/test-package/',
},
expect.any(Function)
);

View File

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

View File

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

View File

@@ -29,7 +29,7 @@
"@testing-library/dom": "^7.29.0",
"@testing-library/jest-dom": "^5.11.6",
"@testing-library/react": "10.4.9",
"@verdaccio/node-api": "workspace:6.0.0-6-next.16",
"@verdaccio/node-api": "workspace:6.0.0-6-next.17",
"autosuggest-highlight": "3.1.1",
"babel-loader": "^8.2.2",
"babel-plugin-dynamic-import-node": "^2.3.3",

View File

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

View File

@@ -6,9 +6,10 @@ import { Theme } from './theme';
const resetStyles = makeStyles(({ theme }: { theme?: Theme }) => ({
'@global': {
// 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': {
fontFamily: '"Roboto", Helvetica Neue, Arial, sans-serif',
},
'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',
},
strong: {
fontWeight: theme && theme.fontWeight.semiBold,
},

View File

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

View File

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

View File

@@ -1,5 +1,13 @@
# @verdaccio/proxy
## 6.0.0-6-next.9
### Patch Changes
- Updated dependencies [d2c65da9]
- @verdaccio/utils@6.0.0-6-next.5
- @verdaccio/config@6.0.0-6-next.7
## 6.0.0-6-next.8
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/proxy",
"version": "6.0.0-6-next.8",
"version": "6.0.0-6-next.9",
"description": "verdaccio proxy fetcher",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -40,17 +40,19 @@
},
"dependencies": {
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/config": "workspace:6.0.0-6-next.6",
"@verdaccio/config": "workspace:6.0.0-6-next.7",
"@verdaccio/local-storage": "workspace:11.0.0-6-next.6",
"@verdaccio/logger": "workspace:6.0.0-6-next.4",
"@verdaccio/streams": "workspace:11.0.0-alpha.3",
"@verdaccio/utils": "workspace:6.0.0-6-next.4",
"@verdaccio/utils": "workspace:6.0.0-6-next.5",
"JSONStream": "1.3.5",
"lodash": "^4.17.20",
"lodash": "4.17.20",
"request": "2.87.0"
},
"devDependencies": {
"@verdaccio/types": "workspace:11.0.0-6-next.7"
"@verdaccio/types": "workspace:11.0.0-6-next.7",
"nock": "13.0.11",
"node-mocks-http": "1.10.1"
},
"funding": {
"type": "opencollective",

View File

@@ -1,2 +1 @@
export * from './up-storage';
export * from './uplink-util';

View File

@@ -64,7 +64,6 @@ export interface IProxy {
fail_timeout: number;
upname: string;
fetchTarball(url: string): IReadTarball;
isUplinkValid(url: string): boolean;
search(options: any);
getRemoteMetadata(name: string, options: any, callback: Callback): void;
}
@@ -436,27 +435,6 @@ class ProxyStorage implements IProxy {
}
}
/**
* Determine whether can fetch from the provided URL
* @param {*} url
* @return {Boolean}
*/
public isUplinkValid(url: string): boolean {
// $FlowFixMe
const urlParsed: UrlWithStringQuery = URL.parse(url);
const isHTTPS = (urlDomainParsed: URL): boolean =>
urlDomainParsed.protocol === 'https:' &&
(urlParsed.port === null || urlParsed.port === '443');
const getHost = (urlDomainParsed): boolean =>
isHTTPS(urlDomainParsed) ? urlDomainParsed.hostname : urlDomainParsed.host;
const isMatchProtocol: boolean = urlParsed.protocol === this.url.protocol;
const isMatchHost: boolean = getHost(urlParsed) === getHost(this.url);
// @ts-ignore
const isMatchPath: boolean = urlParsed.path.indexOf(this.url.path) === 0;
return isMatchProtocol && isMatchHost && isMatchPath;
}
/**
* Get a remote package metadata
* @param {*} name package name

View File

@@ -0,0 +1,31 @@
storage: ./storage
plugins: ./plugins
web:
title: Verdaccio
auth:
htpasswd:
file: ./htpasswd
uplinks:
npmjs:
url: https://registry.npmjs.org/
packages:
'@*/*':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: npmjs
'**':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: npmjs
server:
keepAliveTimeout: 60
middlewares:
audit:
enabled: true
logs: { type: stdout, format: pretty, level: http }

View File

@@ -19,6 +19,7 @@ function createUplink(config) {
function setHeaders(config: unknown = {}, headers: unknown = {}) {
const uplink = createUplink(config);
// @ts-expect-error
return uplink._setHeaders({
headers,
});

Binary file not shown.

View File

@@ -0,0 +1,567 @@
{
"verdaccio": {
"name": "verdaccio",
"description": "A lightweight private npm proxy registry",
"maintainers": [
"=jotadeveloper",
"=ayusharma",
"=trentearl",
"=jmwilkinson",
"=sergiohgz",
"=verdaccio.npm"
],
"url": null,
"keywords": [],
"version": "5.0.4",
"time": "2021-04-28 ",
"words": "verdaccio a lightweight private npm proxy registry =jotadeveloper =ayusharma =trentearl =jmwilkinson =sergiohgz =verdaccio.npm"
},
"verdaccio-bitbucket": {
"name": "verdaccio-bitbucket",
"description": "Verdaccio module to authenticate users via Bitbucket",
"maintainers": ["=idangozlan"],
"url": null,
"keywords": [],
"version": "3.0.1",
"time": "2020-11-17 ",
"words": "verdaccio-bitbucket verdaccio module to authenticate users via bitbucket =idangozlan"
},
"@verdaccio/streams": {
"name": "@verdaccio/streams",
"description": "Stream extension for Verdaccio",
"maintainers": ["=sergiohgz", "=verdaccio.npm", "=jotadeveloper", "=ayusharma"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "@verdaccio/streams stream extension for verdaccio =sergiohgz =verdaccio.npm =jotadeveloper =ayusharma"
},
"@verdaccio/commons-api": {
"name": "@verdaccio/commons-api",
"description": "Commons API utilities for Verdaccio",
"maintainers": ["=sergiohgz", "=verdaccio.npm", "=jotadeveloper", "=ayusharma"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "@verdaccio/commons-api commons api utilities for verdaccio =sergiohgz =verdaccio.npm =jotadeveloper =ayusharma"
},
"verdaccio-auth-bitbucket": {
"name": "verdaccio-auth-bitbucket",
"description": "Verdaccio module to authenticate users via Bitbucket",
"maintainers": ["=tomamatics"],
"url": null,
"keywords": [],
"version": "2.0.3",
"time": "2020-11-12 ",
"words": "verdaccio-auth-bitbucket verdaccio module to authenticate users via bitbucket =tomamatics"
},
"verdaccio-audit": {
"name": "verdaccio-audit",
"description": "Verdaccio Middleware plugin to bypass npmjs audit",
"maintainers": ["=jotadeveloper", "=ayusharma", "=verdaccio.npm"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "verdaccio-audit verdaccio middleware plugin to bypass npmjs audit =jotadeveloper =ayusharma =verdaccio.npm"
},
"@verdaccio/ui-theme": {
"name": "@verdaccio/ui-theme",
"description": "Verdaccio User Interface",
"maintainers": ["=sergiohgz", "=verdaccio.npm", "=jotadeveloper", "=ayusharma"],
"url": null,
"keywords": [],
"version": "3.1.0",
"time": "2021-04-27 ",
"words": "@verdaccio/ui-theme verdaccio user interface =sergiohgz =verdaccio.npm =jotadeveloper =ayusharma"
},
"@verdaccio/local-storage": {
"name": "@verdaccio/local-storage",
"description": "Local storage implementation",
"maintainers": ["=sergiohgz", "=verdaccio.npm", "=jotadeveloper", "=ayusharma"],
"url": null,
"keywords": [],
"version": "10.0.6",
"time": "2021-05-01 ",
"words": "@verdaccio/local-storage local storage implementation =sergiohgz =verdaccio.npm =jotadeveloper =ayusharma"
},
"@verdaccio/file-locking": {
"name": "@verdaccio/file-locking",
"description": "library that handle file locking",
"maintainers": ["=sergiohgz", "=verdaccio.npm", "=jotadeveloper", "=ayusharma"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "@verdaccio/file-locking library that handle file locking =sergiohgz =verdaccio.npm =jotadeveloper =ayusharma"
},
"verdaccio-htpasswd": {
"name": "verdaccio-htpasswd",
"description": "htpasswd auth plugin for Verdaccio",
"maintainers": ["=jotadeveloper", "=ayusharma", "=verdaccio.npm"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "verdaccio-htpasswd htpasswd auth plugin for verdaccio =jotadeveloper =ayusharma =verdaccio.npm"
},
"verdaccio-badger": {
"name": "verdaccio-badger",
"description": "verdaccio middleware plugin to serve svg badges",
"maintainers": ["=paddek"],
"url": null,
"keywords": [],
"version": "1.0.0",
"time": "2020-08-02 ",
"words": "verdaccio-badger verdaccio middleware plugin to serve svg badges =paddek"
},
"@verdaccio/readme": {
"name": "@verdaccio/readme",
"description": "Readme markdown parser",
"maintainers": ["=sergiohgz", "=verdaccio.npm", "=jotadeveloper", "=ayusharma"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "@verdaccio/readme readme markdown parser =sergiohgz =verdaccio.npm =jotadeveloper =ayusharma"
},
"verdaccio-dynamodb": {
"name": "verdaccio-dynamodb",
"description": "Verdaccio DynamoDB Auth Plugin",
"maintainers": ["=cwilson"],
"url": null,
"keywords": [],
"version": "1.1.8",
"time": "2020-06-24 ",
"words": "verdaccio-dynamodb verdaccio dynamodb auth plugin =cwilson"
},
"@outcome-co/verdaccio-github-auth": {
"name": "@outcome-co/verdaccio-github-auth",
"description": "Verdaccio Github Authentication Plugin",
"maintainers": ["=d-tw"],
"url": null,
"keywords": [],
"version": "2.0.9",
"time": "2021-05-05 ",
"words": "@outcome-co/verdaccio-github-auth verdaccio github authentication plugin =d-tw"
},
"verdaccio-memory": {
"name": "verdaccio-memory",
"description": "Storage implementation in memory",
"maintainers": ["=jotadeveloper", "=ayusharma", "=verdaccio.npm"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "verdaccio-memory storage implementation in memory =jotadeveloper =ayusharma =verdaccio.npm"
},
"@verdaccio/types": {
"name": "@verdaccio/types",
"description": "verdaccio types definitions",
"maintainers": ["=sergiohgz", "=verdaccio.npm", "=jotadeveloper", "=ayusharma"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "@verdaccio/types verdaccio types definitions =sergiohgz =verdaccio.npm =jotadeveloper =ayusharma"
},
"verdaccio-auth-memory": {
"name": "verdaccio-auth-memory",
"description": "Auth plugin for Verdaccio that keeps users in memory",
"maintainers": ["=jotadeveloper", "=ayusharma", "=verdaccio.npm"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "verdaccio-auth-memory auth plugin for verdaccio that keeps users in memory =jotadeveloper =ayusharma =verdaccio.npm"
},
"generator-verdaccio-plugin": {
"name": "generator-verdaccio-plugin",
"description": "plugin generator for verdaccio",
"maintainers": ["=jotadeveloper", "=verdaccio.npm"],
"url": null,
"keywords": [],
"version": "3.0.1",
"time": "2020-12-23 ",
"words": "generator-verdaccio-plugin plugin generator for verdaccio =jotadeveloper =verdaccio.npm"
},
"verdaccio-bitbucket-server": {
"name": "verdaccio-bitbucket-server",
"description": "Verdaccio Authentication Plugin via Bitbucket Server",
"maintainers": ["=oeph"],
"url": null,
"keywords": [],
"version": "1.3.1",
"time": "2020-09-24 ",
"words": "verdaccio-bitbucket-server verdaccio authentication plugin via bitbucket server =oeph"
},
"verdaccio-theme-hilio": {
"name": "verdaccio-theme-hilio",
"description": "Verdaccio User Interface",
"maintainers": ["=joebnb"],
"url": null,
"keywords": [],
"version": "1.14.5",
"time": "2021-01-12 ",
"words": "verdaccio-theme-hilio verdaccio user interface =joebnb"
},
"verdaccio-aws-s3-storage": {
"name": "verdaccio-aws-s3-storage",
"description": "AWS S3 storage implementation for Verdaccio",
"maintainers": ["=jotadeveloper", "=verdaccio.npm"],
"url": null,
"keywords": [],
"version": "10.1.0",
"time": "2021-05-02 ",
"words": "verdaccio-aws-s3-storage aws s3 storage implementation for verdaccio =jotadeveloper =verdaccio.npm"
},
"verdaccio-minio": {
"name": "verdaccio-minio",
"description": "A verdaccio plugin for storing data in Minio",
"maintainers": ["=barolab"],
"url": null,
"keywords": [],
"version": "0.2.5",
"time": "2020-03-16 ",
"words": "verdaccio-minio a verdaccio plugin for storing data in minio =barolab"
},
"p3x-verdaccio-cli": {
"name": "p3x-verdaccio-cli",
"description": "🍶 Verdaccio CLI",
"maintainers": ["=patrikx3"],
"url": null,
"keywords": [],
"version": "2021.4.113",
"time": "2021-03-07 ",
"words": "p3x-verdaccio-cli 🍶 verdaccio cli =patrikx3"
},
"verdaccio-theme-xdf": {
"name": "verdaccio-theme-xdf",
"description": "Verdaccio User Interface",
"maintainers": ["=likaizhu"],
"url": null,
"keywords": [],
"version": "1.0.0",
"time": "2020-11-25 ",
"words": "verdaccio-theme-xdf verdaccio user interface =likaizhu"
},
"kiss-verdaccio-types": {
"name": "kiss-verdaccio-types",
"description": "verdaccio types definitions",
"maintainers": ["=qd397"],
"url": null,
"keywords": [],
"version": "9.7.3",
"time": "2021-02-22 ",
"words": "kiss-verdaccio-types verdaccio types definitions =qd397"
},
"@verdaccio/testing-utilities": {
"name": "@verdaccio/testing-utilities",
"description": "Utils for Verdaccio",
"maintainers": ["=sergiohgz", "=verdaccio.npm", "=jotadeveloper", "=ayusharma"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "@verdaccio/testing-utilities utils for verdaccio =sergiohgz =verdaccio.npm =jotadeveloper =ayusharma"
},
"verdaccio-git": {
"name": "verdaccio-git",
"description": "Publish packages to git repositories.",
"maintainers": ["=amazeelabs"],
"url": null,
"keywords": [],
"version": "0.1.29",
"time": "2021-03-01 ",
"words": "verdaccio-git publish packages to git repositories. =amazeelabs"
},
"eslint-plugin-verdaccio": {
"name": "eslint-plugin-verdaccio",
"description": "Verdaccio code guidelines",
"maintainers": ["=jotadeveloper", "=verdaccio.npm"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "eslint-plugin-verdaccio verdaccio code guidelines =jotadeveloper =verdaccio.npm"
},
"@verdaccio/active-directory": {
"name": "@verdaccio/active-directory",
"description": "Active Directory authentication plugin for Verdaccio",
"maintainers": ["=sergiohgz", "=verdaccio.npm", "=jotadeveloper", "=ayusharma"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "@verdaccio/active-directory active directory authentication plugin for verdaccio =sergiohgz =verdaccio.npm =jotadeveloper =ayusharma"
},
"verdaccio-google-cloud": {
"name": "verdaccio-google-cloud",
"description": "Google Cloud storage implementation for Verdaccio",
"maintainers": ["=jotadeveloper", "=verdaccio.npm"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "verdaccio-google-cloud google cloud storage implementation for verdaccio =jotadeveloper =verdaccio.npm"
},
"verdaccio-pacman": {
"name": "verdaccio-pacman",
"description": "Verdaccio Middleware Plugin to manage tags and versions of packages",
"maintainers": ["=paddek"],
"url": null,
"keywords": [],
"version": "1.1.1",
"time": "2020-10-07 ",
"words": "verdaccio-pacman verdaccio middleware plugin to manage tags and versions of packages =paddek"
},
"verdaccio-ldap-memcached": {
"name": "verdaccio-ldap-memcached",
"description": "LDAP auth plugin for verdaccio",
"maintainers": ["=therippa"],
"url": null,
"keywords": [],
"version": "1.4.1",
"time": "2018-02-02 ",
"words": "verdaccio-ldap-memcached ldap auth plugin for verdaccio =therippa"
},
"@verdaccio/eslint-config": {
"name": "@verdaccio/eslint-config",
"description": "Verdaccio ESLint shareable config",
"maintainers": ["=sergiohgz", "=verdaccio.npm", "=jotadeveloper", "=ayusharma"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "@verdaccio/eslint-config verdaccio eslint shareable config =sergiohgz =verdaccio.npm =jotadeveloper =ayusharma"
},
"uino-verdaccio": {
"name": "uino-verdaccio",
"description": "A lightweight private npm proxy registry",
"maintainers": ["=qd397"],
"url": null,
"keywords": [],
"version": "4.8.5",
"time": "2021-02-22 ",
"words": "uino-verdaccio a lightweight private npm proxy registry =qd397"
},
"@verdaccio/babel-preset": {
"name": "@verdaccio/babel-preset",
"description": "A common preset for Verdaccio projects",
"maintainers": ["=sergiohgz", "=verdaccio.npm", "=jotadeveloper", "=ayusharma"],
"url": null,
"keywords": [],
"version": "10.0.0",
"time": "2021-03-29 ",
"words": "@verdaccio/babel-preset a common preset for verdaccio projects =sergiohgz =verdaccio.npm =jotadeveloper =ayusharma"
},
"verdaccio-gitlab-hilio": {
"name": "verdaccio-gitlab-hilio",
"description": "private npm registry (Verdaccio) using gitlab-ce as authentication and authorization provider",
"maintainers": ["=joebnb"],
"url": null,
"keywords": [],
"version": "1.1.17",
"time": "2021-04-07 ",
"words": "verdaccio-gitlab-hilio private npm registry (verdaccio) using gitlab-ce as authentication and authorization provider =joebnb"
},
"verdaccio-ldap": {
"name": "verdaccio-ldap",
"description": "LDAP auth plugin for verdaccio",
"maintainers": ["=alexandre-io"],
"url": null,
"keywords": [],
"version": "4.2.0",
"time": "2020-08-15 ",
"words": "verdaccio-ldap ldap auth plugin for verdaccio =alexandre-io"
},
"verdaccio-github-oauth-ui": {
"name": "verdaccio-github-oauth-ui",
"description": "<h1 align=\"center\"> 📦🔐 Verdaccio GitHub OAuth - With UI Support </h1>",
"maintainers": ["=abraham-schilling"],
"url": null,
"keywords": [],
"version": "3.0.0",
"time": "2021-05-02 ",
"words": "verdaccio-github-oauth-ui <h1 align=\"center\"> 📦🔐 verdaccio github oauth - with ui support </h1> =abraham-schilling"
},
"verdaccio-https": {
"name": "verdaccio-https",
"description": "verdaccio middleware plugin to redirect to https",
"maintainers": ["=honzahommer"],
"url": null,
"keywords": [],
"version": "1.0.11",
"time": "2019-10-19 ",
"words": "verdaccio-https verdaccio middleware plugin to redirect to https =honzahommer"
},
"mlc-verdaccio-s3-archiver": {
"name": "mlc-verdaccio-s3-archiver",
"description": "Builds an archive of your verdaccio instance, then backup it to AWS S3.",
"maintainers": ["=moonlight-coding"],
"url": null,
"keywords": [],
"version": "1.0.3",
"time": "2020-05-17 ",
"words": "mlc-verdaccio-s3-archiver builds an archive of your verdaccio instance, then backup it to aws s3. =moonlight-coding"
},
"verdaccio-pg-storage": {
"name": "verdaccio-pg-storage",
"description": "Storage plugin to host packages PostgreSQL",
"maintainers": ["=yckao"],
"url": null,
"keywords": [],
"version": "1.0.3",
"time": "2020-06-24 ",
"words": "verdaccio-pg-storage storage plugin to host packages postgresql =yckao"
},
"verdaccio-openmetrics": {
"name": "verdaccio-openmetrics",
"description": "Verdaccio plugin exposing an OpenMetrics/Prometheus endpoint with health and traffic metrics",
"maintainers": ["=freightbot"],
"url": null,
"keywords": [],
"version": "1.1.0",
"time": "2021-03-22 ",
"words": "verdaccio-openmetrics verdaccio plugin exposing an openmetrics/prometheus endpoint with health and traffic metrics =freightbot"
},
"verdaccio-apm-server": {
"name": "verdaccio-apm-server",
"description": "An amazing verdaccio plugin",
"maintainers": ["=soul741"],
"url": null,
"keywords": [],
"version": "1.0.14",
"time": "2020-09-28 ",
"words": "verdaccio-apm-server an amazing verdaccio plugin =soul741"
},
"verdaccio-local-storage-with-cache-db": {
"name": "verdaccio-local-storage-with-cache-db",
"description": "Local storage implementation",
"maintainers": ["=joebnb"],
"url": null,
"keywords": [],
"version": "9.7.5",
"time": "2020-11-28 ",
"words": "verdaccio-local-storage-with-cache-db local storage implementation =joebnb"
},
"verdaccio-azure-ad-login": {
"name": "verdaccio-azure-ad-login",
"description": "Let your users authenticate into Verdaccio using Azure AD OAuth",
"maintainers": ["=ihton"],
"url": null,
"keywords": [],
"version": "1.0.5",
"time": "2021-02-25 ",
"words": "verdaccio-azure-ad-login let your users authenticate into verdaccio using azure ad oauth =ihton"
},
"@freighthub/verdaccio-openmetrics": {
"name": "@freighthub/verdaccio-openmetrics",
"description": "Verdaccio plugin exposing an OpenMetrics/Prometheus endpoint with health and traffic metrics",
"maintainers": [
"=pallavimalik",
"=lydia.seidlitz",
"=michelle.chua",
"=rodmatos",
"=danopia",
"=diogocostaferraz",
"=namit1211",
"=matang.dave",
"=wes.lim",
"=orinelin",
"=beheim",
"=erikmuttersbach",
"=justgoscha",
"=firellon",
"=l-oris",
"=artfwo",
"=pravinbashyal",
"=freightbot",
"=milos.mircov",
"=unsal.gokdag",
"=norocketscientist",
"=sid23",
"=vedpbharti",
"=fr-yp",
"=prabhakalaivani",
"=baptlesta",
"=luisantunesdeveloper",
"=blueyedgeek",
"=rashidfh",
"=ulymarins",
"=pedrock",
"=jose.suero",
"=anup.dev",
"=sidoshi",
"=mridulmeh",
"=dhayanand",
"=avijit.gupta",
"=dijia",
"=batuhandirek",
"=dayemsiddiqui",
"=eruditespirit",
"=ajayvarghese003",
"=ortserga",
"=fmueller_bln",
"=imartyn",
"=sabbir.ahmmed",
"=aditya337",
"=ranyardmforto",
"=mtrabelsi",
"=lsamayoa-forto",
"=nitesh-forto",
"=albertvp",
"=aliasgarhada",
"=ruizmurcia",
"=micszym",
"=b3nshi",
"=dawidmf"
],
"url": null,
"keywords": [],
"version": "1.0.1",
"time": "2021-01-12 ",
"words": "@freighthub/verdaccio-openmetrics verdaccio plugin exposing an openmetrics/prometheus endpoint with health and traffic metrics =pallavimalik =lydia.seidlitz =michelle.chua =rodmatos =danopia =diogocostaferraz =namit1211 =matang.dave =wes.lim =orinelin =beheim =erikmuttersbach =justgoscha =firellon =l-oris =artfwo =pravinbashyal =freightbot =milos.mircov =unsal.gokdag =norocketscientist =sid23 =vedpbharti =fr-yp =prabhakalaivani =baptlesta =luisantunesdeveloper =blueyedgeek =rashidfh =ulymarins =pedrock =jose.suero =anup.dev =sidoshi =mridulmeh =dhayanand =avijit.gupta =dijia =batuhandirek =dayemsiddiqui =eruditespirit =ajayvarghese003 =ortserga =fmueller_bln =imartyn =sabbir.ahmmed =aditya337 =ranyardmforto =mtrabelsi =lsamayoa-forto =nitesh-forto =albertvp =aliasgarhada =ruizmurcia =micszym =b3nshi =dawidmf"
},
"bulk-npm-publish": {
"name": "bulk-npm-publish",
"description": "Publish Multiple NPM packages from verdaccio storage",
"maintainers": ["=rluvaton"],
"url": null,
"keywords": [],
"version": "3.0.2",
"time": "2021-03-15 ",
"words": "bulk-npm-publish publish multiple npm packages from verdaccio storage =rluvaton"
},
"verdaccio-acl-plugin": {
"name": "verdaccio-acl-plugin",
"description": "Plugin to simplify group permissions management",
"maintainers": ["=t3o-it"],
"url": null,
"keywords": [],
"version": "1.0.1",
"time": "2021-02-01 ",
"words": "verdaccio-acl-plugin plugin to simplify group permissions management =t3o-it"
},
"verdaccio-openid-connect": {
"name": "verdaccio-openid-connect",
"description": "Verdaccio authentication plugin for OpenID Connect. When installed, `npm login --registry ...` command will open the browser to start login flow.",
"maintainers": ["=aikoven"],
"url": null,
"keywords": [],
"version": "1.0.2",
"time": "2021-01-31 ",
"words": "verdaccio-openid-connect verdaccio authentication plugin for openid connect. when installed, `npm login --registry ...` command will open the browser to start login flow. =aikoven"
},
"verdaccio-groups2": {
"name": "verdaccio-groups2",
"description": "- 一个verdaccio group管理插件(auth插件)",
"maintainers": ["=jeffery0211"],
"url": null,
"keywords": [],
"version": "1.0.2",
"time": "2021-01-02 ",
"words": "verdaccio-groups2 - 一个verdaccio group管理插件(auth插件) =jeffery0211"
}
}

View File

@@ -0,0 +1,744 @@
[
{
"name": "verdaccio",
"scope": "unscoped",
"version": "5.0.4",
"description": "A lightweight private npm proxy registry",
"keywords": [
"private",
"package",
"repository",
"registry",
"enterprise",
"modules",
"proxy",
"server",
"verdaccio"
],
"date": "2021-04-28T05:24:23.696Z",
"links": {
"npm": "https://www.npmjs.com/package/verdaccio",
"homepage": "https://verdaccio.org",
"repository": "https://github.com/verdaccio/verdaccio",
"bugs": "https://github.com/verdaccio/verdaccio/issues"
},
"author": {
"name": "Verdaccio Maintainers",
"email": "verdaccio.npm@gmail.com",
"username": "verdaccio.npm"
},
"publisher": {
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
"maintainers": [
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "ayusharma",
"email": "ayush.aceit@gmail.com"
},
{
"username": "trentearl",
"email": "trent@trentearl.com"
},
{
"username": "jmwilkinson",
"email": "J.Wilkinson@f5.com"
},
{
"username": "sergiohgz",
"email": "sergio@sergiohgz.eu"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
}
]
},
{
"name": "verdaccio-bitbucket",
"scope": "unscoped",
"version": "3.0.1",
"description": "Verdaccio module to authenticate users via Bitbucket",
"keywords": [
"sinopia",
"verdaccio",
"bitbucket",
"atlassian",
"auth",
"node",
"nodejs",
"js",
"javascript"
],
"date": "2020-11-17T18:31:50.893Z",
"links": {
"npm": "https://www.npmjs.com/package/verdaccio-bitbucket",
"homepage": "https://github.com/idangozlan/verdaccio-bitbucket#readme",
"repository": "https://github.com/idangozlan/verdaccio-bitbucket",
"bugs": "https://github.com/idangozlan/verdaccio-bitbucket/issues"
},
"author": {
"name": "Idan Gozlan",
"email": "idangozlan@gmail.com",
"username": "idangozlan"
},
"publisher": {
"username": "idangozlan",
"email": "idangozlan@gmail.com"
},
"maintainers": [
{
"username": "idangozlan",
"email": "idangozlan@gmail.com"
}
]
},
{
"name": "verdaccio-auth-bitbucket",
"scope": "unscoped",
"version": "2.0.3",
"description": "Verdaccio module to authenticate users via Bitbucket",
"keywords": [
"sinopia",
"verdaccio",
"bitbucket",
"atlassian",
"auth",
"node",
"nodejs",
"js",
"javascript"
],
"date": "2020-11-12T16:44:32.807Z",
"links": {
"npm": "https://www.npmjs.com/package/verdaccio-auth-bitbucket",
"homepage": "https://github.com/tomamatics/verdaccio-bitbucket#readme",
"repository": "https://github.com/tomamatics/verdaccio-bitbucket",
"bugs": "https://github.com/tomamatics/verdaccio-bitbucket/issues"
},
"author": {
"name": "Tom Pachtner",
"email": "tompachtner@gmail.com"
},
"publisher": {
"username": "tomamatics",
"email": "tom@pachtner.net"
},
"maintainers": [
{
"username": "tomamatics",
"email": "tom@pachtner.net"
}
]
},
{
"name": "verdaccio-badger",
"scope": "unscoped",
"version": "1.0.0",
"description": "verdaccio middleware plugin to serve svg badges",
"keywords": ["verdaccio", "plugin", "middleware", "badge", "badges"],
"date": "2020-08-02T18:08:10.321Z",
"links": {
"npm": "https://www.npmjs.com/package/verdaccio-badger",
"homepage": "https://github.com/PaddeK/verdaccio-badger",
"repository": "https://github.com/PaddeK/verdaccio-badger",
"bugs": "https://github.com/PaddeK/verdaccio-badger/issues"
},
"author": {
"name": "Patrick Klös",
"email": "pkloes@web.de",
"username": "paddek"
},
"publisher": {
"username": "paddek",
"email": "pkloes@web.de"
},
"maintainers": [
{
"username": "paddek",
"email": "pkloes@web.de"
}
]
},
{
"name": "@verdaccio/streams",
"scope": "verdaccio",
"version": "10.0.0",
"description": "Stream extension for Verdaccio",
"keywords": ["verdaccio", "streams"],
"date": "2021-03-29T13:01:49.263Z",
"links": {
"npm": "https://www.npmjs.com/package/%40verdaccio%2Fstreams",
"homepage": "https://verdaccio.org",
"repository": "https://github.com/verdaccio/monorepo",
"bugs": "https://github.com/verdaccio/monorepo/issues"
},
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com",
"username": "jotadeveloper"
},
"publisher": {
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
"maintainers": [
{
"username": "sergiohgz",
"email": "sergio@sergiohgz.eu"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "ayusharma",
"email": "ayush.aceit@gmail.com"
}
]
},
{
"name": "@verdaccio/commons-api",
"scope": "verdaccio",
"version": "10.0.0",
"description": "Commons API utilities for Verdaccio",
"keywords": ["http", "verdaccio", "api"],
"date": "2021-03-29T13:01:51.477Z",
"links": {
"npm": "https://www.npmjs.com/package/%40verdaccio%2Fcommons-api",
"homepage": "https://verdaccio.org",
"repository": "https://github.com/verdaccio/monorepo",
"bugs": "https://github.com/verdaccio/monorepo/issues"
},
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com",
"username": "jotadeveloper"
},
"publisher": {
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
"maintainers": [
{
"username": "sergiohgz",
"email": "sergio@sergiohgz.eu"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "ayusharma",
"email": "ayush.aceit@gmail.com"
}
]
},
{
"name": "verdaccio-audit",
"scope": "unscoped",
"version": "10.0.0",
"description": "Verdaccio Middleware plugin to bypass npmjs audit",
"keywords": ["verdaccio", "plugin", "middleware", "audit"],
"date": "2021-03-29T13:01:49.126Z",
"links": {
"npm": "https://www.npmjs.com/package/verdaccio-audit",
"homepage": "https://verdaccio.org",
"repository": "https://github.com/verdaccio/monorepo",
"bugs": "https://github.com/verdaccio/monorepo/issues"
},
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com",
"username": "jotadeveloper"
},
"publisher": {
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
"maintainers": [
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "ayusharma",
"email": "ayush.aceit@gmail.com"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
}
]
},
{
"name": "@verdaccio/ui-theme",
"scope": "verdaccio",
"version": "3.1.0",
"description": "Verdaccio User Interface",
"keywords": ["verdaccio", "verdaccio-plugin", "verdaccio-theme"],
"date": "2021-04-27T20:14:01.392Z",
"links": {
"npm": "https://www.npmjs.com/package/%40verdaccio%2Fui-theme",
"homepage": "https://verdaccio.org",
"repository": "https://github.com/verdaccio/ui",
"bugs": "https://github.com/verdaccio/ui/issues"
},
"author": {
"name": "Verdaccio Core Team",
"email": "verdaccio.npm@gmail.com",
"username": "verdaccio.npm"
},
"publisher": {
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
"maintainers": [
{
"username": "sergiohgz",
"email": "sergio@sergiohgz.eu"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "ayusharma",
"email": "ayush.aceit@gmail.com"
}
]
},
{
"name": "@verdaccio/local-storage",
"scope": "verdaccio",
"version": "10.0.6",
"description": "Local storage implementation",
"keywords": ["plugin", "verdaccio", "storage", "local-storage"],
"date": "2021-05-01T07:51:30.546Z",
"links": {
"npm": "https://www.npmjs.com/package/%40verdaccio%2Flocal-storage",
"homepage": "https://verdaccio.org",
"repository": "https://github.com/verdaccio/monorepo",
"bugs": "https://github.com/verdaccio/monorepo/issues"
},
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com",
"username": "jotadeveloper"
},
"publisher": {
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
"maintainers": [
{
"username": "sergiohgz",
"email": "sergio@sergiohgz.eu"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "ayusharma",
"email": "ayush.aceit@gmail.com"
}
]
},
{
"name": "@verdaccio/file-locking",
"scope": "verdaccio",
"version": "10.0.0",
"description": "library that handle file locking",
"keywords": ["verdaccio", "lock", "fs"],
"date": "2021-03-29T13:01:49.338Z",
"links": {
"npm": "https://www.npmjs.com/package/%40verdaccio%2Ffile-locking",
"homepage": "https://verdaccio.org",
"repository": "https://github.com/verdaccio/monorepo",
"bugs": "https://github.com/verdaccio/monorepo/issues"
},
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com",
"username": "jotadeveloper"
},
"publisher": {
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
"maintainers": [
{
"username": "sergiohgz",
"email": "sergio@sergiohgz.eu"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "ayusharma",
"email": "ayush.aceit@gmail.com"
}
]
},
{
"name": "verdaccio-htpasswd",
"scope": "unscoped",
"version": "10.0.0",
"description": "htpasswd auth plugin for Verdaccio",
"keywords": ["verdaccio", "plugin", "auth", "htpasswd"],
"date": "2021-03-29T13:01:56.726Z",
"links": {
"npm": "https://www.npmjs.com/package/verdaccio-htpasswd",
"homepage": "https://verdaccio.org",
"repository": "https://github.com/verdaccio/monorepo",
"bugs": "https://github.com/verdaccio/monorepo/issues"
},
"author": {
"name": "Ayush Sharma",
"email": "ayush.aceit@gmail.com",
"username": "ayusharma"
},
"publisher": {
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
"maintainers": [
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "ayusharma",
"email": "ayush.aceit@gmail.com"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
}
]
},
{
"name": "@verdaccio/readme",
"scope": "verdaccio",
"version": "10.0.0",
"description": "Readme markdown parser",
"keywords": ["verdaccio", "readme", "markdown"],
"date": "2021-03-29T13:01:49.184Z",
"links": {
"npm": "https://www.npmjs.com/package/%40verdaccio%2Freadme",
"homepage": "https://verdaccio.org",
"repository": "https://github.com/verdaccio/monorepo",
"bugs": "https://github.com/verdaccio/monorepo/issues"
},
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com",
"username": "jotadeveloper"
},
"publisher": {
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
"maintainers": [
{
"username": "sergiohgz",
"email": "sergio@sergiohgz.eu"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "ayusharma",
"email": "ayush.aceit@gmail.com"
}
]
},
{
"name": "verdaccio-dynamodb",
"scope": "unscoped",
"version": "1.1.8",
"description": "Verdaccio DynamoDB Auth Plugin",
"keywords": ["aws", "auth-plugin", "verdaccio", "dynamodb", "verdaccio-plugin"],
"date": "2020-06-24T00:27:56.073Z",
"links": {
"npm": "https://www.npmjs.com/package/verdaccio-dynamodb",
"homepage": "https://github.com/pusherman/verdaccio-dynamodb#readme",
"repository": "https://github.com/pusherman/verdaccio-dynamodb",
"bugs": "https://github.com/pusherman/verdaccio-dynamodb/issues"
},
"author": {
"name": "Corey Wilson",
"email": "corey@eastcodes.com",
"username": "cwilson"
},
"publisher": {
"username": "cwilson",
"email": "corey@eastcodes.com"
},
"maintainers": [
{
"username": "cwilson",
"email": "corey@eastcodes.com"
}
]
},
{
"name": "@outcome-co/verdaccio-github-auth",
"scope": "outcome-co",
"version": "2.0.9",
"description": "Verdaccio Github Authentication Plugin",
"date": "2021-05-05T09:20:40.658Z",
"links": {
"npm": "https://www.npmjs.com/package/%40outcome-co%2Fverdaccio-github-auth",
"homepage": "https://github.com/outcome-co/verdaccio-github-auth-js",
"repository": "https://github.com/outcome-co/verdaccio-github-auth-js",
"bugs": "https://github.com/outcome-co/verdaccio-github-auth-js/issues"
},
"author": {
"name": "Outcome Engineering",
"email": "engineering@outcome.co",
"url": "https://outcome.co"
},
"publisher": {
"username": "d-tw",
"email": "douglas@outcome.co"
},
"maintainers": [
{
"username": "d-tw",
"email": "douglas@outcome.co"
}
]
},
{
"name": "verdaccio-bitbucket-server",
"scope": "unscoped",
"version": "1.3.1",
"description": "Verdaccio Authentication Plugin via Bitbucket Server",
"keywords": ["verdaccio", "verdaccio-plugin", "bitbucket", "bitbucket-server"],
"date": "2020-09-24T18:02:25.638Z",
"links": {
"npm": "https://www.npmjs.com/package/verdaccio-bitbucket-server",
"homepage": "https://github.com/oeph/verdaccio-bitbucket-server#readme",
"repository": "https://github.com/oeph/verdaccio-bitbucket-server",
"bugs": "https://github.com/oeph/verdaccio-bitbucket-server/issues"
},
"author": {
"name": "oeph"
},
"publisher": {
"username": "oeph",
"email": "npm@philippoeh.me"
},
"maintainers": [
{
"username": "oeph",
"email": "npm@philippoeh.me"
}
]
},
{
"name": "verdaccio-memory",
"scope": "unscoped",
"version": "10.0.0",
"description": "Storage implementation in memory",
"keywords": ["verdaccio", "plugin", "storage", "memory"],
"date": "2021-03-29T13:01:59.285Z",
"links": {
"npm": "https://www.npmjs.com/package/verdaccio-memory",
"homepage": "https://verdaccio.org"
},
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com",
"username": "jotadeveloper"
},
"publisher": {
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
"maintainers": [
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "ayusharma",
"email": "ayush.aceit@gmail.com"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
}
]
},
{
"name": "@verdaccio/types",
"scope": "verdaccio",
"version": "10.0.0",
"description": "verdaccio types definitions",
"keywords": ["verdaccio", "typescript", "types"],
"date": "2021-03-29T13:01:49.294Z",
"links": {
"npm": "https://www.npmjs.com/package/%40verdaccio%2Ftypes",
"homepage": "https://verdaccio.org",
"repository": "https://github.com/verdaccio/monorepo",
"bugs": "https://github.com/verdaccio/monorepo/issues"
},
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com",
"username": "jotadeveloper"
},
"publisher": {
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
"maintainers": [
{
"username": "sergiohgz",
"email": "sergio@sergiohgz.eu"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "ayusharma",
"email": "ayush.aceit@gmail.com"
}
]
},
{
"name": "verdaccio-auth-memory",
"scope": "unscoped",
"version": "10.0.0",
"description": "Auth plugin for Verdaccio that keeps users in memory",
"keywords": ["verdaccio", "plugin", "auth", "memory"],
"date": "2021-03-29T13:02:02.215Z",
"links": {
"npm": "https://www.npmjs.com/package/verdaccio-auth-memory",
"homepage": "https://verdaccio.org"
},
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com",
"username": "jotadeveloper"
},
"publisher": {
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
"maintainers": [
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "ayusharma",
"email": "ayush.aceit@gmail.com"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
}
]
},
{
"name": "generator-verdaccio-plugin",
"scope": "unscoped",
"version": "3.0.1",
"description": "plugin generator for verdaccio",
"keywords": ["verdaccio-plugin", "yeoman-generator"],
"date": "2020-12-23T10:31:29.150Z",
"links": {
"npm": "https://www.npmjs.com/package/generator-verdaccio-plugin",
"homepage": "https://github.com/verdaccio",
"repository": "https://github.com/verdaccio/generator-verdaccio-plugin",
"bugs": "https://github.com/verdaccio/generator-verdaccio-plugin/issues"
},
"author": {
"name": "Juan Picado",
"email": "@jotadeveloper",
"url": "https://github.com/verdaccio/generator-verdaccio-plugin"
},
"publisher": {
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
},
"maintainers": [
{
"username": "jotadeveloper",
"email": "juanpicado19@gmail.com"
},
{
"username": "verdaccio.npm",
"email": "verdaccio.npm@gmail.com"
}
]
},
{
"name": "verdaccio-minio",
"scope": "unscoped",
"version": "0.2.5",
"description": "A verdaccio plugin for storing data in Minio",
"keywords": ["Verdaccio", "S3", "Minio"],
"date": "2020-03-16T08:49:58.248Z",
"links": {
"npm": "https://www.npmjs.com/package/verdaccio-minio",
"homepage": "https://github.com/barolab/verdaccio-minio#readme",
"repository": "https://github.com/barolab/verdaccio-minio",
"bugs": "https://github.com/barolab/verdaccio-minio/issues"
},
"author": {
"name": "Romain Bailly",
"email": "rbailly17000@gmail.com",
"username": "barolab"
},
"publisher": {
"username": "barolab",
"email": "rbailly17000@gmail.com"
},
"maintainers": [
{
"username": "barolab",
"email": "rbailly17000@gmail.com"
}
]
}
]

View File

@@ -0,0 +1,348 @@
import path from 'path';
import nock from 'nock';
import * as httpMocks from 'node-mocks-http';
import { Config, parseConfigFile } from '@verdaccio/config';
import { ErrorCode } from '@verdaccio/utils';
import {
API_ERROR,
HEADERS,
HEADER_TYPE,
HTTP_STATUS,
VerdaccioError,
} from '@verdaccio/commons-api';
import { ProxyStorage } from '../src/up-storage';
const getConf = (name) => path.join(__dirname, '/conf', name);
const mockDebug = jest.fn();
const mockInfo = jest.fn();
const mockHttp = jest.fn();
const mockError = jest.fn();
const mockWarn = jest.fn();
jest.mock('@verdaccio/logger', () => {
const originalLogger = jest.requireActual('@verdaccio/logger');
return {
...originalLogger,
logger: {
child: () => ({
debug: (arg) => mockDebug(arg),
info: (arg) => mockInfo(arg),
http: (arg) => mockHttp(arg),
error: (arg) => mockError(arg),
warn: (arg) => mockWarn(arg),
}),
},
};
});
const domain = 'https://registry.npmjs.org';
describe('proxy', () => {
beforeEach(() => {
nock.cleanAll();
});
const defaultRequestOptions = {
url: 'https://registry.npmjs.org',
};
const proxyPath = getConf('proxy1.yaml');
const conf = new Config(parseConfigFile(proxyPath));
describe('search', () => {
test('get file from v1 endpoint', (done) => {
const url = '/-/v1/search';
nock(domain).get(url).replyWithFile(200, path.join(__dirname, 'partials/search-v1.json'));
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
const req = httpMocks.createRequest({
method: 'GET',
headers: {
referer: 'some.org',
['x-forwarded-for']: '10.0.0.1',
},
connection: {
remoteAddress: 'localhost',
},
url,
});
const stream = prox1.search({ req });
stream.on('data', (data) => {
expect(data).toBeDefined();
done();
});
});
test('abort search from v1 endpoint', (done) => {
const url = '/-/v1/search';
nock(domain).get(url).delay(20000);
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
const req = httpMocks.createRequest({
method: 'GET',
headers: {
referer: 'some.org',
['x-forwarded-for']: '10.0.0.1',
},
connection: {
remoteAddress: 'localhost',
},
url,
});
const stream = prox1.search({ req });
stream.on('end', () => {
done();
});
// TODO: apply correct types here
// @ts-ignore
stream.abort();
});
// TODO: we should test the gzip deflate here, but is hard to test
// fix me if you can deal with Incorrect Header Check issue
test.todo('get file from v1 endpoint with gzip headers');
test('search v1 endpoint fails', (done) => {
const url = '/-/v1/search';
nock(domain).get(url).replyWithError('search endpoint is down');
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
const req = httpMocks.createRequest({
method: 'GET',
headers: {
referer: 'some.org',
['x-forwarded-for']: '10.0.0.1',
},
connection: {
remoteAddress: 'localhost',
},
url,
});
const stream = prox1.search({ req });
stream.on('error', (error) => {
expect(error).toEqual(Error('search endpoint is down'));
done();
});
});
test('search v1 endpoint bad status code', (done) => {
const url = '/-/v1/search';
nock(domain).get(url).reply(409);
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
const req = httpMocks.createRequest({
method: 'GET',
headers: {
referer: 'some.org',
['x-forwarded-for']: '10.0.0.1',
},
connection: {
remoteAddress: 'localhost',
},
url,
});
const stream = prox1.search({ req });
stream.on('error', (error) => {
expect(error).toEqual(ErrorCode.getInternalError(`bad status code 409 from uplink`));
done();
});
});
});
describe('fetchTarball', () => {
test('get file tarball no content-length', (done) => {
nock(domain)
.get('/jquery/-/jquery-0.0.1.tgz')
.replyWithFile(201, path.join(__dirname, 'partials/jquery-0.0.1.tgz'));
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
const stream = prox1.fetchTarball('https://registry.npmjs.org/jquery/-/jquery-0.0.1.tgz');
stream.on('data', (data) => {
expect(data).toBeDefined();
done();
});
});
test('get file tarball correct content-length', (done) => {
nock(domain)
.get('/jquery/-/jquery-0.0.1.tgz')
// types does not match here with documentation
// @ts-expect-error
.replyWithFile(201, path.join(__dirname, 'partials/jquery-0.0.1.tgz'), {
[HEADER_TYPE.CONTENT_LENGTH]: 277,
});
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
const stream = prox1.fetchTarball('https://registry.npmjs.org/jquery/-/jquery-0.0.1.tgz');
stream.on(HEADER_TYPE.CONTENT_LENGTH, (data) => {
expect(data).toEqual('277');
done();
});
});
describe('error handling', () => {
test('should be offline uplink', (done) => {
const tarball = 'https://registry.npmjs.org/jquery/-/jquery-0.0.1.tgz';
nock(domain).get('/jquery/-/jquery-0.0.1.tgz').times(100).replyWithError('some error');
const proxy = new ProxyStorage(defaultRequestOptions, conf);
const stream = proxy.fetchTarball(tarball);
// to test a uplink is offline we have to be try 3 times
// the default failed request are set to 2
process.nextTick(function () {
stream.on('error', function (err) {
expect(err).not.toBeNull();
// expect(err.statusCode).toBe(404);
expect(proxy.failed_requests).toBe(1);
const streamSecondTry = proxy.fetchTarball(tarball);
streamSecondTry.on('error', function (err) {
expect(err).not.toBeNull();
/*
code: 'ENOTFOUND',
errno: 'ENOTFOUND',
*/
// expect(err.statusCode).toBe(404);
expect(proxy.failed_requests).toBe(2);
const streamThirdTry = proxy.fetchTarball(tarball);
streamThirdTry.on('error', function (err: VerdaccioError) {
expect(err).not.toBeNull();
expect(err.statusCode).toBe(HTTP_STATUS.INTERNAL_ERROR);
expect(proxy.failed_requests).toBe(2);
expect(err.message).toMatch(API_ERROR.UPLINK_OFFLINE);
done();
});
});
});
});
});
test('not found tarball', (done) => {
nock(domain).get('/jquery/-/jquery-0.0.1.tgz').reply(404);
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
const stream = prox1.fetchTarball('https://registry.npmjs.org/jquery/-/jquery-0.0.1.tgz');
stream.on('error', (response) => {
expect(response).toEqual(ErrorCode.getNotFound(API_ERROR.NOT_FILE_UPLINK));
done();
});
});
test('fail tarball request', (done) => {
nock(domain).get('/jquery/-/jquery-0.0.1.tgz').replyWithError('boom file');
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
const stream = prox1.fetchTarball('https://registry.npmjs.org/jquery/-/jquery-0.0.1.tgz');
stream.on('error', (response) => {
expect(response).toEqual(Error('boom file'));
done();
});
});
test('bad uplink request', (done) => {
nock(domain).get('/jquery/-/jquery-0.0.1.tgz').reply(409);
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
const stream = prox1.fetchTarball('https://registry.npmjs.org/jquery/-/jquery-0.0.1.tgz');
stream.on('error', (response) => {
expect(response).toEqual(ErrorCode.getInternalError(`bad uplink status code: 409`));
done();
});
});
test('content length header mismatch', (done) => {
nock(domain)
.get('/jquery/-/jquery-0.0.1.tgz')
// types does not match here with documentation
// @ts-expect-error
.replyWithFile(201, path.join(__dirname, 'partials/jquery-0.0.1.tgz'), {
[HEADER_TYPE.CONTENT_LENGTH]: 0,
});
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
const stream = prox1.fetchTarball('https://registry.npmjs.org/jquery/-/jquery-0.0.1.tgz');
stream.on('error', (response) => {
expect(response).toEqual(ErrorCode.getInternalError(API_ERROR.CONTENT_MISMATCH));
done();
});
});
});
});
describe('getRemoteMetadata', () => {
describe('basic requests', () => {
test('proxy call with etag', (done) => {
nock(domain)
.get('/jquery')
.reply(
200,
{ body: 'test' },
{
etag: () => `_ref_4444`,
}
);
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
prox1.getRemoteMetadata('jquery', {}, (_error, body, etag) => {
expect(etag).toEqual('_ref_4444');
expect(body).toEqual({ body: 'test' });
done();
});
});
test('proxy call with etag as option', (done) => {
nock(domain)
.get('/jquery')
.reply(
200,
{ body: 'test' },
{
etag: () => `_ref_4444`,
}
);
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
prox1.getRemoteMetadata('jquery', { etag: 'rev_3333' }, (_error, body, etag) => {
expect(etag).toEqual('_ref_4444');
expect(body).toEqual({ body: 'test' });
done();
});
});
test('proxy not found', (done) => {
nock(domain).get('/jquery').reply(404);
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
prox1.getRemoteMetadata('jquery', { etag: 'rev_3333' }, (error) => {
expect(error).toEqual(ErrorCode.getNotFound(API_ERROR.NOT_PACKAGE_UPLINK));
done();
});
});
});
describe('error handling', () => {
test('reply with error', (done) => {
nock(domain).get('/jquery').replyWithError('something awful happened');
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
prox1.getRemoteMetadata('jquery', {}, (error) => {
expect(error).toEqual(new Error('something awful happened'));
done();
});
});
test('reply with bad body json format', (done) => {
nock(domain).get('/jquery').reply(200, 'some-text');
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
prox1.getRemoteMetadata('jquery', {}, (error) => {
expect(error).toEqual(new SyntaxError('Unexpected token s in JSON at position 0'));
done();
});
});
test('400 error proxy call', (done) => {
nock(domain).get('/jquery').reply(409);
const prox1 = new ProxyStorage(defaultRequestOptions, conf);
prox1.getRemoteMetadata('jquery', {}, (error) => {
expect(error.statusCode).toEqual(500);
expect(mockInfo).toHaveBeenCalled();
expect(mockHttp).toHaveBeenCalledWith({
request: { method: 'GET', url: 'https://registry.npmjs.org/jquery' },
status: 409,
});
expect(mockHttp).toHaveBeenCalledWith({
bytes: { in: 0, out: 0 },
err: undefined,
error: undefined,
request: { method: 'GET', url: 'https://registry.npmjs.org/jquery' },
status: 409,
});
done();
});
});
});
});
});

View File

@@ -1,5 +1,19 @@
# @verdaccio/server
## 6.0.0-6-next.16
### Patch Changes
- Updated dependencies [d2c65da9]
- @verdaccio/utils@6.0.0-6-next.5
- @verdaccio/api@6.0.0-6-next.12
- @verdaccio/auth@6.0.0-6-next.9
- @verdaccio/config@6.0.0-6-next.7
- @verdaccio/middleware@6.0.0-6-next.9
- @verdaccio/store@6.0.0-6-next.10
- @verdaccio/web@6.0.0-6-next.15
- @verdaccio/loaders@6.0.0-6-next.4
## 6.0.0-6-next.15
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/server",
"version": "6.0.0-6-next.15",
"version": "6.0.0-6-next.16",
"description": "server logic",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -30,16 +30,16 @@
"npm": ">=6"
},
"dependencies": {
"@verdaccio/api": "workspace:6.0.0-6-next.11",
"@verdaccio/auth": "workspace:6.0.0-6-next.8",
"@verdaccio/api": "workspace:6.0.0-6-next.12",
"@verdaccio/auth": "workspace:6.0.0-6-next.9",
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/config": "workspace:6.0.0-6-next.6",
"@verdaccio/config": "workspace:6.0.0-6-next.7",
"@verdaccio/loaders": "workspace:6.0.0-6-next.4",
"@verdaccio/logger": "workspace:6.0.0-6-next.4",
"@verdaccio/middleware": "workspace:6.0.0-6-next.8",
"@verdaccio/store": "workspace:6.0.0-6-next.9",
"@verdaccio/utils": "workspace:6.0.0-6-next.4",
"@verdaccio/web": "workspace:6.0.0-6-next.14",
"@verdaccio/middleware": "workspace:6.0.0-6-next.9",
"@verdaccio/store": "workspace:6.0.0-6-next.10",
"@verdaccio/utils": "workspace:6.0.0-6-next.5",
"@verdaccio/web": "workspace:6.0.0-6-next.15",
"verdaccio-audit": "workspace:11.0.0-alpha.4",
"compression": "1.7.4",
"cors": "2.8.5",
@@ -48,8 +48,8 @@
"lodash": "4.17.15"
},
"devDependencies": {
"@verdaccio/mock": "workspace:6.0.0-6-next.6",
"@verdaccio/proxy": "workspace:6.0.0-6-next.8",
"@verdaccio/mock": "workspace:6.0.0-6-next.7",
"@verdaccio/proxy": "workspace:6.0.0-6-next.9",
"http-errors": "1.7.3",
"request": "2.87.0"
},

View File

@@ -1,259 +0,0 @@
import path from 'path';
import _ from 'lodash';
import { Config as AppConfig } from '@verdaccio/config';
import { Config, UpLinkConf } from '@verdaccio/types';
import { VerdaccioError } from '@verdaccio/commons-api';
import { IProxy } from '@verdaccio/proxy';
import { API_ERROR, HTTP_STATUS } from '@verdaccio/commons-api';
import { mockServer, configExample, DOMAIN_SERVERS } from '@verdaccio/mock';
import { ProxyStorage } from '@verdaccio/proxy';
import { setup, logger } from '@verdaccio/logger';
setup([]);
describe('UpStorge', () => {
const mockServerPort = 55547;
let mockRegistry;
const uplinkDefault = {
url: `http://0.0.0.0:${mockServerPort}`,
};
const generateProxy = (config: UpLinkConf = uplinkDefault) => {
const appConfig: Config = new AppConfig(configExample());
return new ProxyStorage(config, appConfig);
};
beforeAll(async () => {
const binPath = require.resolve('verdaccio/bin/verdaccio');
const storePath = path.join(__dirname, '/mock/store');
mockRegistry = await mockServer(mockServerPort, { storePath, silence: true }).init(binPath);
});
afterAll(function (done) {
const [registry, pid] = mockRegistry;
registry.stop();
logger.info(`registry ${pid} has been stopped`);
done();
});
test('should be defined', () => {
const proxy = generateProxy();
expect(proxy).toBeDefined();
});
describe('UpStorge::getRemoteMetadata', () => {
test('should be get remote metadata', (done) => {
const proxy = generateProxy();
proxy.getRemoteMetadata('jquery', {}, (err, data, etag) => {
expect(err).toBeNull();
expect(_.isString(etag)).toBeTruthy();
expect(data.name).toBe('jquery');
done();
});
});
test('should be get remote metadata with etag', (done) => {
const proxy = generateProxy();
proxy.getRemoteMetadata('jquery', { etag: '123456' }, (err, data, etag) => {
expect(err).toBeNull();
expect(_.isString(etag)).toBeTruthy();
expect(data.name).toBe('jquery');
done();
});
});
test('should be get remote metadata package does not exist', (done) => {
const proxy = generateProxy();
proxy.getRemoteMetadata('@verdaccio/fake-package', { etag: '123456' }, (err) => {
expect(err).not.toBeNull();
expect(err.statusCode).toBe(HTTP_STATUS.NOT_FOUND);
expect(err.message).toMatch(API_ERROR.NOT_PACKAGE_UPLINK);
done();
});
});
});
describe('UpStorge::fetchTarball', () => {
test('should fetch a tarball from uplink', (done) => {
const proxy = generateProxy();
const tarball = `http://${DOMAIN_SERVERS}:${mockServerPort}/jquery/-/jquery-1.5.1.tgz`;
const stream = proxy.fetchTarball(tarball);
stream.on('error', function (err) {
expect(err).toBeNull();
done();
});
stream.on('content-length', function (contentLength) {
expect(contentLength).toBeDefined();
done();
});
});
test('should throw a 404 on fetch a tarball from uplink', (done) => {
const proxy = generateProxy();
const tarball = `http://${DOMAIN_SERVERS}:${mockServerPort}/jquery/-/no-exist-1.5.1.tgz`;
const stream = proxy.fetchTarball(tarball);
stream.on('error', function (err: VerdaccioError) {
expect(err).not.toBeNull();
expect(err.statusCode).toBe(HTTP_STATUS.NOT_FOUND);
expect(err.message).toMatch(API_ERROR.NOT_FILE_UPLINK);
done();
});
stream.on('content-length', function (contentLength) {
expect(contentLength).toBeDefined();
done();
});
});
test('should be offline uplink', (done) => {
const proxy = generateProxy();
const tarball = 'http://404.verdaccioo.com';
const stream = proxy.fetchTarball(tarball);
expect(proxy.failed_requests).toBe(0);
// to test a uplink is offline we have to be try 3 times
// the default failed request are set to 2
process.nextTick(function () {
stream.on('error', function (err) {
expect(err).not.toBeNull();
// expect(err.statusCode).toBe(404);
expect(proxy.failed_requests).toBe(1);
const streamSecondTry = proxy.fetchTarball(tarball);
streamSecondTry.on('error', function (err) {
expect(err).not.toBeNull();
/*
code: 'ENOTFOUND',
errno: 'ENOTFOUND',
*/
// expect(err.statusCode).toBe(404);
expect(proxy.failed_requests).toBe(2);
const streamThirdTry = proxy.fetchTarball(tarball);
streamThirdTry.on('error', function (err: VerdaccioError) {
expect(err).not.toBeNull();
expect(err.statusCode).toBe(HTTP_STATUS.INTERNAL_ERROR);
expect(proxy.failed_requests).toBe(2);
expect(err.message).toMatch(API_ERROR.UPLINK_OFFLINE);
done();
});
});
});
});
});
});
describe('UpStorge::isUplinkValid', () => {
describe('valid use cases', () => {
const validateUpLink = (
url: string,
tarBallUrl = `${url}/artifactory/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz`
) => {
const uplinkConf = { url };
const proxy: IProxy = generateProxy(uplinkConf);
return proxy.isUplinkValid(tarBallUrl);
};
test('should validate tarball path against uplink', () => {
expect(validateUpLink('https://artifactory.mydomain.com')).toBe(true);
});
test('should validate tarball path against uplink case#2', () => {
expect(validateUpLink('https://artifactory.mydomain.com:443')).toBe(true);
});
test('should validate tarball path against uplink case#3', () => {
expect(validateUpLink('http://localhost')).toBe(true);
});
test('should validate tarball path against uplink case#4', () => {
expect(validateUpLink('http://my.domain.test')).toBe(true);
});
test('should validate tarball path against uplink case#5', () => {
expect(validateUpLink('http://my.domain.test:3000')).toBe(true);
});
// corner case https://github.com/verdaccio/verdaccio/issues/571
test('should validate tarball path against uplink case#6', () => {
// same protocol, same domain, port === 443 which is also the standard for https
expect(
validateUpLink(
'https://my.domain.test',
`https://my.domain.test:443/artifactory/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz`
)
).toBe(true);
});
test('should validate tarball path against uplink case#7', () => {
expect(validateUpLink('https://artifactory.mydomain.com:5569')).toBe(true);
});
test('should validate tarball path against uplink case#8', () => {
expect(validateUpLink('https://localhost:5539')).toBe(true);
});
});
describe('invalid use cases', () => {
test('should fails on validate tarball path against uplink', () => {
const url = 'https://artifactory.mydomain.com';
const tarBallUrl = 'https://localhost/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz';
const uplinkConf = { url };
const proxy: IProxy = generateProxy(uplinkConf);
expect(proxy.isUplinkValid(tarBallUrl)).toBe(false);
});
test('should fails on validate tarball path against uplink case#2', () => {
// different domain same, same port, same protocol
const url = 'https://domain';
const tarBallUrl = 'https://localhost/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz';
const uplinkConf = { url };
const proxy: IProxy = generateProxy(uplinkConf);
expect(proxy.isUplinkValid(tarBallUrl)).toBe(false);
});
test('should fails on validate tarball path against uplink case#3', () => {
// same domain, different protocol, different port
const url = 'http://localhost:5001';
const tarBallUrl = 'https://localhost:4000/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz';
const uplinkConf = { url };
const proxy: IProxy = generateProxy(uplinkConf);
expect(proxy.isUplinkValid(tarBallUrl)).toBe(false);
});
test('should fails on validate tarball path against uplink case#4', () => {
// same domain, same protocol, different port
const url = 'https://subdomain.domain:5001';
const tarBallUrl =
'https://subdomain.domain:4000/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz';
const uplinkConf = { url };
const proxy: IProxy = generateProxy(uplinkConf);
expect(proxy.isUplinkValid(tarBallUrl)).toBe(false);
});
test('should fails on validate tarball path against uplink case#5', () => {
// different protocol, different domain, different port
const url = 'https://subdomain.my:5001';
const tarBallUrl = 'http://subdomain.domain:4000/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz';
const uplinkConf = { url };
const proxy: IProxy = generateProxy(uplinkConf);
expect(proxy.isUplinkValid(tarBallUrl)).toBe(false);
});
});
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +0,0 @@
storage: ./storage
plugins: ./plugins
auth:
htpasswd:
file: ./htpasswd
security:
api:
jwt:
sign:
expiresIn: 10m
notBefore: 0
packages:
'@*/*':
access: $authenticated
publish: $authenticated
'**':
access: $authenticated
publish: $authenticated
logs:
- { type: stdout, format: pretty, level: warn }

View File

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

View File

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

View File

@@ -32,7 +32,7 @@
"homepage": "https://verdaccio.org",
"license": "MIT",
"devDependencies": {
"@verdaccio/cli": "workspace:6.0.0-6-next.16",
"@verdaccio/cli": "workspace:6.0.0-6-next.17",
"@verdaccio/ui-theme": "workspace:6.0.0-6-next.8",
"fs-extra": "9.0.1",
"webpack": "^5.11.1",

View File

@@ -1,5 +1,15 @@
# @verdaccio/store
## 6.0.0-6-next.10
### Patch Changes
- Updated dependencies [d2c65da9]
- @verdaccio/utils@6.0.0-6-next.5
- @verdaccio/config@6.0.0-6-next.7
- @verdaccio/proxy@6.0.0-6-next.9
- @verdaccio/loaders@6.0.0-6-next.4
## 6.0.0-6-next.9
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/store",
"version": "6.0.0-6-next.9",
"version": "6.0.0-6-next.10",
"description": "loaders logic",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -40,13 +40,13 @@
},
"dependencies": {
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/config": "workspace:6.0.0-6-next.6",
"@verdaccio/config": "workspace:6.0.0-6-next.7",
"@verdaccio/loaders": "workspace:6.0.0-6-next.4",
"@verdaccio/local-storage": "workspace:11.0.0-6-next.6",
"@verdaccio/logger": "workspace:6.0.0-6-next.4",
"@verdaccio/proxy": "workspace:6.0.0-6-next.8",
"@verdaccio/proxy": "workspace:6.0.0-6-next.9",
"@verdaccio/streams": "workspace:11.0.0-alpha.3",
"@verdaccio/utils": "workspace:6.0.0-6-next.4",
"@verdaccio/utils": "workspace:6.0.0-6-next.5",
"async": "3.1.1",
"debug": "^4.1.1",
"lodash": "4.17.15",
@@ -55,7 +55,7 @@
"semver": "7.1.2"
},
"devDependencies": {
"@verdaccio/mock": "workspace:6.0.0-6-next.6",
"@verdaccio/mock": "workspace:6.0.0-6-next.7",
"@verdaccio/types": "workspace:11.0.0-6-next.7"
},
"funding": {

View File

@@ -9,7 +9,7 @@ import { ProxyStorage } from '@verdaccio/proxy';
import { API_ERROR, HTTP_STATUS, DIST_TAGS } from '@verdaccio/commons-api';
import { ReadTarball } from '@verdaccio/streams';
import { ErrorCode, normalizeDistTags, validateMetadata, isObject } from '@verdaccio/utils';
import { setupUpLinks, updateVersionsHiddenUpLink, ProxyList, IProxy } from '@verdaccio/proxy';
import { ProxyList, IProxy } from '@verdaccio/proxy';
import {
IReadTarball,
IUploadTarball,
@@ -38,6 +38,7 @@ import { SearchInstance } from './search';
import { LocalStorage } from './local-storage';
import { mergeVersions } from './metadata-utils';
import { setupUpLinks, updateVersionsHiddenUpLink } from './uplink-util';
import {
checkPackageLocal,
publishPackage,
@@ -308,6 +309,7 @@ class Storage {
let uplink: any = null;
for (const uplinkId in self.uplinks) {
// https://github.com/verdaccio/verdaccio/issues/1642
if (hasProxyTo(name, uplinkId, self.config.packages)) {
uplink = self.uplinks[uplinkId];
}

View File

@@ -1,6 +1,6 @@
import { Versions, Config } from '@verdaccio/types';
import { ProxyStorage, IProxy, ProxyList } from './up-storage';
import { ProxyStorage, IProxy, ProxyList } from '@verdaccio/proxy';
/**
* Set up the Up Storage for each link.
@@ -27,7 +27,6 @@ export function updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy):
const version = versions[i];
// holds a "hidden" value to be used by the package storage.
// $FlowFixMe
version[Symbol.for('__verdaccio_uplink')] = upLink.upname;
}
}

View File

@@ -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"
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -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,
},
};

View File

@@ -1,5 +1,11 @@
# @verdaccio/utils
## 6.0.0-6-next.5
### Patch Changes
- d2c65da9: Fixed the validation of the name when searching for a tarball that have scoped package name
## 6.0.0-6-next.4
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/utils",
"version": "6.0.0-6-next.4",
"version": "6.0.0-6-next.5",
"description": "verdaccio utilities",
"main": "./build/index.js",
"types": "build/index.d.ts",

View File

@@ -25,8 +25,14 @@ export function validateName(name: string): boolean {
if (_.isString(name) === false) {
return false;
}
let normalizedName: string = name.toLowerCase();
const normalizedName: string = name.toLowerCase();
const isScoped: boolean = name.startsWith('@') && name.includes('/');
const scopedName = name.split('/', 2)[1];
if (isScoped && !_.isUndefined(scopedName)) {
normalizedName = scopedName.toLowerCase();
}
/**
* Some context about the first regex

View File

@@ -118,6 +118,7 @@ describe('Utilities', () => {
expect(validateName('old-package@0.1.2.tgz')).toBeTruthy();
// fix https://github.com/verdaccio/verdaccio/issues/1400
expect(validateName('-build-infra')).toBeTruthy();
expect(validateName('@pkg-scoped/without-extension')).toBeTruthy();
});
test('should be valid using uppercase', () => {

View File

@@ -1,5 +1,18 @@
# verdaccio
## 6.0.0-6-next.18
### Patch Changes
- Updated dependencies [d2c65da9]
- Updated dependencies [55ee3fdd]
- @verdaccio/utils@6.0.0-6-next.5
- @verdaccio/cli@6.0.0-6-next.17
- @verdaccio/mock@6.0.0-6-next.7
- @verdaccio/hooks@6.0.0-6-next.4
- @verdaccio/node-api@6.0.0-6-next.17
- @verdaccio/ui-theme@6.0.0-6-next.8
## 6.0.0-6-next.17
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "verdaccio",
"version": "6.0.0-6-next.17",
"version": "6.0.0-6-next.18",
"description": "A lightweight private npm proxy registry",
"main": "build/index.js",
"types": "build/index.d.ts",
@@ -36,21 +36,21 @@
},
"homepage": "https://verdaccio.org",
"dependencies": {
"@verdaccio/cli": "workspace:6.0.0-6-next.16",
"@verdaccio/cli": "workspace:6.0.0-6-next.17",
"@verdaccio/hooks": "workspace:6.0.0-6-next.4",
"@verdaccio/logger": "workspace:6.0.0-6-next.4",
"@verdaccio/mock": "workspace:6.0.0-6-next.6",
"@verdaccio/node-api": "workspace:6.0.0-6-next.16",
"@verdaccio/mock": "workspace:6.0.0-6-next.7",
"@verdaccio/node-api": "workspace:6.0.0-6-next.17",
"@verdaccio/ui-theme": "workspace:6.0.0-6-next.8",
"@verdaccio/utils": "workspace:6.0.0-6-next.4",
"@verdaccio/utils": "workspace:6.0.0-6-next.5",
"verdaccio-audit": "11.0.0-alpha.4",
"verdaccio-htpasswd": "11.0.0-alpha.6"
},
"devDependencies": {
"@verdaccio/auth": "workspace:6.0.0-6-next.8",
"@verdaccio/auth": "workspace:6.0.0-6-next.9",
"@verdaccio/commons-api": "workspace:11.0.0-alpha.3",
"@verdaccio/config": "workspace:6.0.0-6-next.6",
"@verdaccio/store": "workspace:6.0.0-6-next.9"
"@verdaccio/config": "workspace:6.0.0-6-next.7",
"@verdaccio/store": "workspace:6.0.0-6-next.10"
},
"keywords": [
"private",

View File

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

Some files were not shown because too many files have changed in this diff Show More