Compare commits

...

12 Commits

Author SHA1 Message Date
Juan Picado
d220e5b54b chore: update versions (next-8) (#5326)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-07-06 22:21:58 +02:00
Juan Picado
f8a321f03e fix: restore minimatch major version (#5325)
minimatch 10 requires ESM breaks 6.x old versions
2025-07-06 22:02:14 +02:00
Juan Picado
ac0fed3fa0 chore: update versions (next-8) (#5314)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-07-06 18:07:56 +02:00
renovate[bot]
f6c06fc982 fix(deps): update dependency dompurify to v3.2.6 (#5323)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-06 18:05:27 +02:00
Marc Bernard
d92ba65866 chore(proxy): update tests (#5320) 2025-07-06 17:44:08 +02:00
Juan Picado
6a4d6dddf7 feat: getListenAddress getConfigParsed methods (#5324) 2025-07-06 17:24:57 +02:00
Marc Bernard
73c0194091 chore(auth): typings (#5319) 2025-07-06 17:01:11 +02:00
verdacciobot
8a2bb51ba3 chore: updated static data 2025-07-03 00:17:00 +00:00
Marc Bernard
a1a73e9172 feat(logger): support redacting sensitive data (#5316)
* feat(logger): support redacting sensitive data

* Update config & docs
2025-06-30 06:47:51 +02:00
verdacciobot
6304965009 chore: updated static data 2025-06-30 00:17:29 +00:00
Marc Bernard
5fef0b629a chore(auth): multiple plugins test (#5312) 2025-06-29 12:00:34 +02:00
Marc Bernard
08e1b2137e chore(deps): built-in node imports (#5313) 2025-06-29 10:48:06 +02:00
157 changed files with 2875 additions and 1186 deletions

View File

@@ -0,0 +1,21 @@
---
'docusaurus-plugin-contributors': patch
'generator-verdaccio-plugin': patch
'@verdaccio/logger-prettify': patch
'@verdaccio/local-scripts': patch
'@verdaccio/file-locking': patch
'@verdaccio/ui-theme': patch
'@verdaccio/server-fastify': patch
'@verdaccio/test-helper': patch
'@verdaccio/middleware': patch
'verdaccio': patch
'@verdaccio/node-api': patch
'@verdaccio/config': patch
'@verdaccio/hooks': patch
'@verdaccio/proxy': patch
'@verdaccio/store': patch
'@verdaccio/auth': patch
'@verdaccio/api': patch
---
chore(deps): built-in node imports

View File

@@ -0,0 +1,7 @@
---
'@verdaccio/config': patch
'@verdaccio/logger-commons': patch
'@verdaccio/types': patch
---
feat(logger): support redacting sensitive data

View File

@@ -0,0 +1,7 @@
---
'@verdaccio/core': minor
'@verdaccio/node-api': minor
'@verdaccio/config': minor
---
feat: getListenAddress getConfigParsed methods

View File

@@ -74,6 +74,7 @@
"breezy-geckos-search",
"breezy-toys-judge",
"bright-bobcats-ring",
"bright-mugs-buy",
"brown-lions-talk",
"brown-planets-approve",
"calm-mangos-compare",
@@ -84,6 +85,7 @@
"clever-bees-happen",
"cool-balloons-search",
"cool-seals-watch",
"cuddly-paws-laugh",
"curly-mirrors-smile",
"curvy-rockets-camp",
"cyan-snakes-kiss",
@@ -106,6 +108,7 @@
"fuzzy-ears-yawn",
"gentle-stingrays-repeat",
"gold-files-speak",
"gold-parents-shave",
"gold-squids-watch",
"great-candles-hang",
"green-eagles-boil",
@@ -138,19 +141,23 @@
"poor-hats-smile",
"poor-queens-shop",
"popular-trees-grin",
"pretty-beds-destroy",
"proud-houses-switch",
"purple-planes-do",
"quick-avocados-type",
"quick-seas-deny",
"rare-mirrors-notice",
"real-balloons-travel",
"real-seahorses-change",
"red-dolls-repair",
"rotten-bananas-attend",
"rotten-melons-notice",
"rotton-readers-shave",
"rude-birds-design",
"rude-socks-walk",
"serious-apes-rule",
"seven-peas-obey",
"seven-suits-kneel",
"sharp-queens-rhyme",
"shiny-buttons-laugh",
"short-mails-smoke",

View File

@@ -0,0 +1,5 @@
---
'@verdaccio/core': patch
---
fix: restore minimatch major version

View File

@@ -0,0 +1,5 @@
---
'@verdaccio/auth': patch
---
chore(auth): typings

View File

@@ -0,0 +1,5 @@
---
'@verdaccio/auth': patch
---
chore(auth): multiple plugins test

View File

@@ -0,0 +1,5 @@
---
'@verdaccio/proxy': patch
---
chore(proxy): update tests

View File

@@ -68,7 +68,7 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-latest]
node_version: [18, 20, 21, 22, 23, 24]
node_version: [18, 20, 22, 24]
name: ${{ matrix.os }} / Node ${{ matrix.node_version }}
runs-on: ${{ matrix.os }}
steps:

View File

@@ -4,16 +4,16 @@
"version": "2.0.0-next-8.1",
"main": "src/index.ts",
"devDependencies": {
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"debug": "4.4.1",
"fs-extra": "11.2.0",
"get-port": "5.1.1",
"got": "11.8.6",
"js-yaml": "4.1.0",
"lodash": "4.17.21",
"verdaccio": "workspace:8.0.0-next-8.19"
"verdaccio": "workspace:8.0.0-next-8.21"
},
"scripts": {
"test": "echo no test",

View File

@@ -3,10 +3,10 @@
"name": "@verdaccio/e2e-ui",
"version": "2.0.0",
"devDependencies": {
"verdaccio": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/test-helper": "workspace:4.0.0-next-8.5",
"verdaccio": "workspace:8.0.0-next-8.21",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"@verdaccio/test-helper": "workspace:4.0.0-next-8.6",
"debug": "4.4.1",
"cypress": "^13.6.0",
"get-port": "5.1.1"

View File

@@ -1,5 +1,34 @@
# @verdaccio/api
## 8.1.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
- @verdaccio/auth@8.0.0-next-8.21
- @verdaccio/config@8.0.0-next-8.21
- @verdaccio/middleware@8.0.0-next-8.21
- @verdaccio/store@8.0.0-next-8.21
- @verdaccio/logger@8.0.0-next-8.21
## 8.1.0-next-8.20
### Patch Changes
- 08e1b21: chore(deps): built-in node imports
- Updated dependencies [08e1b21]
- Updated dependencies [a1a73e9]
- Updated dependencies [6a4d6dd]
- Updated dependencies [73c0194]
- Updated dependencies [5fef0b6]
- @verdaccio/middleware@8.0.0-next-8.20
- @verdaccio/config@8.0.0-next-8.20
- @verdaccio/store@8.0.0-next-8.20
- @verdaccio/auth@8.0.0-next-8.20
- @verdaccio/core@8.0.0-next-8.20
- @verdaccio/logger@8.0.0-next-8.20
## 8.1.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/api",
"version": "8.1.0-next-8.19",
"version": "8.1.0-next-8.21",
"description": "Verdaccio Registry API",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -42,12 +42,12 @@
},
"license": "MIT",
"dependencies": {
"@verdaccio/auth": "workspace:8.0.0-next-8.19",
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/logger": "workspace:8.0.0-next-8.19",
"@verdaccio/middleware": "workspace:8.0.0-next-8.19",
"@verdaccio/store": "workspace:8.0.0-next-8.19",
"@verdaccio/auth": "workspace:8.0.0-next-8.21",
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio/logger": "workspace:8.0.0-next-8.21",
"@verdaccio/middleware": "workspace:8.0.0-next-8.21",
"@verdaccio/store": "workspace:8.0.0-next-8.21",
"abortcontroller-polyfill": "1.7.8",
"body-parser": "1.20.3",
"cookies": "0.9.1",
@@ -58,8 +58,8 @@
"semver": "7.7.2"
},
"devDependencies": {
"@verdaccio/test-helper": "workspace:4.0.0-next-8.5",
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/test-helper": "workspace:4.0.0-next-8.6",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"mockdate": "3.0.5",
"supertest": "7.0.0"
},

View File

@@ -1,6 +1,6 @@
import { Application } from 'express';
import _ from 'lodash';
import path from 'path';
import path from 'node:path';
import supertest from 'supertest';
import { expect } from 'vitest';

View File

@@ -1,5 +1,5 @@
import nock from 'nock';
import { basename } from 'path';
import { basename } from 'node:path';
import supertest from 'supertest';
import { describe, expect, test } from 'vitest';

View File

@@ -1,7 +1,7 @@
/* eslint-disable curly */
// ensure that all arguments are validated
import fs from 'fs';
import path from 'path';
import fs from 'node:fs';
import path from 'node:path';
import { describe, expect, test } from 'vitest';
/**

View File

@@ -1,5 +1,32 @@
# @verdaccio/auth
## 8.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
- @verdaccio/config@8.0.0-next-8.21
- @verdaccio/loaders@8.0.0-next-8.11
- verdaccio-htpasswd@13.0.0-next-8.21
- @verdaccio/signature@8.0.0-next-8.13
## 8.0.0-next-8.20
### Patch Changes
- 08e1b21: chore(deps): built-in node imports
- 73c0194: chore(auth): typings
- 5fef0b6: chore(auth): multiple plugins test
- Updated dependencies [08e1b21]
- Updated dependencies [a1a73e9]
- Updated dependencies [6a4d6dd]
- @verdaccio/config@8.0.0-next-8.20
- @verdaccio/core@8.0.0-next-8.20
- verdaccio-htpasswd@13.0.0-next-8.20
- @verdaccio/loaders@8.0.0-next-8.10
- @verdaccio/signature@8.0.0-next-8.12
## 8.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/auth",
"version": "8.0.0-next-8.19",
"version": "8.0.0-next-8.21",
"description": "Verdaccio Authentication",
"main": "./build/index.js",
"types": "./build/index.d.ts",
@@ -42,18 +42,18 @@
},
"license": "MIT",
"dependencies": {
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/loaders": "workspace:8.0.0-next-8.9",
"@verdaccio/signature": "workspace:8.0.0-next-8.11",
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio/loaders": "workspace:8.0.0-next-8.11",
"@verdaccio/signature": "workspace:8.0.0-next-8.13",
"debug": "4.4.1",
"lodash": "4.17.21",
"verdaccio-htpasswd": "workspace:13.0.0-next-8.19"
"verdaccio-htpasswd": "workspace:13.0.0-next-8.21"
},
"devDependencies": {
"@verdaccio/middleware": "workspace:8.0.0-next-8.19",
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/logger": "workspace:8.0.0-next-8.19",
"@verdaccio/middleware": "workspace:8.0.0-next-8.21",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"@verdaccio/logger": "workspace:8.0.0-next-8.21",
"express": "4.21.2",
"supertest": "7.0.0"
},

View File

@@ -1,5 +1,5 @@
import buildDebug from 'debug';
import _, { isFunction } from 'lodash';
import _ from 'lodash';
import { HTPasswd } from 'verdaccio-htpasswd';
import { TOKEN_VALID_LENGTH, createAnonymousRemoteUser, createRemoteUser } from '@verdaccio/config';
@@ -73,7 +73,7 @@ class Auth implements IAuthMiddleware, TokenEncryption, pluginUtils.IBasicAuth {
}
public async init() {
let plugins = (await this.loadPlugin()) as pluginUtils.Auth<unknown>[];
let plugins = await this.loadPlugin();
debug('auth plugins found %s', plugins.length);
if (!plugins || plugins.length === 0) {
@@ -86,15 +86,14 @@ class Auth implements IAuthMiddleware, TokenEncryption, pluginUtils.IBasicAuth {
private loadDefaultPlugin() {
debug('load default auth plugin');
const pluginOptions: pluginUtils.PluginOptions = {
config: this.config,
logger: this.logger,
};
let authPlugin;
try {
authPlugin = new HTPasswd(
{ file: './htpasswd' },
pluginOptions as any as pluginUtils.PluginOptions
{
config: this.config,
logger: this.logger,
}
);
this.logger.info(
{ name: 'verdaccio-htpasswd', pluginCategory: PLUGIN_CATEGORY.AUTHENTICATION },
@@ -110,7 +109,7 @@ class Auth implements IAuthMiddleware, TokenEncryption, pluginUtils.IBasicAuth {
}
private async loadPlugin() {
return asyncLoadPlugin<pluginUtils.Auth<unknown>>(
return asyncLoadPlugin<pluginUtils.Auth<Config>>(
this.config.auth,
{
config: this.config,
@@ -184,9 +183,9 @@ class Auth implements IAuthMiddleware, TokenEncryption, pluginUtils.IBasicAuth {
): void {
const plugins = this.plugins.slice(0);
(function next(): void {
const plugin = plugins.shift() as pluginUtils.Auth<Config>;
const plugin = plugins.shift();
if (isFunction(plugin.authenticate) === false) {
if (typeof plugin?.authenticate !== 'function') {
return next();
}
@@ -233,7 +232,7 @@ class Auth implements IAuthMiddleware, TokenEncryption, pluginUtils.IBasicAuth {
(function next(): void {
let method = 'adduser';
const plugin = plugins.shift() as pluginUtils.Auth<Config>;
const plugin = plugins.shift();
// @ts-expect-error future major (7.x) should remove this section
if (typeof plugin.adduser === 'undefined' && typeof plugin.add_user === 'function') {
method = 'add_user';
@@ -283,9 +282,9 @@ class Auth implements IAuthMiddleware, TokenEncryption, pluginUtils.IBasicAuth {
debug('allow access for %o', packageName);
(function next(): void {
const plugin: pluginUtils.Auth<unknown> = plugins.shift() as pluginUtils.Auth<unknown>;
const plugin = plugins.shift();
if (_.isNil(plugin) || isFunction(plugin.allow_access) === false) {
if (typeof plugin?.allow_access !== 'function') {
return next();
}
@@ -321,7 +320,7 @@ class Auth implements IAuthMiddleware, TokenEncryption, pluginUtils.IBasicAuth {
debug('allow unpublish for %o plugin does not implement allow_unpublish', packageName);
continue;
} else {
plugin.allow_unpublish(user, pkg, (err, ok): void => {
plugin.allow_unpublish(user, pkg, (err: VerdaccioError | null, ok?: boolean): void => {
if (err) {
debug(
'forbidden publish for %o, it will fallback on unpublish permissions',

View File

@@ -1,5 +1,5 @@
import _ from 'lodash';
import path from 'path';
import path from 'node:path';
import { describe, expect, test, vi } from 'vitest';
import {

View File

@@ -1,5 +1,5 @@
import _ from 'lodash';
import path from 'path';
import path from 'node:path';
import { describe, expect, test, vi } from 'vitest';
import {

View File

@@ -1,5 +1,5 @@
import express from 'express';
import path from 'path';
import path from 'node:path';
import supertest from 'supertest';
import { describe, expect, test, vi } from 'vitest';
@@ -198,29 +198,52 @@ describe('AuthTest', () => {
});
});
describe('test multiple authenticate methods', () => {
test('should skip falsy values', async () => {
const config: Config = new AppConfig({
...getDefaultConfig(),
plugins: path.join(__dirname, './partials/plugin'),
auth: {
success: {},
'fail-invalid-method': {},
},
});
config.checkSecretKey('12345');
const auth: Auth = new Auth(config, logger);
await auth.init();
test('should success first plugin, ignore subsequent plugins', async () => {
const config: Config = new AppConfig({
...getDefaultConfig(),
plugins: path.join(__dirname, './partials/plugin'),
auth: {
success: {},
'no-access': {},
},
});
config.checkSecretKey('12345');
const auth: Auth = new Auth(config, logger);
await auth.init();
return new Promise((resolve) => {
auth.authenticate('foo', 'bar', (err, value) => {
expect(value).toEqual({
name: 'foo',
groups: ['test', ROLES.$ALL, '$authenticated', '@all', '@authenticated', 'all'],
real_groups: ['test'],
});
resolve(value);
return new Promise((resolve) => {
auth.authenticate('foo', 'bar', (err, value) => {
expect(value).toEqual({
name: 'foo',
groups: ['test', ROLES.$ALL, '$authenticated', '@all', '@authenticated', 'all'],
real_groups: ['test'],
});
resolve(value);
});
});
});
test('should fail first plugin, success second plugin', async () => {
const config: Config = new AppConfig({
...getDefaultConfig(),
plugins: path.join(__dirname, './partials/plugin'),
auth: {
'no-access': {},
success: {},
},
});
config.checkSecretKey('12345');
const auth: Auth = new Auth(config, logger);
await auth.init();
return new Promise((resolve) => {
auth.authenticate('foo', 'bar', (err, value) => {
expect(value).toEqual({
name: 'foo',
groups: ['test', ROLES.$ALL, '$authenticated', '@all', '@authenticated', 'all'],
real_groups: ['test'],
});
resolve(value);
});
});
});

View File

@@ -1,4 +1,4 @@
import path from 'path';
import path from 'node:path';
import { getDefaultConfig } from '@verdaccio/config';

View File

@@ -0,0 +1,8 @@
module.exports = function () {
return {
authenticate(user, pass, callback) {
// no access but also no error
callback(null, false);
},
};
};

View File

@@ -0,0 +1,5 @@
{
"name": "verdaccio-no-access",
"main": "no-access.js",
"version": "1.0.0"
}

View File

@@ -1,5 +1,27 @@
# @verdaccio/cli
## 8.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
- @verdaccio/config@8.0.0-next-8.21
- @verdaccio/node-api@8.0.0-next-8.21
- @verdaccio/logger@8.0.0-next-8.21
## 8.0.0-next-8.20
### Patch Changes
- Updated dependencies [08e1b21]
- Updated dependencies [a1a73e9]
- Updated dependencies [6a4d6dd]
- @verdaccio/node-api@8.0.0-next-8.20
- @verdaccio/config@8.0.0-next-8.20
- @verdaccio/core@8.0.0-next-8.20
- @verdaccio/logger@8.0.0-next-8.20
## 8.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/cli",
"version": "8.0.0-next-8.19",
"version": "8.0.0-next-8.21",
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com"
@@ -47,10 +47,10 @@
"start": "ts-node src/index.ts"
},
"dependencies": {
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/logger": "workspace:8.0.0-next-8.19",
"@verdaccio/node-api": "workspace:8.0.0-next-8.19",
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio/logger": "workspace:8.0.0-next-8.21",
"@verdaccio/node-api": "workspace:8.0.0-next-8.21",
"clipanion": "4.0.0-rc.4",
"envinfo": "7.14.0",
"kleur": "4.1.5",

View File

@@ -1,5 +1,25 @@
# @verdaccio/config
## 8.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
## 8.0.0-next-8.20
### Minor Changes
- 6a4d6dd: feat: getListenAddress getConfigParsed methods
### Patch Changes
- 08e1b21: chore(deps): built-in node imports
- a1a73e9: feat(logger): support redacting sensitive data
- Updated dependencies [6a4d6dd]
- @verdaccio/core@8.0.0-next-8.20
## 8.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/config",
"version": "8.0.0-next-8.19",
"version": "8.0.0-next-8.21",
"description": "Verdaccio Configuration",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -42,7 +42,7 @@
"build": "pnpm run build:js && pnpm run build:types"
},
"dependencies": {
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"debug": "4.4.1",
"js-yaml": "4.1.0",
"lodash": "4.17.21",

View File

@@ -0,0 +1,136 @@
import createDebug from 'debug';
import { DEFAULT_DOMAIN, DEFAULT_PORT, DEFAULT_PROTOCOL } from '@verdaccio/core';
import { Logger } from '@verdaccio/types';
const debug = createDebug('verdaccio:config:address');
export interface ListenAddress {
proto: string;
host?: string;
port?: string;
path?: string;
}
/**
* Parse an internet address
* Allow:
- https:localhost:1234 - protocol + host + port
- localhost:1234 - host + port
- 1234 - port
- http::1234 - protocol + port
- https://localhost:443/ - full url + https
- http://[::1]:443/ - ipv6
- unix:/tmp/http.sock - unix sockets
- https://unix:/tmp/http.sock - unix sockets (https)
* @param {*} urlAddress the internet address definition
* @return {Object|Null} literal object that represent the address parsed
*/
export function parseAddress(urlAddress: string): ListenAddress | null {
//
// TODO: refactor it to something more reasonable?
//
// protocol : // ( host )|( ipv6 ): port /
const urlPattern = /^((https?):(\/\/)?)?((([^\/:]*)|\[([^\[\]]+)\]):)?(\d+)\/?$/.exec(urlAddress);
if (urlPattern) {
return {
proto: urlPattern[2] || DEFAULT_PROTOCOL,
host: urlPattern[6] || urlPattern[7] || DEFAULT_DOMAIN,
port: urlPattern[8] || DEFAULT_PORT,
};
}
const unixPattern = /^(?:(https?):\/\/)?unix:(\/.*)$/.exec(urlAddress);
if (!unixPattern) {
// if we cannot match the unix pattern, we return null
// this is to avoid returning a wrong object
return null;
}
return {
host: unixPattern[2],
proto: unixPattern[1] || 'unix',
path: unixPattern[2],
};
}
function addrToString(a: ListenAddress): string {
return a.proto === 'unix' ? `unix:${a.host}` : `${a.proto}://${a.host}:${a.port}`;
}
/**
* Retrieve all addresses defined in the config file.
* Verdaccio is able to listen multiple ports
* @param {String} argListen
* @param {String} configListen
* eg:
* listen:
- localhost:5555
- localhost:5557
@return {Array}
*/
export function getListenAddress(listen: (string | void)[], logger: Logger): ListenAddress {
debug('getListenAddress called with %o', listen);
if (!listen) {
debug('No listen address provided, using default');
return { proto: DEFAULT_PROTOCOL, host: DEFAULT_DOMAIN, port: DEFAULT_PORT };
}
if (Array.isArray(listen)) {
const filteredListen = listen.filter((item) => typeof item === 'string');
if (filteredListen.length === 0) {
throw new Error('Listen addresses array cannot be empty');
}
const invalid: string[] = [];
for (const raw of filteredListen) {
const candidate = parseAddress(raw as string);
if (candidate) {
debug('valid listen address found: %o', candidate);
invalid.forEach((bad) =>
logger.warn(
{ addr: bad },
'invalid address - @{addr}, we expect a port (e.g. "4873"), ' +
'host:port (e.g. "localhost:4873"), full url ' +
'(e.g. "http://localhost:4873/") or unix:/path/socket'
)
);
if (listen.length > 1) {
logger.warn(
`Multiple listen addresses are not supported, using the first valid one ${addrToString(
candidate
)}`
);
}
return candidate;
}
invalid.push(raw as string);
}
invalid.forEach((bad) =>
logger.warn(
{ addr: bad },
'invalid address - @{addr}, we expect a port (e.g. "4873"), ' +
'host:port (e.g. "localhost:4873"), full url ' +
'(e.g. "http://localhost:4873/") or unix:/path/socket'
)
);
throw new Error('No valid listen addresses found in configuration array');
}
const single = parseAddress(listen);
if (!single) {
throw new Error(
`Invalid address - ${listen}, we expect a port (e.g. "4873"), ` +
`host:port (e.g. "localhost:4873"), full url ` +
`(e.g. "http://localhost:4873/") or unix:/path/socket`
);
}
return single;
}

View File

@@ -210,7 +210,16 @@ middlewares:
# Log settings
# https://verdaccio.org/docs/logger
log: { type: stdout, format: pretty, level: http }
# Redaction: https://getpino.io/#/docs/redaction
# Synchronous logging: https://getpino.io/#/docs/asynchronous
log:
type: stdout
format: pretty
level: http
# redact:
# paths: ['req.header.authorization','req.header.cookie','req.remoteAddress','req.remotePort','ip','remoteIP','user','msg']
# censor: '<redacted>'
# sync: true
# Feature flags (experimental settings that can be changed or removed in the future)
# https://verdaccio.org/docs/configuration#experiments

View File

@@ -210,7 +210,16 @@ middlewares:
# Log settings
# https://verdaccio.org/docs/logger
log: { type: stdout, format: pretty, level: http }
# Redaction: https://getpino.io/#/docs/redaction
# Synchronous logging: https://getpino.io/#/docs/asynchronous
log:
type: stdout
format: pretty
level: http
# redact:
# paths: ['req.header.authorization','req.header.cookie','req.remoteAddress','req.remotePort','ip','remoteIP','user','msg']
# censor: '<redacted>'
# sync: true
# Feature flags (experimental settings that can be changed or removed in the future)
# https://verdaccio.org/docs/configuration#experiments

View File

@@ -1,8 +1,8 @@
import { join } from 'path';
import { join } from 'node:path';
import { parseConfigFile } from '../parse';
export function getDefaultConfig(fileName = 'default.yaml') {
export function getDefaultConfig(fileName: string = 'default.yaml') {
const file = join(__dirname, `./${fileName}`);
return parseConfigFile(file);
}

View File

@@ -1,8 +1,8 @@
import buildDebug from 'debug';
import fs from 'fs';
import _ from 'lodash';
import os from 'os';
import path from 'path';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { fileExists, folderExists } from './config-utils';

View File

@@ -1,5 +1,5 @@
import buildDebug from 'debug';
import fs from 'fs';
import fs from 'node:fs';
const debug = buildDebug('verdaccio:config:config-utils');

View File

@@ -1,6 +1,6 @@
import assert from 'assert';
import buildDebug from 'debug';
import _ from 'lodash';
import assert from 'node:assert';
import { APP_ERROR, authUtils, cryptoUtils, validationUtils, warningUtils } from '@verdaccio/core';
import { Codes } from '@verdaccio/core/build/warning-utils';

View File

@@ -3,10 +3,11 @@ export * from './config-path';
export * from './token';
export * from './config-utils';
export * from './package-access';
export { fromJStoYAML, parseConfigFile } from './parse';
export { fromJStoYAML, parseConfigFile, getConfigParsed } from './parse';
export * from './uplinks';
export * from './security';
export * from './agent';
export * from './user';
export { default as ConfigBuilder } from './builder';
export { getDefaultConfig } from './conf';
export * from './address';

View File

@@ -1,6 +1,6 @@
import assert from 'assert';
import buildDebug from 'debug';
import _ from 'lodash';
import assert from 'node:assert';
import { errorUtils } from '@verdaccio/core';
import { PackageAccess } from '@verdaccio/types';

View File

@@ -1,11 +1,13 @@
import buildDebug from 'debug';
import fs from 'fs';
import YAML from 'js-yaml';
import { isObject } from 'lodash';
import fs from 'node:fs';
import path from 'node:path';
import { APP_ERROR } from '@verdaccio/core';
import { API_ERROR, APP_ERROR } from '@verdaccio/core';
import { ConfigYaml } from '@verdaccio/types';
import { findConfigFile } from './config-path';
import { fileExists } from './config-utils';
const debug = buildDebug('verdaccio:config:parse');
@@ -61,3 +63,48 @@ export function fromJStoYAML(config: Partial<ConfigYaml>): string | null {
throw new Error(`config is not a valid object`);
}
}
/**
* Parses and returns a configuration object of type `ConfigYaml`.
*
* If a string or `undefined` is provided, it is interpreted as a path to a config file
* (or uses a default location). The config file is then loaded and parsed.
* If an object is provided, it is assumed to be a pre-parsed configuration.
* Backward compability: ensures the returned configuration object has a `self_path` property set,
* either to the config file path or to a property within the object.
*
* @param {string | ConfigYaml} [config] - Optional. A path to the configuration file (string),
* a pre-parsed config object, or `undefined`.
* @returns {ConfigYaml} The parsed configuration object with a guaranteed `self_path` property.
* @throws {Error} If the provided config is neither a string, undefined, nor an object.
*/
export function getConfigParsed(config?: string | ConfigYaml): ConfigYaml {
debug('getConfigParsed called with config: %o', typeof config);
let configurationParsed: ConfigYaml;
if (config === undefined || typeof config === 'string') {
debug('using default configuration');
const configPathLocation = findConfigFile(config);
configurationParsed = parseConfigFile(configPathLocation);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
if (!configurationParsed.self_path) {
debug('self_path not defined, using config path location');
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
configurationParsed.self_path = path.resolve(configPathLocation);
}
} else if (typeof config === 'object' && config !== null) {
configurationParsed = config;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
if (!configurationParsed.self_path) {
debug('self_path not defined, using config path location');
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
configurationParsed.self_path = configurationParsed.configPath;
}
} else {
throw new Error(API_ERROR.CONFIG_BAD_FORMAT);
}
return configurationParsed;
}

View File

@@ -1,4 +1,4 @@
import { randomBytes } from 'crypto';
import { randomBytes } from 'node:crypto';
export const TOKEN_VALID_LENGTH = 32;

View File

@@ -1,5 +1,5 @@
import assert from 'assert';
import _ from 'lodash';
import assert from 'node:assert';
import { authUtils } from '@verdaccio/core';
import { PackageList, UpLinksConfList } from '@verdaccio/types';

View File

@@ -0,0 +1,209 @@
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { Logger } from '@verdaccio/types';
import { getListenAddress, parseAddress } from '../src';
const logger: Logger = {
warn: vi.fn(),
error: vi.fn(),
} as any;
describe('address parsing', () => {
describe('getListenAddress', () => {
const warn = logger.warn as unknown as ReturnType<typeof vi.fn>;
beforeEach(() => {
vi.clearAllMocks();
});
test('returns a parsed object for a simple port', () => {
const addr = getListenAddress('4873', logger);
expect(addr).toEqual({
proto: 'http',
host: 'localhost',
port: '4873',
});
expect(warn).not.toHaveBeenCalled();
});
test('throws when the single string is invalid', () => {
expect(() => getListenAddress('not_valid', logger)).toThrow(/Invalid address/i);
expect(warn).not.toHaveBeenCalled();
});
test('uses the first valid element and warns about the rest', () => {
const addr = getListenAddress(['bad', 'http://localhost:4873', 'unix:/tmp/x.sock'], logger);
expect(addr).toEqual({
proto: 'http',
host: 'localhost',
port: '4873',
});
expect(warn).toHaveBeenCalledTimes(2);
// expect(warn.mock.calls[0][0]).toMatchObject({ addr: 'bad' });
expect(warn.mock.calls[1][0]).toMatch(/Multiple listen addresses/i);
});
test('throws if every element in the array is invalid', () => {
expect(() => getListenAddress(['bad1', 'also_bad'], logger)).toThrow(
/No valid listen addresses/i
);
// two warnings, one per invalid element
expect(warn).toHaveBeenCalledTimes(2);
});
test('throws when given an empty array', () => {
expect(() => getListenAddress([])).toThrow(/array cannot be empty/i);
expect(warn).not.toHaveBeenCalled();
});
test('localhost:4873 (default value)', () => {
const addr = getListenAddress('localhost:4873');
expect(addr).toEqual({ proto: 'http', host: 'localhost', port: '4873' });
expect(warn).not.toHaveBeenCalled();
});
test('http://localhost:4873 (explicit protocol)', () => {
const addr = getListenAddress('http://localhost:4873', logger);
expect(addr).toEqual({ proto: 'http', host: 'localhost', port: '4873' });
expect(warn).not.toHaveBeenCalled();
});
test('0.0.0.0:4873 (INADDR_ANY)', () => {
const addr = getListenAddress('0.0.0.0:4873', logger);
expect(addr).toEqual({ proto: 'http', host: '0.0.0.0', port: '4873' });
expect(warn).not.toHaveBeenCalled();
});
test('https://example.org:4873 (TLS)', () => {
const addr = getListenAddress('https://example.org:4873', logger);
expect(addr).toEqual({ proto: 'https', host: 'example.org', port: '4873' });
expect(warn).not.toHaveBeenCalled();
});
test('"[::1]:4873" (IPv6)', () => {
const addr = getListenAddress('[::1]:4873', logger);
/* parseAddress collapses brackets & assigns proto http */
expect(addr).toEqual({ proto: 'http', host: '::1', port: '4873' });
expect(warn).not.toHaveBeenCalled();
});
test('"https:[::1]:4873" (IPv6)', () => {
const addr = getListenAddress('https:[::1]:4873', logger);
/* parseAddress collapses brackets & assigns proto http */
expect(addr).toEqual({ proto: 'https', host: '::1', port: '4873' });
expect(warn).not.toHaveBeenCalled();
});
test('unix:/tmp/verdaccio.sock (Unix socket)', () => {
const addr = getListenAddress('unix:/tmp/verdaccio.sock', logger);
expect(addr).toEqual({
proto: 'unix',
path: '/tmp/verdaccio.sock',
host: '/tmp/verdaccio.sock',
});
expect(warn).not.toHaveBeenCalled();
});
test('http://foo.sock:34 (Unix socket)', () => {
const addr = getListenAddress('http://foo.sock:34', logger);
expect(addr).toEqual({
host: 'foo.sock',
port: '34',
proto: 'http',
});
expect(warn).not.toHaveBeenCalled();
});
test('http://unix:/tmp/verdaccio.sock (HTTP Unix socket)', () => {
const addr = getListenAddress('http://unix:/tmp/verdaccio.sock', logger);
expect(addr).toEqual({
path: '/tmp/verdaccio.sock',
proto: 'http',
host: '/tmp/verdaccio.sock',
});
expect(warn).not.toHaveBeenCalled();
});
test('https://unix:/tmp/verdaccio.sock (HTTPS Unix socket)', () => {
const addr = getListenAddress('https://unix:/tmp/verdaccio.sock', logger);
expect(addr).toEqual({
path: '/tmp/verdaccio.sock',
proto: 'https',
host: '/tmp/verdaccio.sock',
});
expect(warn).not.toHaveBeenCalled();
});
});
describe('parseAddress documented listen values', () => {
test('localhost:4873 (default style)', () => {
expect(parseAddress('localhost:4873')).toEqual({
proto: 'http',
host: 'localhost',
port: '4873',
});
});
test('http://localhost:4873 (explicit protocol)', () => {
expect(parseAddress('http://localhost:4873')).toEqual({
proto: 'http',
host: 'localhost',
port: '4873',
});
});
test('0.0.0.0:4873 (INADDR_ANY)', () => {
expect(parseAddress('0.0.0.0:4873')).toEqual({
proto: 'http',
host: '0.0.0.0',
port: '4873',
});
});
test('https://example.org:4873 (HTTPS)', () => {
expect(parseAddress('https://example.org:4873')).toEqual({
proto: 'https',
host: 'example.org',
port: '4873',
});
});
test('"[::1]:4873" (IPv6)', () => {
expect(parseAddress('[::1]:4873')).toEqual({
proto: 'http',
host: '::1',
port: '4873',
});
});
test('unix:/tmp/verdaccio.sock (Unix socket)', () => {
expect(parseAddress('unix:/tmp/verdaccio.sock')).toEqual({
host: '/tmp/verdaccio.sock',
proto: 'unix',
path: '/tmp/verdaccio.sock',
});
});
test('https://unix:/tmp/verdaccio.sock (HTTPS Unix socket)', () => {
expect(parseAddress('https://unix:/tmp/verdaccio.sock')).toEqual({
host: '/tmp/verdaccio.sock',
proto: 'https',
path: '/tmp/verdaccio.sock',
});
});
});
});

View File

@@ -1,5 +1,5 @@
import fs from 'fs';
import path from 'path';
import fs from 'node:fs';
import path from 'node:path';
import { describe, expect, test } from 'vitest';
import { fileUtils } from '@verdaccio/core';

View File

@@ -1,4 +1,4 @@
import path from 'path';
import path from 'node:path';
import { describe, expect, test } from 'vitest';
import { fileExists, folderExists } from '../src/config-utils';

View File

@@ -1,5 +1,5 @@
import fs from 'fs';
import os from 'os';
import fs from 'node:fs';
import os from 'node:os';
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
import { findConfigFile } from '../src/config-path';

View File

@@ -1,5 +1,5 @@
import _ from 'lodash';
import path from 'path';
import path from 'node:path';
import { describe, expect, test } from 'vitest';
import {

View File

@@ -0,0 +1,27 @@
import path from 'node:path';
import { describe, expect, test } from 'vitest';
import { getConfigParsed, parseConfigFile } from '../src';
describe('getConfigParsed', () => {
const partialsDir = path.join(__dirname, './partials/config/yaml');
test('parses config from a YAML file path', () => {
const yamlFile = path.join(partialsDir, 'config-getMatchedPackagesSpec.yaml');
const config = getConfigParsed(yamlFile);
expect(config).toBeDefined();
});
test('parses config from a YAML file path', () => {
const yamlFile = path.join(partialsDir, 'config-getMatchedPackagesSpec.yaml');
const config = getConfigParsed(parseConfigFile(yamlFile));
expect(config).toBeDefined();
});
test('throws error for invalid config type', () => {
// @ts-expect-error
expect(() => getConfigParsed(123)).toThrow();
// @ts-expect-error
expect(() => getConfigParsed(true)).toThrow();
});
});

View File

@@ -1,4 +1,4 @@
import path from 'path';
import path from 'node:path';
export const parseConfigurationFile = (conf: string) => {
const { name, ext } = path.parse(conf);

View File

@@ -1,5 +1,17 @@
# @verdaccio/core
## 8.0.0-next-8.21
### Patch Changes
- f8a321f: fix: restore minimatch major version
## 8.0.0-next-8.20
### Minor Changes
- 6a4d6dd: feat: getListenAddress getConfigParsed methods
## 8.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/core",
"version": "8.0.0-next-8.19",
"version": "8.0.0-next-8.21",
"description": "Verdaccio Core Components",
"keywords": [
"private",
@@ -36,12 +36,12 @@
"ajv": "8.17.1",
"http-errors": "2.0.0",
"http-status-codes": "2.3.0",
"minimatch": "10.0.1",
"minimatch": "7.4.6",
"process-warning": "1.0.0",
"semver": "7.7.2"
},
"devDependencies": {
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"express": "4.21.2",
"typedoc": "0.23.25",
"vitest": "3.0.4"

View File

@@ -163,3 +163,7 @@ export const PLUGIN_CATEGORY = {
FILTER: 'filter',
THEME: 'theme',
};
export const DEFAULT_PORT = '4873';
export const DEFAULT_PROTOCOL = 'http';
export const DEFAULT_DOMAIN = 'localhost';

View File

@@ -31,6 +31,9 @@ export {
PLUGIN_PREFIX,
PLUGIN_UI_PREFIX,
HtpasswdHashAlgorithm,
DEFAULT_DOMAIN,
DEFAULT_PORT,
DEFAULT_PROTOCOL,
} from './constants';
export {
authUtils,

View File

@@ -1,5 +1,11 @@
# Change Log
## 13.0.0-next-8.5
### Patch Changes
- 08e1b21: chore(deps): built-in node imports
## 13.0.0-next-8.4
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/file-locking",
"version": "13.0.0-next-8.4",
"version": "13.0.0-next-8.5",
"description": "Verdaccio File Locking Library",
"keywords": [
"private",
@@ -39,7 +39,7 @@
"lockfile": "1.0.4"
},
"devDependencies": {
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"vitest": "3.0.4"
},
"scripts": {

View File

@@ -1,7 +1,7 @@
import locker from 'lockfile';
import fs from 'node:fs';
import path from 'node:path';
import { promisify } from 'util';
import { promisify } from 'node:util';
const fsP = fs.promises ? fs.promises : require('fs/promises');

View File

@@ -1,5 +1,21 @@
# Change Log
## 13.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
- @verdaccio/url@13.0.0-next-8.21
## 13.0.0-next-8.20
### Patch Changes
- Updated dependencies [6a4d6dd]
- @verdaccio/core@8.0.0-next-8.20
- @verdaccio/url@13.0.0-next-8.20
## 13.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/tarball",
"version": "13.0.0-next-8.19",
"version": "13.0.0-next-8.21",
"description": "Verdaccio Tarball Utilities",
"keywords": [
"private",
@@ -33,14 +33,14 @@
"access": "public"
},
"dependencies": {
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/url": "workspace:13.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio/url": "workspace:13.0.0-next-8.21",
"debug": "4.4.1",
"gunzip-maybe": "^1.4.2",
"tar-stream": "^3.1.7"
},
"devDependencies": {
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"node-mocks-http": "1.14.1",
"vitest": "3.0.4"
},

View File

@@ -1,5 +1,11 @@
# Change Log
## 13.0.0-next-8.7
### Patch Changes
- a1a73e9: feat(logger): support redacting sensitive data
## 13.0.0-next-8.6
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/types",
"version": "13.0.0-next-8.6",
"version": "13.0.0-next-8.7",
"description": "Verdaccio Type Definitions",
"keywords": [
"private",

View File

@@ -20,13 +20,20 @@ export type LoggerType = 'stdout' | 'file';
export type LoggerFormat = 'pretty' | 'pretty-timestamped' | 'json';
export type LoggerLevel = 'fatal' | 'error' | 'warn' | 'info' | 'http' | 'debug' | 'trace';
export type LoggerRedact = {
paths: string[];
censor?: string;
remove?: boolean;
};
export type LoggerConfigItem = {
type?: LoggerType;
format?: LoggerFormat;
path?: string;
level?: LoggerLevel;
colors?: boolean;
async?: boolean;
sync?: boolean;
redact?: LoggerRedact;
};
export interface ConfigWithHttps extends Config {

View File

@@ -1,5 +1,19 @@
# Change Log
## 13.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
## 13.0.0-next-8.20
### Patch Changes
- Updated dependencies [6a4d6dd]
- @verdaccio/core@8.0.0-next-8.20
## 13.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/url",
"version": "13.0.0-next-8.19",
"version": "13.0.0-next-8.21",
"description": "Verdaccio URL Utilities",
"keywords": [
"private",
@@ -33,13 +33,13 @@
"access": "public"
},
"dependencies": {
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"debug": "4.4.1",
"lodash": "4.17.21",
"validator": "13.12.0"
},
"devDependencies": {
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"node-mocks-http": "1.14.1",
"vitest": "3.0.4"
},

View File

@@ -1,5 +1,22 @@
# @verdaccio/hooks
## 8.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
- @verdaccio/logger@8.0.0-next-8.21
## 8.0.0-next-8.20
### Patch Changes
- 08e1b21: chore(deps): built-in node imports
- Updated dependencies [6a4d6dd]
- @verdaccio/core@8.0.0-next-8.20
- @verdaccio/logger@8.0.0-next-8.20
## 8.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/hooks",
"version": "8.0.0-next-8.19",
"version": "8.0.0-next-8.21",
"description": "Verdaccio Hooks",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -33,15 +33,15 @@
"node": ">=18"
},
"dependencies": {
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/logger": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio/logger": "workspace:8.0.0-next-8.21",
"debug": "4.4.1",
"got-cjs": "12.5.4",
"handlebars": "4.7.8"
},
"devDependencies": {
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"nock": "13.5.6",
"vitest": "3.0.4"
},

View File

@@ -1,4 +1,4 @@
import path from 'path';
import path from 'node:path';
export const parseConfigurationFile = (name) => {
return path.join(__dirname, `../partials/config/yaml/${name}.yaml`);

View File

@@ -1,5 +1,19 @@
# @verdaccio/loaders
## 8.0.0-next-8.11
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
## 8.0.0-next-8.10
### Patch Changes
- Updated dependencies [6a4d6dd]
- @verdaccio/core@8.0.0-next-8.20
## 8.0.0-next-8.9
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/loaders",
"version": "8.0.0-next-8.9",
"version": "8.0.0-next-8.11",
"description": "Verdaccio Loader Logic",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -17,14 +17,14 @@
"url": "https://github.com/verdaccio/verdaccio/issues"
},
"dependencies": {
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"debug": "4.4.1",
"lodash": "4.17.21"
},
"devDependencies": {
"@verdaccio/logger": "workspace:8.0.0-next-8.19",
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/logger": "workspace:8.0.0-next-8.21",
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio-scope/verdaccio-auth-foo": "0.0.2",
"customprefix-auth": "workspace:2.0.0",
"verdaccio-auth-memory": "workspace:*",

View File

@@ -1,5 +1,22 @@
# @verdaccio/logger-commons
## 8.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
## 8.0.0-next-8.20
### Patch Changes
- a1a73e9: feat(logger): support redacting sensitive data
- Updated dependencies [08e1b21]
- Updated dependencies [6a4d6dd]
- @verdaccio/logger-prettify@8.0.0-next-8.4
- @verdaccio/core@8.0.0-next-8.20
## 8.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/logger-commons",
"version": "8.0.0-next-8.19",
"version": "8.0.0-next-8.21",
"description": "Verdaccio Logger Commons",
"main": "./build/index.js",
"types": "./build/index.d.ts",
@@ -42,13 +42,13 @@
"build": "pnpm run build:js && pnpm run build:types"
},
"dependencies": {
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/logger-prettify": "workspace:8.0.0-next-8.3",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio/logger-prettify": "workspace:8.0.0-next-8.4",
"debug": "4.4.1",
"colorette": "2.0.20"
},
"devDependencies": {
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"pino": "9.7.0",
"vitest": "3.0.4"
},

View File

@@ -25,10 +25,8 @@ export type LogPlugin = {
options?: any[];
};
type LoggerOptions = { level?: string; path?: string; colors?: boolean; sync?: boolean };
export function createLogger(
options: LoggerOptions = { level: 'http' },
options: LoggerConfigItem = { level: 'http' },
// eslint-disable-next-line no-undef
// @ts-ignore
destination: NodeJS.WritableStream = pino.destination(1),
@@ -46,6 +44,8 @@ export function createLogger(
req: pino.stdSerializers.req,
res: pino.stdSerializers.res,
},
sync: options.sync,
redact: options.redact,
};
debug('has prettifier? %o', !isProd());
@@ -124,32 +124,17 @@ export function prepareSetup(options: LoggerConfigItem = DEFAULT_LOGGER_CONF, pi
loggerConfig
);
}
const pinoConfig = { level: loggerConfig.level };
if (loggerConfig.type === 'file') {
debug('logging file enabled');
const destination = pino.destination(loggerConfig.path);
/* eslint-disable */
/* istanbul ignore next */
process.on('SIGUSR2', () => destination.reopen());
// @ts-ignore
logger = createLogger(
{ level: loggerConfig.level, path: loggerConfig.path, colors: loggerConfig.colors },
// @ts-ignore
destination,
loggerConfig.format,
pino
);
logger = createLogger(loggerConfig, destination, loggerConfig.format, pino);
return logger;
} else {
debug('logging stdout enabled');
// @ts-ignore
logger = createLogger(
{ level: loggerConfig.level, colors: loggerConfig.colors },
// @ts-ignore
pino.destination(1),
loggerConfig.format,
pino
);
logger = createLogger(loggerConfig, pino.destination(1), loggerConfig.format, pino);
return logger;
}
}

View File

@@ -126,4 +126,168 @@ describe('logger test', () => {
expect(content).toMatch('info --- publishing or updating a new version for test\n');
});
});
describe('redacting sensitive data', () => {
test('should redact sensitive data with default censor', async () => {
const file = await createLogFile();
const logger = prepareSetup(
{
...defaultOptions,
format: 'json',
type: 'file',
path: file,
level: 'info',
redact: {
paths: ['password', 'token'],
},
},
pino
);
logger.info(
{
user: 'testuser',
password: 'secretpassword123',
token: 'bearer-token-xyz',
publicInfo: 'this should be visible',
},
'User authentication attempt'
);
const content = await readLogFile(file);
const logEntry = JSON.parse(content);
expect(logEntry.user).toBe('testuser');
expect(logEntry.password).toBe('[Redacted]');
expect(logEntry.token).toBe('[Redacted]');
expect(logEntry.publicInfo).toBe('this should be visible');
expect(logEntry.msg).toBe('User authentication attempt');
});
test('should redact sensitive data with custom censor string', async () => {
const file = await createLogFile();
const logger = prepareSetup(
{
...defaultOptions,
format: 'json',
type: 'file',
path: file,
level: 'info',
redact: {
paths: ['apiKey', 'credentials.secret'],
censor: '***HIDDEN***',
},
},
pino
);
logger.info(
{
apiKey: 'api-key-12345',
credentials: {
secret: 'very-secret-data',
publicKey: 'public-data-ok-to-show',
},
requestId: 'req-123',
},
'API request processed'
);
const content = await readLogFile(file);
const logEntry = JSON.parse(content);
expect(logEntry.apiKey).toBe('***HIDDEN***');
expect(logEntry.credentials.secret).toBe('***HIDDEN***');
expect(logEntry.credentials.publicKey).toBe('public-data-ok-to-show');
expect(logEntry.requestId).toBe('req-123');
});
test('should remove sensitive fields when remove option is true', async () => {
const file = await createLogFile();
const logger = prepareSetup(
{
...defaultOptions,
format: 'json',
type: 'file',
path: file,
level: 'info',
redact: {
paths: ['sensitiveData', 'auth.token'],
remove: true,
},
},
pino
);
logger.info(
{
sensitiveData: 'this should be completely removed',
auth: {
token: 'auth-token-456',
userId: 'user123',
},
normalData: 'this should remain',
},
'Processing request with sensitive data'
);
const content = await readLogFile(file);
const logEntry = JSON.parse(content);
expect(logEntry).not.toHaveProperty('sensitiveData');
expect(logEntry.auth).not.toHaveProperty('token');
expect(logEntry.auth.userId).toBe('user123');
expect(logEntry.normalData).toBe('this should remain');
});
test('should redact nested paths correctly', async () => {
const file = await createLogFile();
const logger = prepareSetup(
{
...defaultOptions,
format: 'json',
type: 'file',
path: file,
level: 'info',
redact: {
paths: ['user.password', 'request.headers.authorization', 'data[*].secret'],
censor: '<REDACTED>',
},
},
pino
);
logger.info(
{
user: {
name: 'john',
password: 'userpassword',
email: 'john@example.com',
},
request: {
method: 'POST',
headers: {
authorization: 'Bearer token123',
'content-type': 'application/json',
},
},
data: [
{ id: 1, secret: 'secret1', value: 'public1' },
{ id: 2, secret: 'secret2', value: 'public2' },
],
},
'Complex nested data processing'
);
const content = await readLogFile(file);
const logEntry = JSON.parse(content);
expect(logEntry.user.name).toBe('john');
expect(logEntry.user.password).toBe('<REDACTED>');
expect(logEntry.user.email).toBe('john@example.com');
expect(logEntry.request.method).toBe('POST');
expect(logEntry.request.headers.authorization).toBe('<REDACTED>');
expect(logEntry.request.headers['content-type']).toBe('application/json');
expect(logEntry.data[0].secret).toBe('<REDACTED>');
expect(logEntry.data[0].value).toBe('public1');
expect(logEntry.data[1].secret).toBe('<REDACTED>');
expect(logEntry.data[1].value).toBe('public2');
});
});
});

View File

@@ -1,5 +1,11 @@
# @verdaccio/logger-prettify
## 8.0.0-next-8.4
### Patch Changes
- 08e1b21: chore(deps): built-in node imports
## 8.0.0-next-8.3
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/logger-prettify",
"version": "8.0.0-next-8.3",
"version": "8.0.0-next-8.4",
"description": "Verdaccio Logger Prettify",
"main": "./build/index.js",
"types": "build/index.d.ts",

View File

@@ -1,5 +1,5 @@
import { green, red, white } from 'colorette';
import { inspect } from 'util';
import { inspect } from 'node:util';
import { LevelCode, calculateLevel, levelsColors, subSystemLevels } from './levels';
import { PrettyOptionsExtended } from './types';

View File

@@ -1,5 +1,18 @@
# @verdaccio/logger
## 8.0.0-next-8.21
### Patch Changes
- @verdaccio/logger-commons@8.0.0-next-8.21
## 8.0.0-next-8.20
### Patch Changes
- Updated dependencies [a1a73e9]
- @verdaccio/logger-commons@8.0.0-next-8.20
## 8.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/logger",
"version": "8.0.0-next-8.19",
"version": "8.0.0-next-8.21",
"description": "Verdaccio Logger",
"main": "./build/index.js",
"types": "./build/index.d.ts",
@@ -42,11 +42,11 @@
"build": "pnpm run build:js && pnpm run build:types"
},
"dependencies": {
"@verdaccio/logger-commons": "workspace:8.0.0-next-8.19",
"@verdaccio/logger-commons": "workspace:8.0.0-next-8.21",
"pino": "9.7.0"
},
"devDependencies": {
"@verdaccio/types": "workspace:13.0.0-next-8.6"
"@verdaccio/types": "workspace:13.0.0-next-8.7"
},
"funding": {
"type": "opencollective",

View File

@@ -1,5 +1,26 @@
# @verdaccio/middleware
## 8.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
- @verdaccio/config@8.0.0-next-8.21
- @verdaccio/url@13.0.0-next-8.21
## 8.0.0-next-8.20
### Patch Changes
- 08e1b21: chore(deps): built-in node imports
- Updated dependencies [08e1b21]
- Updated dependencies [a1a73e9]
- Updated dependencies [6a4d6dd]
- @verdaccio/config@8.0.0-next-8.20
- @verdaccio/core@8.0.0-next-8.20
- @verdaccio/url@13.0.0-next-8.20
## 8.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/middleware",
"version": "8.0.0-next-8.19",
"version": "8.0.0-next-8.21",
"description": "Verdaccio Express Middleware",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -42,9 +42,9 @@
"build": "pnpm run build:js && pnpm run build:types"
},
"dependencies": {
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/url": "workspace:13.0.0-next-8.19",
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio/url": "workspace:13.0.0-next-8.21",
"debug": "4.4.1",
"express": "4.21.2",
"express-rate-limit": "5.5.1",
@@ -57,8 +57,8 @@
"url": "https://opencollective.com/verdaccio"
},
"devDependencies": {
"@verdaccio/logger": "workspace:8.0.0-next-8.19",
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/logger": "workspace:8.0.0-next-8.21",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"http-errors": "2.0.0",
"supertest": "7.0.0",
"jsdom": "26.1.0",

View File

@@ -1,5 +1,5 @@
// <reference types="node" />
import * as http from 'http';
import * as http from 'node:http';
import { Logger, RemoteUser } from '@verdaccio/types';

View File

@@ -1,5 +1,34 @@
# @verdaccio/node-api
## 8.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
- @verdaccio/config@8.0.0-next-8.21
- @verdaccio/server@8.0.0-next-8.21
- @verdaccio/server-fastify@8.0.0-next-8.21
- @verdaccio/logger@8.0.0-next-8.21
## 8.0.0-next-8.20
### Minor Changes
- 6a4d6dd: feat: getListenAddress getConfigParsed methods
### Patch Changes
- 08e1b21: chore(deps): built-in node imports
- Updated dependencies [08e1b21]
- Updated dependencies [a1a73e9]
- Updated dependencies [6a4d6dd]
- @verdaccio/server-fastify@8.0.0-next-8.20
- @verdaccio/config@8.0.0-next-8.20
- @verdaccio/core@8.0.0-next-8.20
- @verdaccio/server@8.0.0-next-8.20
- @verdaccio/logger@8.0.0-next-8.20
## 8.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/node-api",
"version": "8.0.0-next-8.19",
"version": "8.0.0-next-8.21",
"description": "Verdaccio Node API",
"main": "build/index.js",
"types": "build/index.d.ts",
@@ -42,16 +42,16 @@
},
"license": "MIT",
"dependencies": {
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/logger": "workspace:8.0.0-next-8.19",
"@verdaccio/server": "workspace:8.0.0-next-8.19",
"@verdaccio/server-fastify": "workspace:8.0.0-next-8.19",
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio/logger": "workspace:8.0.0-next-8.21",
"@verdaccio/server": "workspace:8.0.0-next-8.21",
"@verdaccio/server-fastify": "workspace:8.0.0-next-8.21",
"debug": "4.4.1",
"lodash": "4.17.21"
},
"devDependencies": {
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"selfsigned": "2.4.1",
"supertest": "7.0.0",
"vitest": "3.0.4"

View File

@@ -1,84 +0,0 @@
import { warningUtils } from '@verdaccio/core';
export const DEFAULT_PORT = '4873';
export const DEFAULT_PROTOCOL = 'http';
export const DEFAULT_DOMAIN = 'localhost';
/**
* Parse an internet address
* Allow:
- https:localhost:1234 - protocol + host + port
- localhost:1234 - host + port
- 1234 - port
- http::1234 - protocol + port
- https://localhost:443/ - full url + https
- http://[::1]:443/ - ipv6
- unix:/tmp/http.sock - unix sockets
- https://unix:/tmp/http.sock - unix sockets (https)
* @param {*} urlAddress the internet address definition
* @return {Object|Null} literal object that represent the address parsed
*/
export function parseAddress(urlAddress: any): any {
//
// TODO: refactor it to something more reasonable?
//
// protocol : // ( host )|( ipv6 ): port /
let urlPattern = /^((https?):(\/\/)?)?((([^\/:]*)|\[([^\[\]]+)\]):)?(\d+)\/?$/.exec(urlAddress);
if (urlPattern) {
return {
proto: urlPattern[2] || DEFAULT_PROTOCOL,
host: urlPattern[6] || urlPattern[7] || DEFAULT_DOMAIN,
port: urlPattern[8] || DEFAULT_PORT,
};
}
urlPattern = /^((https?):(\/\/)?)?unix:(.*)$/.exec(urlAddress);
if (urlPattern) {
return {
proto: urlPattern[2] || DEFAULT_PROTOCOL,
path: urlPattern[4],
};
}
return null;
}
/**
* Retrieve all addresses defined in the config file.
* Verdaccio is able to listen multiple ports
* @param {String} argListen
* @param {String} configListen
* eg:
* listen:
- localhost:5555
- localhost:5557
@return {Array}
*/
export function getListListenAddresses(argListen: string | void, configListen: any): any {
// command line || config file || default
let addresses;
if (argListen) {
addresses = [argListen];
} else if (Array.isArray(configListen)) {
addresses = configListen;
process.emitWarning('multiple addresses will be deprecated in the next major, only use one');
} else if (configListen) {
addresses = [configListen];
} else {
addresses = [DEFAULT_PORT];
}
addresses = addresses
.map(function (addr): string {
const parsedAddr = parseAddress(addr);
if (!parsedAddr) {
warningUtils.emit(warningUtils.Codes.VERWAR004, addr);
}
return parsedAddr;
})
.filter(Boolean);
return addresses;
}

View File

@@ -1,20 +1,19 @@
/* eslint-disable */
import constants from 'constants';
import buildDebug from 'debug';
import _, { assign, isFunction } from 'lodash';
import constants from 'node:constants';
import fs from 'node:fs';
import http from 'node:http';
import https from 'node:https';
import url from 'node:url';
import { findConfigFile, parseConfigFile } from '@verdaccio/config';
import { API_ERROR } from '@verdaccio/core';
import { setup } from '@verdaccio/logger';
import { getConfigParsed, getListenAddress } from '@verdaccio/config';
import { DEFAULT_PORT } from '@verdaccio/core';
import { logger, setup } from '@verdaccio/logger';
import expressServer from '@verdaccio/server';
import fastifyServer from '@verdaccio/server-fastify';
import { ConfigYaml, HttpsConfKeyCert, HttpsConfPfx } from '@verdaccio/types';
import { getListListenAddresses } from './cli-utils';
import { displayExperimentsInfoBox } from './experiments';
const debug = buildDebug('verdaccio:node-api');
@@ -121,9 +120,9 @@ export async function initServer(
pkgName: string
): Promise<void> {
return new Promise(async (resolve, reject) => {
// FIXME: get only the first match, the multiple address will be removed
const [addr] = getListListenAddresses(port, config.listen);
const logger = setup(config?.log as any);
const combined: string | undefined | any[] = [port, config?.listen, DEFAULT_PORT];
const addr = getListenAddress(combined, logger);
displayExperimentsInfoBox(config.flags);
let app;
@@ -198,20 +197,12 @@ export async function initServer(
* @param config
*/
export async function runServer(config?: string | ConfigYaml): Promise<any> {
let configurationParsed: ConfigYaml;
if (config === undefined || typeof config === 'string') {
const configPathLocation = findConfigFile(config);
configurationParsed = parseConfigFile(configPathLocation);
} else if (_.isObject(config)) {
configurationParsed = config;
} else {
throw new Error(API_ERROR.CONFIG_BAD_FORMAT);
}
const configurationParsed = getConfigParsed(config);
setup(configurationParsed.log as any);
displayExperimentsInfoBox(configurationParsed.flags);
// FIXME: get only the first match, the multiple address will be removed
const [addr] = getListListenAddresses(undefined, configurationParsed.listen);
const combined: string | undefined | any[] = [configurationParsed?.listen, DEFAULT_PORT];
const addr = getListenAddress(combined, logger);
const app = await expressServer(configurationParsed);
return createServerFactory(configurationParsed, addr, app);
}

View File

@@ -1,68 +0,0 @@
import _ from 'lodash';
import { describe, expect, test } from 'vitest';
import {
DEFAULT_DOMAIN,
DEFAULT_PORT,
DEFAULT_PROTOCOL,
getListListenAddresses,
} from '../src/cli-utils';
describe('getListListenAddresses test', () => {
test('should return no address if a single address is wrong', () => {
// @ts-ignore
const addrs = getListListenAddresses('wrong');
expect(_.isArray(addrs)).toBeTruthy();
expect(addrs).toHaveLength(0);
});
test('should return no address if a two address are wrong', () => {
// @ts-ignore
const addrs = getListListenAddresses(['wrong', 'same-wrong']);
expect(_.isArray(addrs)).toBeTruthy();
expect(addrs).toHaveLength(0);
});
test('should return a list of 1 address provided', () => {
// @ts-ignore
const addrs = getListListenAddresses(null, '1000');
expect(_.isArray(addrs)).toBeTruthy();
expect(addrs).toHaveLength(1);
});
test('should return a list of 2 address provided', () => {
// @ts-ignore
const addrs = getListListenAddresses(null, ['1000', '2000']);
expect(_.isArray(addrs)).toBeTruthy();
expect(addrs).toHaveLength(2);
});
test(`should return by default ${DEFAULT_PORT}`, () => {
// @ts-ignore
const [addrs] = getListListenAddresses();
// @ts-ignore
expect(addrs.proto).toBe(DEFAULT_PROTOCOL);
// @ts-ignore
expect(addrs.host).toBe(DEFAULT_DOMAIN);
// @ts-ignore
expect(addrs.port).toBe(DEFAULT_PORT);
});
test('should return default proto, host and custom port', () => {
const initPort = '1000';
// @ts-ignore
const [addrs] = getListListenAddresses(null, initPort);
// @ts-ignore
expect(addrs.proto).toEqual(DEFAULT_PROTOCOL);
// @ts-ignore
expect(addrs.host).toEqual(DEFAULT_DOMAIN);
// @ts-ignore
expect(addrs.port).toEqual(initPort);
});
});

View File

@@ -1,52 +0,0 @@
import _ from 'lodash';
import { describe, expect, test } from 'vitest';
import { DEFAULT_DOMAIN, DEFAULT_PORT, parseAddress } from '../src/cli-utils';
describe('Parse listen address', () => {
const useCases: any[] = [];
function addTest(uri: string, proto: string | null, host?: string, port?: string) {
useCases.push([uri, proto, host, port]);
}
addTest(DEFAULT_PORT, 'http', DEFAULT_DOMAIN, DEFAULT_PORT);
addTest(':4873', 'http', DEFAULT_DOMAIN, DEFAULT_PORT);
addTest('blah:4873', 'http', 'blah', DEFAULT_PORT);
addTest('http://:4873', 'http', DEFAULT_DOMAIN, DEFAULT_PORT);
addTest('https::4873', 'https', DEFAULT_DOMAIN, DEFAULT_PORT);
addTest('https:blah:4873', 'https', 'blah', DEFAULT_PORT);
addTest('https://blah:4873/', 'https', 'blah', DEFAULT_PORT);
addTest('[::1]:4873', 'http', '::1', DEFAULT_PORT);
addTest('https:[::1]:4873', 'https', '::1', DEFAULT_PORT);
addTest('unix:/tmp/foo.sock', 'http', '/tmp/foo.sock');
addTest('http:unix:foo.sock', 'http', 'foo.sock');
addTest('https://unix:foo.sock', 'https', 'foo.sock');
addTest('https://unix:foo.sock:34', 'https', 'foo.sock:34');
addTest('http://foo.sock:34', 'http', 'foo.sock', '34');
addTest('blah', null);
addTest('blah://4873', null);
addTest('https://blah:4873///', null);
addTest('unix:1234', 'http', 'unix', '1234'); // not unix socket
test.each(useCases)(`should parse (%s - %s - %s - %s)`, (uri, proto, host, port) => {
const parsed = parseAddress(uri);
if (_.isNull(proto)) {
expect(parsed).toBeNull();
} else if (port) {
expect(parsed).toEqual({
proto,
host,
port,
});
} else {
expect(parsed).toEqual({
proto,
path: host,
});
}
});
});

View File

@@ -1,5 +1,23 @@
# Change Log
## 13.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
- @verdaccio/config@8.0.0-next-8.21
## 13.0.0-next-8.20
### Patch Changes
- Updated dependencies [08e1b21]
- Updated dependencies [a1a73e9]
- Updated dependencies [6a4d6dd]
- @verdaccio/config@8.0.0-next-8.20
- @verdaccio/core@8.0.0-next-8.20
## 13.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "verdaccio-audit",
"version": "13.0.0-next-8.19",
"version": "13.0.0-next-8.21",
"description": "Verdaccio Middleware plugin to bypass npmjs audit",
"keywords": [
"private",
@@ -30,16 +30,16 @@
"node": ">=18"
},
"dependencies": {
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"express": "4.21.2",
"https-proxy-agent": "5.0.1",
"node-fetch": "cjs"
},
"devDependencies": {
"@verdaccio/auth": "workspace:8.0.0-next-8.19",
"@verdaccio/logger": "workspace:8.0.0-next-8.19",
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/auth": "workspace:8.0.0-next-8.21",
"@verdaccio/logger": "workspace:8.0.0-next-8.21",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"nock": "13.5.6",
"supertest": "7.0.0",
"vitest": "3.0.4"

View File

@@ -1,5 +1,19 @@
# Change Log
## 13.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
## 13.0.0-next-8.20
### Patch Changes
- Updated dependencies [6a4d6dd]
- @verdaccio/core@8.0.0-next-8.20
## 13.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "verdaccio-auth-memory",
"version": "13.0.0-next-8.19",
"version": "13.0.0-next-8.21",
"description": "Auth plugin for Verdaccio that keeps users in memory",
"keywords": [
"private",
@@ -30,13 +30,13 @@
"node": ">=18"
},
"dependencies": {
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"debug": "4.4.1"
},
"devDependencies": {
"@types/debug": "^4.1.12",
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/types": "workspace:13.0.0-next-8.6"
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"@verdaccio/types": "workspace:13.0.0-next-8.7"
},
"scripts": {
"clean": "rimraf ./build",

View File

@@ -1,5 +1,21 @@
# Change Log
## 13.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
## 13.0.0-next-8.20
### Patch Changes
- Updated dependencies [08e1b21]
- Updated dependencies [6a4d6dd]
- @verdaccio/file-locking@13.0.0-next-8.5
- @verdaccio/core@8.0.0-next-8.20
## 13.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "verdaccio-htpasswd",
"version": "13.0.0-next-8.19",
"version": "13.0.0-next-8.21",
"description": "Htpasswd Authentication Plugin for Verdaccio",
"keywords": [
"private",
@@ -33,8 +33,8 @@
"node": ">=18"
},
"dependencies": {
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/file-locking": "workspace:13.0.0-next-8.4",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio/file-locking": "workspace:13.0.0-next-8.5",
"apache-md5": "1.1.8",
"bcryptjs": "2.4.3",
"http-errors": "2.0.0",
@@ -43,8 +43,8 @@
},
"devDependencies": {
"@types/bcryptjs": "2.4.6",
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"mockdate": "3.0.5",
"vitest": "3.0.4"
},

View File

@@ -1,5 +1,23 @@
# Change Log
## 13.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
- @verdaccio/utils@8.1.0-next-8.21
## 13.0.0-next-8.20
### Patch Changes
- Updated dependencies [08e1b21]
- Updated dependencies [6a4d6dd]
- @verdaccio/file-locking@13.0.0-next-8.5
- @verdaccio/core@8.0.0-next-8.20
- @verdaccio/utils@8.1.0-next-8.20
## 13.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/local-storage",
"version": "13.0.0-next-8.19",
"version": "13.0.0-next-8.21",
"description": "Verdaccio Local Storage Plugin",
"keywords": [
"private",
@@ -36,9 +36,9 @@
"node": ">=18"
},
"dependencies": {
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/file-locking": "workspace:13.0.0-next-8.4",
"@verdaccio/utils": "workspace:8.1.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"@verdaccio/file-locking": "workspace:13.0.0-next-8.5",
"@verdaccio/utils": "workspace:8.1.0-next-8.21",
"debug": "4.4.1",
"globby": "11.1.0",
"lodash": "4.17.21",
@@ -46,8 +46,8 @@
"sanitize-filename": "1.6.3"
},
"devDependencies": {
"@verdaccio/logger": "workspace:8.0.0-next-8.19",
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/logger": "workspace:8.0.0-next-8.21",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"vitest": "3.0.4"
},
"scripts": {

View File

@@ -1,5 +1,19 @@
# Change Log
## 13.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
## 13.0.0-next-8.20
### Patch Changes
- Updated dependencies [6a4d6dd]
- @verdaccio/core@8.0.0-next-8.20
## 13.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "verdaccio-memory",
"version": "13.0.0-next-8.19",
"version": "13.0.0-next-8.21",
"description": "Verdaccio Memory Storage Plugin",
"keywords": [
"private",
@@ -30,14 +30,14 @@
"node": ">=18"
},
"dependencies": {
"@verdaccio/core": "workspace:8.0.0-next-8.19",
"@verdaccio/core": "workspace:8.0.0-next-8.21",
"debug": "4.4.1",
"memfs": "3.5.3"
},
"devDependencies": {
"@verdaccio/types": "workspace:13.0.0-next-8.6",
"@verdaccio/config": "workspace:8.0.0-next-8.19",
"@verdaccio/logger": "workspace:8.0.0-next-8.19",
"@verdaccio/types": "workspace:13.0.0-next-8.7",
"@verdaccio/config": "workspace:8.0.0-next-8.21",
"@verdaccio/logger": "workspace:8.0.0-next-8.21",
"vitest": "3.0.4"
},
"scripts": {

View File

@@ -1,5 +1,13 @@
# @verdaccio/ui-theme
## 8.0.0-next-8.21
## 8.0.0-next-8.20
### Patch Changes
- 08e1b21: chore(deps): built-in node imports
## 8.0.0-next-8.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/ui-theme",
"version": "8.0.0-next-8.19",
"version": "8.0.0-next-8.21",
"description": "Verdaccio User Interface (Theme)",
"author": {
"name": "Verdaccio Contributors",

View File

@@ -1,5 +1,5 @@
import fs from 'fs';
import path from 'path';
import fs from 'node:fs';
import path from 'node:path';
/**
* A module to get package informations from package.json

View File

@@ -1,7 +1,7 @@
import FriendlyErrorsPlugin from 'friendly-errors-webpack-plugin';
import fs from 'fs';
import HTMLWebpackPlugin from 'html-webpack-plugin';
import yaml from 'js-yaml';
import fs from 'node:fs';
import StyleLintPlugin from 'stylelint-webpack-plugin';
import webpack from 'webpack';

View File

@@ -1,5 +1,25 @@
# @verdaccio/proxy
## 8.0.0-next-8.21
### Patch Changes
- Updated dependencies [f8a321f]
- @verdaccio/core@8.0.0-next-8.21
- @verdaccio/config@8.0.0-next-8.21
## 8.0.0-next-8.20
### Patch Changes
- 08e1b21: chore(deps): built-in node imports
- d92ba65: chore(proxy): update tests
- Updated dependencies [08e1b21]
- Updated dependencies [a1a73e9]
- Updated dependencies [6a4d6dd]
- @verdaccio/config@8.0.0-next-8.20
- @verdaccio/core@8.0.0-next-8.20
## 8.0.0-next-8.19
### Patch Changes

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