Compare commits

..

10 Commits

Author SHA1 Message Date
Juan Picado
ad1a5b01fa migrate vitest 2024-09-28 09:31:32 +02:00
Juan Picado
f775e05772 fix test 2024-09-28 09:31:32 +02:00
Juan Picado
9790875741 legacy storages support
legacy storages support

rebase
2024-09-28 09:31:32 +02:00
Juan Picado
2f704a6445 chore: update install docs 2024-09-27 06:45:27 +02:00
Juan Picado
24cc01e90e Update crowdin.yaml 2024-09-26 23:13:52 +02:00
Juan Picado
a5ae8b5f82 chore: remove versioned docs 7.x
not longer need it
2024-09-26 23:00:18 +02:00
Juan Picado
11ce908fc6 Update crowdin.yaml 2024-09-26 21:56:25 +02:00
Juan Picado
14c1c829e8 chore: update website config 6.x 2024-09-26 21:05:10 +02:00
Juan Picado
100421624f chore: disable ga-IE temporary website 2024-09-26 21:02:19 +02:00
verdacciobot
80313897cb chore: updated static data 2024-09-26 00:15:15 +00:00
216 changed files with 2600 additions and 18295 deletions

View File

@@ -14,6 +14,10 @@ test/functional/store/*
docker-examples/**/lib/**/*.js
test/cli/e2e-yarn4/bin/yarn-4.0.0-rc.14.cjs
yarn.js
# used for unit tests
packages/store/test/fixtures/plugins/**/*
# storybook
packages/ui-components/storybook-static
dist.js

View File

@@ -15,5 +15,5 @@ files:
ignore: [/website/docs/api/**/*]
- source: /website/versioned_docs/**/*
translation: /website/i18n/%locale%/docusaurus-plugin-content-docs/**/%original_file_name%
ignore: [/website/versioned_docs/version-5.x/api/**/*, /website/versioned_docs/version-6.x/api/**/*]
ignore: [/website/versioned_docs/version-6.x/api/**/*]

View File

@@ -3,7 +3,6 @@ import fs from 'fs';
import { dirname, isAbsolute, join, resolve } from 'path';
import { pluginUtils } from '@verdaccio/core';
import { logger } from '@verdaccio/logger';
import { Config, Logger } from '@verdaccio/types';
import { PluginType, isES6, isValid, tryLoad } from './utils';
@@ -54,7 +53,7 @@ export async function asyncLoadPlugin<T extends pluginUtils.Plugin<T>>(
pluginCategory: string = ''
): Promise<PluginType<T>[]> {
const pluginsIds = Object.keys(pluginConfigs);
const { config } = params;
const { config, logger } = params;
let plugins: PluginType<T>[] = [];
for (let pluginId of pluginsIds) {
debug('plugin %s', pluginId);

View File

@@ -14,7 +14,7 @@ class Search {
public readonly uplinks: ProxyInstanceList;
public readonly logger: Logger;
constructor(config: Config, logger: Logger) {
this.logger = logger.child({ module: 'proxy' });
this.logger = logger;
this.uplinks = setupUpLinks(config, this.logger);
}

View File

@@ -13,7 +13,7 @@
// const { packageName } = request.params;
// const storage = fastify.storage;
// debug('pkg name %s ', packageName);
// // const data = await storage?.getPackageNext({
// // const data = await storage?.getPackage({
// // name: packageName,
// // req: request.raw,
// // uplinksLook: true,

View File

@@ -1,12 +0,0 @@
const config = require('../../jest/config');
module.exports = Object.assign({}, config, {
coverageThreshold: {
global: {
// FIXME: increase to 90
branches: 62,
functions: 84,
lines: 74,
},
},
});

View File

@@ -30,7 +30,7 @@
},
"scripts": {
"clean": "rimraf ./build",
"test": "jest",
"test": "vitest run",
"type-check": "tsc --noEmit -p tsconfig.build.json",
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",

View File

@@ -0,0 +1,59 @@
const isPromiseFunction = (func: any) => {
return typeof func === 'function' && func.then !== undefined;
};
const isCallbackFunction = (func: any) => {
return typeof func === 'function' && func.length > 0 && func.toString().includes('callback');
};
export function checkFunctionIsPromise<T>(instance: T, methodName: keyof T): boolean {
const method = instance[methodName];
if (typeof method !== 'function') {
return false;
}
if (isPromiseFunction(method)) {
return true;
}
if (isCallbackFunction(method)) {
return false;
}
return true;
}
export function isPromise(obj: any): obj is Promise<any> {
return (
!!obj &&
(typeof obj === 'object' || typeof obj === 'function') &&
typeof obj.then === 'function'
);
}
export function promisifiedCallbackFunction<T>(
instance: T,
methodName: keyof T,
...args: any[]
): Promise<any> {
return new Promise((resolve, reject) => {
const method = instance[methodName];
if (typeof method !== 'function') {
reject(new Error(`${String(methodName)} is not a function on the given instance.`));
return;
}
// Append the callback to the args
args.push((error: any, result: any) => {
if (error) {
reject(error);
} else {
resolve(result);
}
});
method.apply(instance, args);
});
}

View File

@@ -23,7 +23,7 @@ class LocalStorage {
public constructor(config: Config, logger: Logger) {
debug('local storage created');
this.logger = logger.child({ sub: 'fs' });
this.logger = logger;
this.config = config;
// @ts-expect-error
this.storagePlugin = null;
@@ -33,8 +33,12 @@ class LocalStorage {
if (this.storagePlugin === null) {
this.storagePlugin = await this.loadStorage(this.config, this.logger);
debug('storage plugin init');
await this.storagePlugin.init();
debug('storage plugin initialized');
if (typeof this.storagePlugin.init !== 'undefined') {
await this.storagePlugin.init();
debug('storage plugin initialized');
} else {
debug('storage plugin does not require initialization');
}
} else {
this.logger.warn('storage plugin has been already initialized');
}

View File

@@ -68,6 +68,7 @@ import {
tagVersion,
tagVersionNext,
} from '.';
import { checkFunctionIsPromise, promisifiedCallbackFunction } from './lib/legacy-utils';
import { isPublishablePackage } from './lib/star-utils';
import { isExecutingStarCommand } from './lib/star-utils';
import {
@@ -103,7 +104,7 @@ class Storage {
private searchService: Search;
public constructor(config: Config, logger: Logger) {
this.config = config;
this.logger = logger.child({ module: 'storage' });
this.logger = logger;
this.uplinks = setupUpLinks(config, this.logger);
this.searchService = new Search(config, this.logger);
this.filters = null;
@@ -201,7 +202,9 @@ class Storage {
}
try {
const cacheManifest = await storage.readPackage(name);
const cacheManifest: Manifest = await (checkFunctionIsPromise(storage, 'readPackage')
? storage.readPackage(name)
: promisifiedCallbackFunction(storage, 'readPackage', name));
if (!cacheManifest._attachments[filename]) {
throw errorUtils.getNotFound('no such file available');
}
@@ -447,7 +450,7 @@ class Storage {
}
// we have version, so we need to return specific version
const [convertedManifest] = await this.getPackageNext(options);
const [convertedManifest] = await this.getPackage(options);
const version: Version | undefined = getVersion(convertedManifest.versions, queryVersion);
@@ -494,7 +497,7 @@ class Storage {
public async getPackageManifest(options: IGetPackageOptionsNext): Promise<Manifest> {
// convert dist remotes to local bars
const [manifest] = await this.getPackageNext(options);
const [manifest] = await this.getPackage(options);
// If change access is requested (?write=true), then check if logged in user is allowed to change package
if (options.byPassCache === true) {
@@ -584,10 +587,16 @@ class Storage {
public async getLocalDatabase(): Promise<Version[]> {
debug('get local database');
const storage = this.localStorage.getStoragePlugin();
const database = await storage.get();
// backward compatibility with legacy storage plugins
const database = await (checkFunctionIsPromise(storage, 'get')
? storage.get()
: promisifiedCallbackFunction(storage, 'get'));
const packages: Version[] = [];
for (const pkg of database) {
debug('get local database %o', pkg);
const manifest = await this.getPackageLocalMetadata(pkg);
const latest = manifest[DIST_TAGS].latest;
if (latest && manifest.versions[latest]) {
@@ -823,7 +832,10 @@ class Storage {
}
try {
const result: Manifest = await storage.readPackage(name);
const result: Manifest = checkFunctionIsPromise(storage, 'readPackage')
? await storage.readPackage(name)
: await promisifiedCallbackFunction(storage, 'readPackage', name);
return normalizePackage(result);
} catch (err: any) {
if (err.code === STORAGE.NO_SUCH_FILE_ERROR || err.code === HTTP_STATUS.NOT_FOUND) {
@@ -1049,7 +1061,7 @@ class Storage {
* @param name
* @returns
*/
private async getPackagelocalByNameNext(name: string): Promise<Manifest | null> {
private async getPackagelocalByName(name: string): Promise<Manifest | null> {
try {
return await this.getPackageLocalMetadata(name);
} catch (err: any) {
@@ -1082,6 +1094,7 @@ class Storage {
if (typeof storage === 'undefined') {
throw errorUtils.getNotFound();
}
// TODO: juan
const hasPackage = await storage.hasPackage();
debug('has package %o for %o', pkgName, hasPackage);
return hasPackage;
@@ -1123,7 +1136,7 @@ class Storage {
try {
// we check if package exist already locally
const localManifest = await this.getPackagelocalByNameNext(name);
const localManifest = await this.getPackagelocalByName(name);
// if continue, the version to be published does not exist
if (localManifest?.versions[versionToPublish] != null) {
debug('%s version %s already exists (locally)', name, versionToPublish);
@@ -1600,7 +1613,7 @@ class Storage {
* @return {*} {Promise<[Manifest, any[]]>}
* @memberof AbstractStorage
*/
private async getPackageNext(options: IGetPackageOptionsNext): Promise<[Manifest, any[]]> {
private async getPackage(options: IGetPackageOptionsNext): Promise<[Manifest, any[]]> {
const { name } = options;
debug('get package for %o', name);
let data: Manifest | null = null;
@@ -1719,7 +1732,7 @@ class Storage {
if (found && syncManifest !== null) {
// updates the local cache manifest with fresh data
let updatedCacheManifest = await this.updateVersionsNext(name, syncManifest);
let updatedCacheManifest = await this.updateVersions(name, syncManifest);
// plugin filter applied to the manifest
const [filteredManifest, filtersErrors] = await this.applyFilters(updatedCacheManifest);
return [
@@ -1883,13 +1896,16 @@ class Storage {
* @return {Function}
*/
private async readCreatePackage(pkgName: string): Promise<Manifest> {
const storage: any = this.getPrivatePackageStorage(pkgName);
const storage = this.getPrivatePackageStorage(pkgName);
if (_.isNil(storage)) {
throw errorUtils.getInternalError('storage could not be found');
}
try {
const result: Manifest = await storage.readPackage(pkgName);
// backward compatibility for legacy plugins
const result: Manifest = await (checkFunctionIsPromise(storage, 'readPackage')
? storage.readPackage(pkgName)
: promisifiedCallbackFunction(storage, 'readPackage', pkgName));
return normalizePackage(result);
} catch (err: any) {
if (err.code === STORAGE.NO_SUCH_FILE_ERROR || err.code === HTTP_STATUS.NOT_FOUND) {
@@ -1910,13 +1926,13 @@ class Storage {
The steps are the following.
1. Get the latest version of the package from the cache.
2. If does not exist will return a
2. If does not exist will return a
@param name
@param remoteManifest
@returns return a merged manifest.
*/
public async updateVersionsNext(name: string, remoteManifest: Manifest): Promise<Manifest> {
public async updateVersions(name: string, remoteManifest: Manifest): Promise<Manifest> {
debug(`updating versions for package %o`, name);
let cacheManifest: Manifest = await this.readCreatePackage(name);
let change = false;

View File

@@ -0,0 +1,18 @@
packages:
'@scope/foo':
access: $all
publish: $authenticated
'@*/*':
access: $all
publish: $all
proxy: ver
'foo':
access: $all
publish: $authenticated
'*':
access: $all
publish: $all
proxy: npmjs
store:
legacy-storage-plugin:
plugins: /roo/does-not-exist

View File

@@ -0,0 +1,16 @@
uplinks:
ver:
url: https://registry.verdaccio.org/
packages:
'@*/*':
access: $all
publish: $all
proxy: ver
'upstream':
access: $all
publish: $authenticated
'*':
access: $all
publish: $all
proxy: ver
log: { type: stdout, format: pretty, level: info }

View File

@@ -0,0 +1,15 @@
'use strict';
var __importDefault =
(this && this.__importDefault) ||
function (mod) {
return mod && mod.__esModule ? mod : { default: mod };
};
Object.defineProperty(exports, '__esModule', { value: true });
exports.default = void 0;
var plugin_1 = require('./plugin');
Object.defineProperty(exports, 'default', {
enumerable: true,
get: function () {
return __importDefault(plugin_1).default;
},
});

View File

@@ -0,0 +1,160 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
const commons_api_1 = require('@verdaccio/commons-api');
class StoragePluginManage {
logger;
packageName;
config;
constructor(config, packageName, logger) {
this.logger = logger;
this.packageName = packageName;
this.config = config;
}
/**
* Handle a metadata update and
* @param name
* @param updateHandler
* @param onWrite
* @param transformPackage
* @param onEnd
*/
updatePackage(name, updateHandler, onWrite, transformPackage, onEnd) {
onEnd((0, commons_api_1.getInternalError)('Not implemented'));
/**
* Example of implementation:
this.customStore.get().then((pkg: Package) => {
updateHandler(pkg, function onUpdateFinish(err) {
if (err) {
onEnd(err);
} else {
onWrite(name, pkg, onEnd);
}
})
});
*/
}
/**
* Delete a specific file (tarball or package.json)
* @param fileName
* @param callback
*/
deletePackage(fileName, callback) {
callback((0, commons_api_1.getInternalError)('Not implemented'));
/**
* Example of implementation:
this.customStore.delete(fileName, (err) => {
if (err) {
callback(err);
} else {
callback(null);
}
})
*/
}
/**
* Delete a package (folder, path)
* This happens after all versions ar tarballs have been removed.
* @param callback
*/
removePackage(callback) {
callback((0, commons_api_1.getInternalError)('Not implemented'));
/**
* Example of implementation:
this.customStore.removePackage((err) => {
if (err) {
callback(err);
} else {
callback(null);
}
})
*/
}
/**
* Publish a new package (version).
* @param name
* @param data
* @param callback
*/
createPackage(name, data, callback) {
callback((0, commons_api_1.getInternalError)('Not implemented'));
/**
* Example of implementation:
* this.customStore.create(name, data).then(err => {
if (err.notFound) {
callback(getNotFound());
} else if (err.alreadyExist) {
callback(getConflict());
} else {
callback(null);
}
})
*/
}
/**
* Perform write anobject to the storage.
* Similar to updatePackage but without middleware handlers
* @param pkgName package name
* @param pkg package metadata
* @param callback
*/
savePackage(pkgName, pkg, callback) {
callback((0, commons_api_1.getInternalError)('Not implemented'));
/*
Example of implementation:
this.cumstomStore.write(pkgName, pkgName).then(data => {
callback(null);
}).catch(err => {
callback(getInternalError(err.message));
})
*/
}
/**
* Read a package from storage
* @param pkgName package name
* @param callback
*/
readPackage(pkgName, callback) {
callback(null, {
name: pkgName,
'dist-tags': { latest: '1.0.0' },
versions: { '1.0.0': { pkgName } },
});
/**
* Example of implementation:
* this.customStorage.read(name, (err, pkg: Package) => {
if (err.fooError) {
callback(getInternalError(err))
} else if (err.barError) {
callback(getNotFound());
} else {
callback(null, pkg)
}
});
*/
}
/**
* Create writtable stream (write a tarball)
* @param name
*/
writeTarball(name) {
/**
* Example of implementation:
* const stream = new UploadTarball({});
return stream;
*/
return Buffer.from('');
}
/**
* Create a readable stream (read a from a tarball)
* @param name
*/
readTarball(name) {
/**
* Example of implementation:
* const stream = new ReadTarball({});
return stream;
*/
return Buffer.from('');
}
}
exports.default = StoragePluginManage;

View File

@@ -0,0 +1,125 @@
'use strict';
var __importDefault =
(this && this.__importDefault) ||
function (mod) {
return mod && mod.__esModule ? mod : { default: mod };
};
Object.defineProperty(exports, '__esModule', { value: true });
const commons_api_1 = require('@verdaccio/commons-api');
const local_storage_1 = __importDefault(require('./local-storage'));
class VerdaccioStoragePlugin {
config;
version;
logger;
constructor(config, options) {
this.config = config;
this.logger = options.logger;
}
/**
*
*/
async getSecret() {
return 'your secret';
}
async setSecret(secret) {
return true;
}
/**
* Add a new element.
* @param {*} name
* @return {Error|*}
*/
add(name, callback) {
callback((0, commons_api_1.getInternalError)('your own message here'));
}
/**
* Perform a search in your registry
* @param onPackage
* @param onEnd
* @param validateName
*/
search(onPackage, onEnd, validateName) {
onEnd();
/**
* Example of implementation:
* try {
* someApi.getPackages((items) => {
* items.map(() => {
* if (validateName(item.name)) {
* onPackage(item);
* }
* });
* onEnd();
* } catch(err) {
* onEnd(err);
* }
* });
*/
}
/**
* Remove an element from the database.
* @param {*} name
* @return {Error|*}
*/
remove(name, callback) {
callback((0, commons_api_1.getInternalError)('your own message here'));
/**
* Example of implementation
database.getPackage(name, (item, err) => {
if (err) {
callback(getInternalError('your own message here'));
}
// if all goes well we return nothing
callback(null);
}
*/
}
/**
* Return all database elements.
* @return {Array}
*/
get(callback) {
callback(null, [{ name: 'your-package' }]);
/*
Example of implementation
database.getAll((allItems, err) => {
callback(err, allItems);
})
*/
}
/**
* Create an instance of the `PackageStorage`
* @param packageInfo
*/
getPackageStorage(packageInfo) {
return new local_storage_1.default(this.config, packageInfo, this.logger);
}
/**
* All methods for npm token support
* more info here https://github.com/verdaccio/verdaccio/pull/1427
*/
saveToken(token) {
throw new Error('Method not implemented.');
}
deleteToken(user, tokenKey) {
throw new Error('Method not implemented.');
}
readTokens(filter) {
throw new Error('Method not implemented.');
}
}
exports.default = VerdaccioStoragePlugin;

View File

@@ -0,0 +1,11 @@
{
"name": "verdaccio-legacy-storage-plugin",
"version": "1.0.0",
"description": "",
"main": "lib/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

View File

@@ -1,14 +1,21 @@
import { pseudoRandomBytes } from 'crypto';
import buildDebug from 'debug';
import fs from 'fs';
import os from 'os';
import path from 'path';
import { parseConfigFile } from '@verdaccio/config';
import { Config, getDefaultConfig } from '@verdaccio/config';
import { ConfigYaml, PackageUsers } from '@verdaccio/types';
const debug = buildDebug('verdaccio:mock:config');
const debug = buildDebug('verdaccio:storage:test:helpers');
export const domain = 'https://registry.npmjs.org';
/**
* Override the default.yaml configuration file with any new config provided.
*/
function configExample(externalConfig: any = {}, configFile?: string, location?: string) {
export function configExample(externalConfig: any = {}, configFile?: string, location?: string) {
let config = {};
if (location && configFile) {
const locationFile = path.join(location, configFile);
@@ -19,4 +26,54 @@ function configExample(externalConfig: any = {}, configFile?: string, location?:
return { ...externalConfig, ...config };
}
export { configExample };
export function generateRandomStorage() {
const tempStorage = pseudoRandomBytes(5).toString('hex');
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), '/verdaccio-test'));
return path.join(tempRoot, tempStorage);
}
export const getConfig = (file, override: Partial<ConfigYaml> = {}): Config => {
const config = new Config(
configExample(
{
...getDefaultConfig(),
storage: generateRandomStorage(),
...override,
},
`./fixtures/config/${file}`,
__dirname
)
);
return config;
};
export const defaultRequestOptions = {
host: 'localhost',
protocol: 'http',
headers: {},
};
export const executeStarPackage = async (
storage,
options: {
users: PackageUsers;
username: string;
name: string;
_rev: string;
_id?: string;
}
) => {
const { name, _rev, _id, users, username } = options;
const starManifest = {
_rev,
_id,
users,
};
return storage.updateManifest(starManifest, {
signal: new AbortController().signal,
name,
uplinksLook: true,
revision: '1',
requestOptions: { ...defaultRequestOptions, username },
});
};

View File

@@ -0,0 +1,68 @@
import { beforeEach, describe, expect, test } from 'vitest';
import { checkFunctionIsPromise, promisifiedCallbackFunction } from '../src/lib/legacy-utils';
describe('utils', () => {
class MyClass {
asyncFunction(): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => {
resolve('I am a promise');
}, 1000);
});
}
readPackage(pkgName: string, callback: (error: any, result: string) => void): void {
setTimeout(() => {
if (pkgName === 'error') {
callback(new Error('Package not found'), null);
} else {
callback(null, `Package ${pkgName} data`);
}
}, 1000);
}
}
describe('checkFunctionIsPromise', () => {
let myInstance: MyClass;
beforeEach(() => {
myInstance = new MyClass();
});
test('should identify asyncFunction as "Promise"', () => {
expect(checkFunctionIsPromise(myInstance, 'asyncFunction')).toBeTruthy();
});
test('should throw an error if method is not a function', () => {
expect(checkFunctionIsPromise(myInstance, 'nonExistentFunction' as any)).toBeFalsy();
});
});
describe('promisifiedCallbackFunction', () => {
let myInstance: MyClass;
beforeEach(() => {
myInstance = new MyClass();
});
test('should reject if method is not a function', async () => {
await expect(
promisifiedCallbackFunction(myInstance, 'nonExistentFunction' as any)
).rejects.toThrow('nonExistentFunction is not a function on the given instance.');
});
test('should resolve with the correct value for readPackage when no error', async () => {
await expect(
promisifiedCallbackFunction(myInstance, 'readPackage', 'examplePackage')
).resolves.toBe('Package examplePackage data');
});
test('should reject with an error for readPackage when there is an error', async () => {
await expect(promisifiedCallbackFunction(myInstance, 'readPackage', 'error')).rejects.toThrow(
'Package not found'
);
});
// Additional tests to cover other cases can be added here
});
});

View File

@@ -1,3 +1,5 @@
import { describe, expect, test } from 'vitest';
import { Manifest } from '@verdaccio/types';
import { generatePackageMetadata } from '../../api/node_modules/@verdaccio/test-helper/build';

View File

@@ -1,3 +1,5 @@
import { describe, expect, test } from 'vitest';
import { DIST_TAGS } from '@verdaccio/core';
import { Manifest } from '@verdaccio/types';

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,90 @@
import MockDate from 'mockdate';
import nock from 'nock';
import path from 'path';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { Config, getDefaultConfig } from '@verdaccio/config';
import { DIST_TAGS } from '@verdaccio/core';
import { setup } from '@verdaccio/logger';
import { generatePackageMetadata } from '@verdaccio/test-helper';
import { Manifest } from '@verdaccio/types';
import { Storage } from '../src';
import { configExample, generateRandomStorage, getConfig } from './helpers';
const logger = setup({ type: 'stdout', format: 'pretty', level: 'trace' });
const pluginsPartialsFolder = path.join(__dirname, './fixtures/plugins');
describe('storage plugin', () => {
beforeEach(() => {
nock.cleanAll();
nock.abortPendingRequests();
vi.clearAllMocks();
});
describe('Plugin Legacy Support', () => {
test('should return no results from a legacy plugin', async () => {
const configJSON = getConfig('storage/plugin-legacy.yaml');
const config = new Config(
configExample({
...configJSON,
plugins: pluginsPartialsFolder,
storage: generateRandomStorage(),
})
);
const storage = new Storage(config, logger);
await storage.init(config);
await expect(storage.getLocalDatabase()).resolves.toHaveLength(1);
});
test('create private package', async () => {
const mockDate = '2018-01-14T11:17:40.712Z';
MockDate.set(mockDate);
const configJSON = getConfig('storage/plugin-publish-legacy.yaml');
const pkgName = 'upstream';
const requestOptions = {
host: 'localhost',
protocol: 'http',
headers: {},
};
const config = new Config(
configExample({
...getDefaultConfig(),
...configJSON,
plugins: pluginsPartialsFolder,
storage: generateRandomStorage(),
})
);
const storage = new Storage(config, logger);
await storage.init(config);
const bodyNewManifest = generatePackageMetadata(pkgName, '1.0.0');
await storage.updateManifest(bodyNewManifest, {
signal: new AbortController().signal,
name: pkgName,
uplinksLook: true,
revision: '1',
requestOptions,
});
const manifest = (await storage.getPackageByOptions({
name: pkgName,
uplinksLook: true,
requestOptions,
})) as Manifest;
expect(manifest.name).toEqual(pkgName);
expect(manifest._id).toEqual(pkgName);
expect(Object.keys(manifest.versions)).toEqual(['1.0.0']);
expect(manifest.time).toEqual({
'1.0.0': mockDate,
created: mockDate,
modified: mockDate,
});
expect(manifest[DIST_TAGS]).toEqual({ latest: '1.0.0' });
// verdaccio keeps latest version of readme on manifest level but not by version
expect(manifest.versions['1.0.0'].readme).not.toBeDefined();
expect(manifest.readme).toEqual('# test');
expect(manifest._attachments).toEqual({});
expect(typeof manifest._rev).toBeTruthy();
});
});
});

View File

@@ -1,4 +1,5 @@
import nock from 'nock';
import { describe, expect, test } from 'vitest';
import { Config, getDefaultConfig } from '@verdaccio/config';
import { fileUtils, searchUtils } from '@verdaccio/core';

View File

@@ -1,101 +1,33 @@
import { pseudoRandomBytes } from 'crypto';
import fs from 'fs';
import MockDate from 'mockdate';
import nock from 'nock';
import * as httpMocks from 'node-mocks-http';
import os from 'os';
import path from 'path';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { Config, getDefaultConfig } from '@verdaccio/config';
import {
API_ERROR,
API_MESSAGE,
DIST_TAGS,
HEADERS,
HEADER_TYPE,
errorUtils,
fileUtils,
} from '@verdaccio/core';
import { API_ERROR, API_MESSAGE, DIST_TAGS, HEADERS, errorUtils, fileUtils } from '@verdaccio/core';
import { setup } from '@verdaccio/logger';
import {
addNewVersion,
generateLocalPackageMetadata,
generatePackageMetadata,
generateRemotePackageMetadata,
getDeprecatedPackageMetadata,
} from '@verdaccio/test-helper';
import {
AbbreviatedManifest,
Author,
ConfigYaml,
Manifest,
PackageUsers,
Version,
} from '@verdaccio/types';
import { AbbreviatedManifest, Author, Manifest, Version } from '@verdaccio/types';
import { Storage } from '../src';
import manifestFooRemoteNpmjs from './fixtures/manifests/foo-npmjs.json';
import { configExample } from './helpers';
function generateRandomStorage() {
const tempStorage = pseudoRandomBytes(5).toString('hex');
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), '/verdaccio-test'));
return path.join(tempRoot, tempStorage);
}
import {
configExample,
defaultRequestOptions,
domain,
executeStarPackage,
generateRandomStorage,
getConfig,
} from './helpers';
const logger = setup({ type: 'stdout', format: 'pretty', level: 'trace' });
const domain = 'https://registry.npmjs.org';
const fakeHost = 'localhost:4873';
const fooManifest = generatePackageMetadata('foo', '1.0.0');
const getConfig = (file, override: Partial<ConfigYaml> = {}): Config => {
const config = new Config(
configExample(
{
...getDefaultConfig(),
storage: generateRandomStorage(),
...override,
},
`./fixtures/config/${file}`,
__dirname
)
);
return config;
};
const defaultRequestOptions = {
host: 'localhost',
protocol: 'http',
headers: {},
};
const executeStarPackage = async (
storage,
options: {
users: PackageUsers;
username: string;
name: string;
_rev: string;
_id?: string;
}
) => {
const { name, _rev, _id, users, username } = options;
const starManifest = {
_rev,
_id,
users,
};
return storage.updateManifest(starManifest, {
signal: new AbortController().signal,
name,
uplinksLook: true,
revision: '1',
requestOptions: { ...defaultRequestOptions, username },
});
};
const executeChangeOwners = async (
storage,
options: {
@@ -125,10 +57,10 @@ describe('storage', () => {
beforeEach(() => {
nock.cleanAll();
nock.abortPendingRequests();
jest.clearAllMocks();
vi.clearAllMocks();
});
describe('updateManifest', () => {
describe('publishing commands', () => {
describe('publishing', () => {
test('create private package', async () => {
const mockDate = '2018-01-14T11:17:40.712Z';
@@ -181,6 +113,7 @@ describe('storage', () => {
});
// TODO: Review triggerUncaughtException exception on abort
// is not working as expected, throws but crash the test
test.skip('abort creating a private package', async () => {
const mockDate = '2018-01-14T11:17:40.712Z';
MockDate.set(mockDate);
@@ -682,7 +615,6 @@ describe('storage', () => {
_rev: bodyNewManifest._rev,
_id: bodyNewManifest._id,
name: pkgName,
// @ts-expect-error
username: undefined,
users: { fooUser: true },
})
@@ -887,758 +819,53 @@ describe('storage', () => {
}
);
});
});
describe('getTarball', () => {
test('should get a package from local storage', (done) => {
const pkgName = 'foo';
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
})
);
const storage = new Storage(config, logger);
storage.init(config).then(() => {
const ac = new AbortController();
const bodyNewManifest = generatePackageMetadata(pkgName, '1.0.0');
storage
.updateManifest(bodyNewManifest, {
signal: ac.signal,
name: pkgName,
uplinksLook: false,
requestOptions: defaultRequestOptions,
})
.then(() => {
const abort = new AbortController();
storage
.getTarball(pkgName, `${pkgName}-1.0.0.tgz`, {
signal: abort.signal,
})
.then((stream) => {
stream.on('data', (dat) => {
expect(dat).toBeDefined();
expect(dat.length).toEqual(512);
});
stream.on('end', () => {
done();
});
stream.on('error', () => {
done('this should not happen');
});
});
});
});
});
test('should not found a package anywhere', (done) => {
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
})
);
const storage = new Storage(config, logger);
storage.init(config).then(() => {
const abort = new AbortController();
storage
.getTarball('some-tarball', 'some-tarball-1.0.0.tgz', {
signal: abort.signal,
})
.then((stream) => {
stream.on('error', (err) => {
expect(err).toEqual(errorUtils.getNotFound(API_ERROR.NO_PACKAGE));
done();
});
});
});
});
test('should create a package if tarball is requested and does not exist locally', (done) => {
const pkgName = 'upstream';
const upstreamManifest = generateRemotePackageMetadata(
pkgName,
'1.0.0',
'https://registry.something.org'
);
nock('https://registry.verdaccio.org').get(`/${pkgName}`).reply(201, upstreamManifest);
nock('https://registry.something.org')
.get(`/${pkgName}/-/${pkgName}-1.0.0.tgz`)
// types does not match here with documentation
// @ts-expect-error
.replyWithFile(201, path.join(__dirname, 'fixtures/tarball.tgz'), {
[HEADER_TYPE.CONTENT_LENGTH]: 277,
});
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/getTarball-getupstream.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
storage.init(config).then(() => {
const abort = new AbortController();
storage
.getTarball(pkgName, `${pkgName}-1.0.0.tgz`, {
signal: abort.signal,
})
.then((stream) => {
stream.on('data', (dat) => {
expect(dat).toBeDefined();
});
stream.on('end', () => {
done();
});
stream.on('error', () => {
done('this should not happen');
});
});
});
});
test('should serve fetch tarball from upstream without dist info local', (done) => {
const pkgName = 'upstream';
const upstreamManifest = addNewVersion(
generateRemotePackageMetadata(pkgName, '1.0.0') as Manifest,
'1.0.1'
);
nock('https://registry.verdaccio.org').get(`/${pkgName}`).reply(201, upstreamManifest);
nock('http://localhost:5555')
.get(`/${pkgName}/-/${pkgName}-1.0.1.tgz`)
// types does not match here with documentation
// @ts-expect-error
.replyWithFile(201, path.join(__dirname, 'fixtures/tarball.tgz'), {
[HEADER_TYPE.CONTENT_LENGTH]: 277,
});
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/getTarball-getupstream.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
storage.init(config).then(() => {
const ac = new AbortController();
const bodyNewManifest = generatePackageMetadata(pkgName, '1.0.0');
storage
.updateManifest(bodyNewManifest, {
signal: ac.signal,
name: pkgName,
uplinksLook: true,
revision: '1',
requestOptions: {
host: 'localhost',
protocol: 'http',
headers: {},
},
})
.then(() => {
const abort = new AbortController();
storage
.getTarball(pkgName, `${pkgName}-1.0.1.tgz`, {
signal: abort.signal,
})
.then((stream) => {
stream.on('data', (dat) => {
expect(dat).toBeDefined();
});
stream.on('end', () => {
done();
});
stream.on('error', () => {
done('this should not happen');
});
});
});
});
});
test('should serve fetch tarball from upstream without with info local', (done) => {
const pkgName = 'upstream';
const upstreamManifest = addNewVersion(
addNewVersion(generateRemotePackageMetadata(pkgName, '1.0.0') as Manifest, '1.0.1'),
'1.0.2'
);
nock('https://registry.verdaccio.org')
.get(`/${pkgName}`)
.times(10)
.reply(201, upstreamManifest);
nock('http://localhost:5555')
.get(`/${pkgName}/-/${pkgName}-1.0.0.tgz`)
// types does not match here with documentation
// @ts-expect-error
.replyWithFile(201, path.join(__dirname, 'fixtures/tarball.tgz'), {
[HEADER_TYPE.CONTENT_LENGTH]: 277,
});
const storagePath = generateRandomStorage();
const config = new Config(
configExample(
{
storage: storagePath,
},
'./fixtures/config/getTarball-getupstream.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
storage.init(config).then(() => {
const req = httpMocks.createRequest({
method: 'GET',
connection: { remoteAddress: fakeHost },
headers: {
host: fakeHost,
[HEADERS.FORWARDED_PROTO]: 'http',
},
url: '/',
});
return storage
.getPackageByOptions({
name: pkgName,
uplinksLook: true,
requestOptions: {
headers: req.headers as any,
protocol: req.protocol,
host: req.get('host') as string,
},
})
.then(() => {
const abort = new AbortController();
storage
.getTarball(pkgName, `${pkgName}-1.0.0.tgz`, {
signal: abort.signal,
})
.then((stream) => {
stream.on('data', (dat) => {
expect(dat).toBeDefined();
});
stream.on('end', () => {
done();
});
stream.once('error', () => {
done('this should not happen');
});
});
});
});
});
test('should serve local cache', (done) => {
const pkgName = 'upstream';
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/getTarball-getupstream.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
storage.init(config).then(() => {
const ac = new AbortController();
const bodyNewManifest = generatePackageMetadata(pkgName, '1.0.0');
storage
.updateManifest(bodyNewManifest, {
signal: ac.signal,
name: pkgName,
uplinksLook: true,
revision: '1',
requestOptions: {
host: 'localhost',
protocol: 'http',
headers: {},
},
})
.then(() => {
const abort = new AbortController();
storage
.getTarball(pkgName, `${pkgName}-1.0.0.tgz`, {
signal: abort.signal,
})
.then((stream) => {
stream.on('data', (dat) => {
expect(dat).toBeDefined();
});
stream.on('end', () => {
done();
});
stream.on('error', () => {
done('this should not happen');
});
});
});
});
});
});
describe('syncUplinksMetadata()', () => {
describe('error handling', () => {
test('should handle double failure on uplinks with timeout', async () => {
const fooManifest = generatePackageMetadata('timeout', '8.0.0');
nock('https://registry.timeout.com')
.get(`/${fooManifest.name}`)
.delayConnection(8000)
.reply(201, manifestFooRemoteNpmjs);
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncDoubleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
await expect(
storage.syncUplinksMetadata(fooManifest.name, null, {
retry: { limit: 3 },
timeout: {
request: 1000,
},
})
).rejects.toThrow(API_ERROR.NO_PACKAGE);
}, 18000);
test('should handle one proxy fails', async () => {
const fooManifest = generatePackageMetadata('foo', '8.0.0');
nock('https://registry.verdaccio.org').get('/foo').replyWithError('service in holidays');
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncSingleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
await expect(
storage.syncUplinksMetadata(fooManifest.name, null, {
retry: { limit: 0 },
})
).rejects.toThrow(API_ERROR.NO_PACKAGE);
});
test('should handle one proxy reply 304', async () => {
const fooManifest = generatePackageMetadata('foo-no-data', '8.0.0');
nock('https://registry.verdaccio.org').get('/foo-no-data').reply(304);
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncSingleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
const [manifest] = await storage.syncUplinksMetadata(fooManifest.name, fooManifest, {
retry: { limit: 0 },
});
expect(manifest).toBe(fooManifest);
});
});
describe('success scenarios', () => {
test('should handle one proxy success', async () => {
const fooManifest = generateLocalPackageMetadata('foo', '8.0.0');
nock('https://registry.verdaccio.org').get('/foo').reply(201, manifestFooRemoteNpmjs);
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncSingleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
const [response] = await storage.syncUplinksMetadata(fooManifest.name, fooManifest);
expect(response).not.toBeNull();
expect((response as Manifest).name).toEqual(fooManifest.name);
expect(Object.keys((response as Manifest).versions)).toEqual([
'8.0.0',
'1.0.0',
'0.0.3',
'0.0.4',
'0.0.5',
'0.0.6',
'0.0.7',
]);
expect(Object.keys((response as Manifest).time)).toEqual([
'modified',
'created',
'8.0.0',
'1.0.0',
'0.0.3',
'0.0.4',
'0.0.5',
'0.0.6',
'0.0.7',
]);
expect((response as Manifest)[DIST_TAGS].latest).toEqual('8.0.0');
expect((response as Manifest).time['8.0.0']).toBeDefined();
});
test('should handle one proxy success with no local cache manifest', async () => {
nock('https://registry.verdaccio.org').get('/foo').reply(201, manifestFooRemoteNpmjs);
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncSingleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
const [response] = await storage.syncUplinksMetadata(fooManifest.name, null);
// the latest from the remote manifest
expect(response).not.toBeNull();
expect((response as Manifest).name).toEqual(fooManifest.name);
expect((response as Manifest)[DIST_TAGS].latest).toEqual('0.0.7');
});
test('should handle no proxy found with local cache manifest', async () => {
const fooManifest = generatePackageMetadata('foo', '8.0.0');
nock('https://registry.verdaccio.org').get('/foo').reply(201, manifestFooRemoteNpmjs);
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncNoUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
const [response] = await storage.syncUplinksMetadata(fooManifest.name, fooManifest);
expect(response).not.toBeNull();
expect((response as Manifest).name).toEqual(fooManifest.name);
expect((response as Manifest)[DIST_TAGS].latest).toEqual('8.0.0');
});
test.todo('should handle double proxy with last one success');
});
describe('options', () => {
test('should handle disable uplinks via options.uplinksLook=false with cache', async () => {
const fooManifest = generatePackageMetadata('foo', '8.0.0');
nock('https://registry.verdaccio.org').get('/foo').reply(201, manifestFooRemoteNpmjs);
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncSingleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
const [response] = await storage.syncUplinksMetadata(fooManifest.name, fooManifest, {
uplinksLook: false,
});
expect((response as Manifest).name).toEqual(fooManifest.name);
expect((response as Manifest)[DIST_TAGS].latest).toEqual('8.0.0');
});
test('should handle disable uplinks via options.uplinksLook=false without cache', async () => {
const fooRemoteManifest = generateRemotePackageMetadata(
'foo',
'9.0.0',
'https://registry.verdaccio.org',
['9.0.0', '9.0.1', '9.0.2', '9.0.3']
);
nock('https://registry.verdaccio.org').get('/foo').reply(201, fooRemoteManifest);
const config = new Config(
configExample(
{
describe('tokens', () => {
describe('saveToken', () => {
test('should retrieve tokens created', async () => {
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
},
'./fixtures/config/syncSingleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
const [response] = await storage.syncUplinksMetadata('foo', null, {
uplinksLook: true,
})
);
const storage = new Storage(config, logger);
await storage.init(config);
await storage.saveToken({
user: 'foo',
token: 'secret',
key: 'key',
created: 'created',
readonly: true,
});
const tokens = await storage.readTokens({ user: 'foo' });
expect(tokens).toEqual([
{ user: 'foo', token: 'secret', key: 'key', readonly: true, created: 'created' },
]);
});
expect((response as Manifest).name).toEqual('foo');
expect((response as Manifest)[DIST_TAGS].latest).toEqual('9.0.0');
});
});
});
describe('getLocalDatabase', () => {
test('should return no results', async () => {
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
})
);
const storage = new Storage(config, logger);
await storage.init(config);
await expect(storage.getLocalDatabase()).resolves.toHaveLength(0);
});
test('should return single result', async () => {
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
})
);
const req = httpMocks.createRequest({
method: 'GET',
connection: { remoteAddress: fakeHost },
headers: {
host: 'host',
},
url: '/',
});
const storage = new Storage(config, logger);
await storage.init(config);
const manifest = generatePackageMetadata('foo');
const ac = new AbortController();
await storage.updateManifest(manifest, {
signal: ac.signal,
name: 'foo',
uplinksLook: false,
requestOptions: {
headers: req.headers as any,
protocol: req.protocol,
host: req.get('host') as string,
},
});
const response = await storage.getLocalDatabase();
expect(response).toHaveLength(1);
expect(response[0]).toEqual(expect.objectContaining({ name: 'foo', version: '1.0.0' }));
});
});
describe('tokens', () => {
describe('saveToken', () => {
test('should retrieve tokens created', async () => {
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
})
);
const storage = new Storage(config, logger);
await storage.init(config);
await storage.saveToken({
user: 'foo',
token: 'secret',
key: 'key',
created: 'created',
readonly: true,
test('should delete a token created', async () => {
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
})
);
const storage = new Storage(config, logger);
await storage.init(config);
await storage.saveToken({
user: 'foo',
token: 'secret',
key: 'key',
created: 'created',
readonly: true,
});
const tokens = await storage.readTokens({ user: 'foo' });
expect(tokens).toHaveLength(1);
await storage.deleteToken('foo', 'key');
const tokens2 = await storage.readTokens({ user: 'foo' });
expect(tokens2).toHaveLength(0);
});
const tokens = await storage.readTokens({ user: 'foo' });
expect(tokens).toEqual([
{ user: 'foo', token: 'secret', key: 'key', readonly: true, created: 'created' },
]);
});
test('should delete a token created', async () => {
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
})
);
const storage = new Storage(config, logger);
await storage.init(config);
await storage.saveToken({
user: 'foo',
token: 'secret',
key: 'key',
created: 'created',
readonly: true,
});
const tokens = await storage.readTokens({ user: 'foo' });
expect(tokens).toHaveLength(1);
await storage.deleteToken('foo', 'key');
const tokens2 = await storage.readTokens({ user: 'foo' });
expect(tokens2).toHaveLength(0);
});
});
});
describe('removeTarball', () => {
test('should fail on remove tarball of package does not exist', async () => {
const username = 'foouser';
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
})
);
const storage = new Storage(config, logger);
await storage.init(config);
await expect(storage.removeTarball('foo', 'foo-1.0.0.tgz', 'rev', username)).rejects.toThrow(
API_ERROR.NO_PACKAGE
);
});
});
describe('removePackage', () => {
test('should remove entirely a package', async () => {
const username = 'foouser';
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
})
);
const req = httpMocks.createRequest({
method: 'GET',
connection: { remoteAddress: fakeHost },
headers: {
host: fakeHost,
[HEADERS.FORWARDED_PROTO]: 'http',
},
url: '/',
});
const storage = new Storage(config, logger);
await storage.init(config);
const manifest = generatePackageMetadata('foo');
const ac = new AbortController();
// 1. publish a package
await storage.updateManifest(manifest, {
signal: ac.signal,
name: 'foo',
uplinksLook: false,
requestOptions: {
headers: req.headers as any,
protocol: req.protocol,
host: req.get('host') as string,
},
});
// 2. request package (should be available in the local cache)
const manifest1 = (await storage.getPackageByOptions({
name: 'foo',
uplinksLook: false,
requestOptions: {
headers: req.headers as any,
protocol: req.protocol,
host: req.get('host') as string,
},
})) as Manifest;
const _rev = manifest1._rev;
// 3. remove the tarball
await expect(
storage.removeTarball(manifest1.name, 'foo-1.0.0.tgz', _rev, username)
).resolves.toBeDefined();
// 4. remove the package
await storage.removePackage(manifest1.name, _rev, username);
// 5. fails if package does not exist anymore in storage
await expect(
storage.getPackageByOptions({
name: 'foo',
uplinksLook: false,
requestOptions: {
headers: req.headers as any,
protocol: req.protocol,
host: req.get('host') as string,
},
})
).rejects.toThrow('package does not exist on uplink: foo');
});
test('ok to remove package as non-owner without check', async () => {
const config = getConfig('publishWithOwnerDefault.yaml');
const storage = new Storage(config, logger);
await storage.init(config);
const owner = 'fooUser';
const options = { ...defaultRequestOptions, username: owner };
// 1. publish a package
const bodyNewManifest = generatePackageMetadata('foo', '1.0.0');
await storage.updateManifest(bodyNewManifest, {
signal: new AbortController().signal,
name: 'foo',
uplinksLook: true,
requestOptions: options,
});
// 2. request package (should be available in the local cache)
const manifest1 = (await storage.getPackageByOptions({
name: 'foo',
uplinksLook: false,
requestOptions: options,
})) as Manifest;
const _rev = manifest1._rev;
// 3. remove the tarball as other user
const nonOwner = 'barUser';
await expect(
storage.removeTarball(manifest1.name, 'foo-1.0.0.tgz', _rev, nonOwner)
).resolves.toBeDefined();
// 4. remove the package as other user
await storage.removePackage(manifest1.name, _rev, nonOwner);
// 5. fails if package does not exist anymore in storage
await expect(
storage.getPackageByOptions({
name: 'foo',
uplinksLook: false,
requestOptions: options,
})
).rejects.toThrow('package does not exist on uplink: foo');
});
test('should fail as non-owner with check', async () => {
const config = getConfig('publishWithOwnerAndCheck.yaml');
const storage = new Storage(config, logger);
await storage.init(config);
const owner = 'fooUser';
const options = { ...defaultRequestOptions, username: owner };
// 1. publish a package
const bodyNewManifest = generatePackageMetadata('foo', '1.0.0');
await storage.updateManifest(bodyNewManifest, {
signal: new AbortController().signal,
name: 'foo',
uplinksLook: true,
requestOptions: options,
});
// 2. request package (should be available in the local cache)
const manifest1 = (await storage.getPackageByOptions({
name: 'foo',
uplinksLook: false,
requestOptions: options,
})) as Manifest;
const _rev = manifest1._rev;
// 3. try removing the tarball
const nonOwner = 'barUser';
await expect(
storage.removeTarball(manifest1.name, 'foo-1.0.0.tgz', _rev, nonOwner)
).rejects.toThrow();
// 4. try removing the package
await expect(storage.removePackage(manifest1.name, _rev, nonOwner)).rejects.toThrow();
});
});

View File

@@ -0,0 +1,243 @@
import nock from 'nock';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { Config, getDefaultConfig } from '@verdaccio/config';
import { API_ERROR, DIST_TAGS } from '@verdaccio/core';
import { setup } from '@verdaccio/logger';
import {
generateLocalPackageMetadata,
generatePackageMetadata,
generateRemotePackageMetadata,
} from '@verdaccio/test-helper';
import { Manifest } from '@verdaccio/types';
import { Storage } from '../src';
import manifestFooRemoteNpmjs from './fixtures/manifests/foo-npmjs.json';
import { configExample, generateRandomStorage } from './helpers';
const logger = setup({ type: 'stdout', format: 'pretty', level: 'trace' });
const fooManifest = generatePackageMetadata('foo', '1.0.0');
describe('storage', () => {
beforeEach(() => {
nock.cleanAll();
nock.abortPendingRequests();
vi.clearAllMocks();
});
describe('syncUplinksMetadata()', () => {
describe('error handling', () => {
test('should handle double failure on uplinks with timeout', async () => {
const fooManifest = generatePackageMetadata('timeout', '8.0.0');
nock('https://registry.timeout.com')
.get(`/${fooManifest.name}`)
.delayConnection(8000)
.reply(201, manifestFooRemoteNpmjs);
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncDoubleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
await expect(
storage.syncUplinksMetadata(fooManifest.name, null, {
retry: { limit: 3 },
timeout: {
request: 1000,
},
})
).rejects.toThrow(API_ERROR.NO_PACKAGE);
}, 18000);
test('should handle one proxy fails', async () => {
const fooManifest = generatePackageMetadata('foo', '8.0.0');
nock('https://registry.verdaccio.org').get('/foo').replyWithError('service in holidays');
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncSingleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
await expect(
storage.syncUplinksMetadata(fooManifest.name, null, {
retry: { limit: 0 },
})
).rejects.toThrow(API_ERROR.NO_PACKAGE);
});
test('should handle one proxy reply 304', async () => {
const fooManifest = generatePackageMetadata('foo-no-data', '8.0.0');
nock('https://registry.verdaccio.org').get('/foo-no-data').reply(304);
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncSingleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
const [manifest] = await storage.syncUplinksMetadata(fooManifest.name, fooManifest, {
retry: { limit: 0 },
});
expect(manifest).toBe(fooManifest);
});
});
describe('success scenarios', () => {
test('should handle one proxy success', async () => {
const fooManifest = generateLocalPackageMetadata('foo', '8.0.0');
nock('https://registry.verdaccio.org').get('/foo').reply(201, manifestFooRemoteNpmjs);
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncSingleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
const [response] = await storage.syncUplinksMetadata(fooManifest.name, fooManifest);
expect(response).not.toBeNull();
expect((response as Manifest).name).toEqual(fooManifest.name);
expect(Object.keys((response as Manifest).versions)).toEqual([
'8.0.0',
'1.0.0',
'0.0.3',
'0.0.4',
'0.0.5',
'0.0.6',
'0.0.7',
]);
expect(Object.keys((response as Manifest).time)).toEqual([
'modified',
'created',
'8.0.0',
'1.0.0',
'0.0.3',
'0.0.4',
'0.0.5',
'0.0.6',
'0.0.7',
]);
expect((response as Manifest)[DIST_TAGS].latest).toEqual('8.0.0');
expect((response as Manifest).time['8.0.0']).toBeDefined();
});
test('should handle one proxy success with no local cache manifest', async () => {
nock('https://registry.verdaccio.org').get('/foo').reply(201, manifestFooRemoteNpmjs);
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncSingleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
const [response] = await storage.syncUplinksMetadata(fooManifest.name, null);
// the latest from the remote manifest
expect(response).not.toBeNull();
expect((response as Manifest).name).toEqual(fooManifest.name);
expect((response as Manifest)[DIST_TAGS].latest).toEqual('0.0.7');
});
test('should handle no proxy found with local cache manifest', async () => {
const fooManifest = generatePackageMetadata('foo', '8.0.0');
nock('https://registry.verdaccio.org').get('/foo').reply(201, manifestFooRemoteNpmjs);
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncNoUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
const [response] = await storage.syncUplinksMetadata(fooManifest.name, fooManifest);
expect(response).not.toBeNull();
expect((response as Manifest).name).toEqual(fooManifest.name);
expect((response as Manifest)[DIST_TAGS].latest).toEqual('8.0.0');
});
test.todo('should handle double proxy with last one success');
});
describe('options', () => {
test('should handle disable uplinks via options.uplinksLook=false with cache', async () => {
const fooManifest = generatePackageMetadata('foo', '8.0.0');
nock('https://registry.verdaccio.org').get('/foo').reply(201, manifestFooRemoteNpmjs);
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/syncSingleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
const [response] = await storage.syncUplinksMetadata(fooManifest.name, fooManifest, {
uplinksLook: false,
});
expect((response as Manifest).name).toEqual(fooManifest.name);
expect((response as Manifest)[DIST_TAGS].latest).toEqual('8.0.0');
});
test('should handle disable uplinks via options.uplinksLook=false without cache', async () => {
const fooRemoteManifest = generateRemotePackageMetadata(
'foo',
'9.0.0',
'https://registry.verdaccio.org',
['9.0.0', '9.0.1', '9.0.2', '9.0.3']
);
nock('https://registry.verdaccio.org').get('/foo').reply(201, fooRemoteManifest);
const config = new Config(
configExample(
{
...getDefaultConfig(),
storage: generateRandomStorage(),
},
'./fixtures/config/syncSingleUplinksMetadata.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
await storage.init(config);
const [response] = await storage.syncUplinksMetadata('foo', null, {
uplinksLook: true,
});
expect((response as Manifest).name).toEqual('foo');
expect((response as Manifest)[DIST_TAGS].latest).toEqual('9.0.0');
});
});
});
});

View File

@@ -0,0 +1,332 @@
import nock from 'nock';
import * as httpMocks from 'node-mocks-http';
import path from 'path';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { Config, getDefaultConfig } from '@verdaccio/config';
import { API_ERROR, HEADERS, HEADER_TYPE, errorUtils } from '@verdaccio/core';
import { setup } from '@verdaccio/logger';
import {
addNewVersion,
generatePackageMetadata,
generateRemotePackageMetadata,
} from '@verdaccio/test-helper';
import { Manifest } from '@verdaccio/types';
import { Storage } from '../src';
import { configExample, defaultRequestOptions, generateRandomStorage } from './helpers';
const logger = setup({ type: 'stdout', format: 'pretty', level: 'trace' });
const fakeHost = 'localhost:4873';
describe('storage', () => {
beforeEach(() => {
nock.cleanAll();
nock.abortPendingRequests();
vi.clearAllMocks();
});
describe('getTarball', () => {
test('should get a package from local storage', (done) => {
const pkgName = 'foo';
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
})
);
const storage = new Storage(config, logger);
storage.init(config).then(() => {
const ac = new AbortController();
const bodyNewManifest = generatePackageMetadata(pkgName, '1.0.0');
storage
.updateManifest(bodyNewManifest, {
signal: ac.signal,
name: pkgName,
uplinksLook: false,
requestOptions: defaultRequestOptions,
})
.then(() => {
const abort = new AbortController();
storage
.getTarball(pkgName, `${pkgName}-1.0.0.tgz`, {
signal: abort.signal,
})
.then((stream) => {
stream.on('data', (dat) => {
expect(dat).toBeDefined();
expect(dat.length).toEqual(512);
});
stream.on('end', () => {
done();
});
stream.on('error', () => {
done('this should not happen');
});
});
});
});
});
test('should not found a package anywhere', (done) => {
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
})
);
const storage = new Storage(config, logger);
storage.init(config).then(() => {
const abort = new AbortController();
storage
.getTarball('some-tarball', 'some-tarball-1.0.0.tgz', {
signal: abort.signal,
})
.then((stream) => {
stream.on('error', (err) => {
expect(err).toEqual(errorUtils.getNotFound(API_ERROR.NO_PACKAGE));
done();
});
});
});
});
test('should create a package if tarball is requested and does not exist locally', (done) => {
const pkgName = 'upstream';
const upstreamManifest = generateRemotePackageMetadata(
pkgName,
'1.0.0',
'https://registry.something.org'
);
nock('https://registry.verdaccio.org').get(`/${pkgName}`).reply(201, upstreamManifest);
nock('https://registry.something.org')
.get(`/${pkgName}/-/${pkgName}-1.0.0.tgz`)
// types does not match here with documentation
// @ts-expect-error
.replyWithFile(201, path.join(__dirname, 'fixtures/tarball.tgz'), {
[HEADER_TYPE.CONTENT_LENGTH]: 277,
});
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/getTarball-getupstream.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
storage.init(config).then(() => {
const abort = new AbortController();
storage
.getTarball(pkgName, `${pkgName}-1.0.0.tgz`, {
signal: abort.signal,
})
.then((stream) => {
stream.on('data', (dat) => {
expect(dat).toBeDefined();
});
stream.on('end', () => {
done();
});
stream.on('error', () => {
done('this should not happen');
});
});
});
});
test('should serve fetch tarball from upstream without dist info local', (done) => {
const pkgName = 'upstream';
const upstreamManifest = addNewVersion(
generateRemotePackageMetadata(pkgName, '1.0.0') as Manifest,
'1.0.1'
);
nock('https://registry.verdaccio.org').get(`/${pkgName}`).reply(201, upstreamManifest);
nock('http://localhost:5555')
.get(`/${pkgName}/-/${pkgName}-1.0.1.tgz`)
// types does not match here with documentation
.replyWithFile(201, path.join(__dirname, 'fixtures/tarball.tgz'), {
[HEADER_TYPE.CONTENT_LENGTH]: 277,
});
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/getTarball-getupstream.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
storage.init(config).then(() => {
const ac = new AbortController();
const bodyNewManifest = generatePackageMetadata(pkgName, '1.0.0');
storage
.updateManifest(bodyNewManifest, {
signal: ac.signal,
name: pkgName,
uplinksLook: true,
revision: '1',
requestOptions: {
host: 'localhost',
protocol: 'http',
headers: {},
},
})
.then(() => {
const abort = new AbortController();
storage
.getTarball(pkgName, `${pkgName}-1.0.1.tgz`, {
signal: abort.signal,
})
.then((stream) => {
stream.on('data', (dat) => {
expect(dat).toBeDefined();
});
stream.on('end', () => {
done();
});
stream.on('error', () => {
done('this should not happen');
});
});
});
});
});
test('should serve fetch tarball from upstream without with info local', (done) => {
const pkgName = 'upstream';
const upstreamManifest = addNewVersion(
addNewVersion(generateRemotePackageMetadata(pkgName, '1.0.0') as Manifest, '1.0.1'),
'1.0.2'
);
nock('https://registry.verdaccio.org')
.get(`/${pkgName}`)
.times(10)
.reply(201, upstreamManifest);
nock('http://localhost:5555')
.get(`/${pkgName}/-/${pkgName}-1.0.0.tgz`)
// types does not match here with documentation
.replyWithFile(201, path.join(__dirname, 'fixtures/tarball.tgz'), {
[HEADER_TYPE.CONTENT_LENGTH]: 277,
});
const storagePath = generateRandomStorage();
const config = new Config(
configExample(
{
storage: storagePath,
},
'./fixtures/config/getTarball-getupstream.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
storage.init(config).then(() => {
const req = httpMocks.createRequest({
method: 'GET',
connection: { remoteAddress: fakeHost },
headers: {
host: fakeHost,
[HEADERS.FORWARDED_PROTO]: 'http',
},
url: '/',
});
return storage
.getPackageByOptions({
name: pkgName,
uplinksLook: true,
requestOptions: {
headers: req.headers as any,
protocol: req.protocol,
host: req.get('host') as string,
},
})
.then(() => {
const abort = new AbortController();
storage
.getTarball(pkgName, `${pkgName}-1.0.0.tgz`, {
signal: abort.signal,
})
.then((stream) => {
stream.on('data', (dat) => {
expect(dat).toBeDefined();
});
stream.on('end', () => {
done();
});
stream.once('error', () => {
done('this should not happen');
});
});
});
});
});
test('should serve local cache', (done) => {
const pkgName = 'upstream';
const config = new Config(
configExample(
{
storage: generateRandomStorage(),
},
'./fixtures/config/getTarball-getupstream.yaml',
__dirname
)
);
const storage = new Storage(config, logger);
storage.init(config).then(() => {
const ac = new AbortController();
const bodyNewManifest = generatePackageMetadata(pkgName, '1.0.0');
storage
.updateManifest(bodyNewManifest, {
signal: ac.signal,
name: pkgName,
uplinksLook: true,
revision: '1',
requestOptions: {
host: 'localhost',
protocol: 'http',
headers: {},
},
})
.then(() => {
const abort = new AbortController();
storage
.getTarball(pkgName, `${pkgName}-1.0.0.tgz`, {
signal: abort.signal,
})
.then((stream) => {
stream.on('data', (dat) => {
expect(dat).toBeDefined();
});
stream.on('end', () => {
done();
});
stream.on('error', () => {
done('this should not happen');
});
});
});
});
});
});
describe('removeTarball', () => {
test('should fail on remove tarball of package does not exist', async () => {
const username = 'foouser';
const config = new Config(
configExample({
...getDefaultConfig(),
storage: generateRandomStorage(),
})
);
const storage = new Storage(config, logger);
await storage.init(config);
await expect(storage.removeTarball('foo', 'foo-1.0.0.tgz', 'rev', username)).rejects.toThrow(
API_ERROR.NO_PACKAGE
);
});
});
});

View File

@@ -1,4 +1,5 @@
import assert from 'assert';
import { describe, expect, test } from 'vitest';
import {
getVersion,
@@ -118,7 +119,7 @@ describe('versions-utils', () => {
});
describe('removeLowerVersions', () => {
it('should remove lower semantic versions', () => {
test('should remove lower semantic versions', () => {
const inputArray = [
{ package: { name: 'object1', version: '1.0.0' } },
{ package: { name: 'object1', version: '2.0.0' } }, // Duplicate name 'object1'
@@ -140,7 +141,7 @@ describe('versions-utils', () => {
expect(result).toEqual(expectedOutput);
});
it('should remove lower semantic versions 2', () => {
test('should remove lower semantic versions 2', () => {
const inputArray = [
{ package: { name: 'object1', version: '1.0.0' } },
{ package: { name: 'object1', version: '2.0.0' } }, // Duplicate name 'object1'

View File

@@ -2,7 +2,8 @@
"extends": "../../tsconfig.reference.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./build"
"outDir": "./build",
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["src/**/*.test.ts"],

View File

@@ -3,11 +3,11 @@
{
"id": 558752,
"login": "juanpicado",
"contributions": 5332,
"contributions": 5333,
"repositories": [
{
"name": "verdaccio",
"contributions": 2966
"contributions": 2967
},
{
"name": "verdaccio-cookbook",
@@ -302,11 +302,11 @@
{
"id": 59966492,
"login": "mbtools",
"contributions": 61,
"contributions": 62,
"repositories": [
{
"name": "verdaccio",
"contributions": 61
"contributions": 62
}
]
},
@@ -5066,7 +5066,7 @@
"full_name": "verdaccio/verdaccio",
"html_url": "https://github.com/verdaccio/verdaccio",
"description": "📦🔐 A lightweight Node.js private proxy registry",
"stargazers_count": 16280,
"stargazers_count": 16288,
"archived": false
},
{

View File

@@ -19,7 +19,6 @@ const PKG_GH1312 = 'pkg-gh1312';
function isCached(pkgName, tarballName) {
const pathCached = path.join(__dirname, STORAGE, pkgName, tarballName);
console.log('isCached =>', pathCached);
return fs.existsSync(pathCached);
}

View File

@@ -7,7 +7,7 @@ Verdaccio is a Node.js private and proxy registry. To install it, you need a few
## Prerequisites {#prerequisites}
1. **Node.js** `v16` or higher.
1. **Node.js** `v18` or higher.
2. Your favorite Node Package Manager `npm`, `pnpm` or `yarn` (classic and modern).

View File

@@ -6,7 +6,7 @@ const lgnMapping = {
'de-DE': 'de',
'pl-PL': 'pl',
'cs-CZ': 'cs',
'ga-IE': 'ga-IE',
// 'ga-IE': 'ga-IE',
'fr-FR': 'fr',
'it-IT': 'it',
'ru-RU': 'ru',
@@ -54,7 +54,7 @@ const locales = filterByProgress([
'es-ES',
'fr-FR',
'it-IT',
'ga-IE',
// 'ga-IE',
'pl-PL',
'pt-BR',
'ru-RU',
@@ -75,7 +75,7 @@ const i18nConfig = {
'it-IT': { label: `Italiano (${progress['it'].translationProgress}%)` },
'es-ES': { label: `Español (${progress['es-ES'].translationProgress}%)` },
'de-DE': { label: `Deutsch (${progress['de'].translationProgress}%)` },
'ga-IE': { label: `Gaeilge (Éire) (${progress['ga-IE'].translationProgress}%)` },
// 'ga-IE': { label: `Gaeilge (Éire) (${progress['ga-IE'].translationProgress}%)` },
'cs-CZ': { label: `Čeština (Česko) (${progress['cs'].translationProgress}%)` },
'fr-FR': { label: `Français (${progress['fr'].translationProgress}%)` },
'pl-PL': { label: `Polski (Polska) (${progress['pl'].translationProgress}%)` },
@@ -415,18 +415,10 @@ module.exports = {
}
return `https://github.com/verdaccio/verdaccio/edit/master/website/docs/${docPath}`;
},
lastVersion: '5.x',
// onlyIncludeVersions: ['next', '5.x', '6.x'],
lastVersion: '6.x',
versions: {
// current: {
// label: `next`,
// },
'6.x': {
label: `6.x`,
banner: 'unreleased',
},
'5.x': {
label: `5.x`,
},
},
},

View File

@@ -10,7 +10,7 @@
"bundled": true,
"description": "Verdaccio Middleware plugin to bypass npmjs audit",
"latest": "10.2.4",
"downloads": 771521,
"downloads": 807400,
"registry": "https://registry.npmjs.org/verdaccio-audit"
},
{
@@ -21,7 +21,7 @@
"bundled": true,
"description": "Local storage implementation",
"latest": "10.3.4",
"downloads": 417312,
"downloads": 429807,
"registry": "https://registry.npmjs.org/@verdaccio/local-storage"
},
{
@@ -32,7 +32,7 @@
"bundled": true,
"description": "Verdaccio User Interface",
"latest": "3.4.1",
"downloads": 771492,
"downloads": 807157,
"registry": "https://registry.npmjs.org/@verdaccio/ui-theme"
},
{
@@ -43,7 +43,7 @@
"bundled": false,
"description": "Storage implementation in memory",
"latest": "10.3.2",
"downloads": 26203,
"downloads": 27431,
"registry": "https://registry.npmjs.org/verdaccio-memory"
},
{
@@ -54,7 +54,7 @@
"bundled": false,
"description": "AWS S3 storage implementation for Verdaccio",
"latest": "10.4.0",
"downloads": 1665,
"downloads": 1609,
"registry": "https://registry.npmjs.org/verdaccio-aws-s3-storage"
},
{
@@ -65,7 +65,7 @@
"bundled": false,
"description": "Google Cloud storage implementation for Verdaccio",
"latest": "10.2.1",
"downloads": 6546,
"downloads": 6703,
"registry": "https://registry.npmjs.org/verdaccio-google-cloud"
},
{
@@ -76,7 +76,7 @@
"bundled": false,
"description": "Auth plugin for Verdaccio that keeps users in memory",
"latest": "10.2.2",
"downloads": 73866,
"downloads": 80516,
"registry": "https://registry.npmjs.org/verdaccio-auth-memory"
},
{
@@ -87,7 +87,7 @@
"bundled": true,
"description": "htpasswd auth plugin for Verdaccio",
"latest": "10.5.5",
"downloads": 772645,
"downloads": 808573,
"registry": "https://registry.npmjs.org/verdaccio-htpasswd"
},
{
@@ -98,7 +98,7 @@
"bundled": false,
"description": "plugin for filtering packages with security purposes",
"latest": "1.1.0",
"downloads": 19,
"downloads": 18,
"registry": "https://registry.npmjs.org/verdaccio-plugin-secfilter"
},
{
@@ -120,7 +120,7 @@
"origin": "community",
"category": "authentication",
"latest": "1.2.13",
"downloads": 31,
"downloads": 29,
"registry": "https://registry.npmjs.org/@playerdata/verdaccio-storage-expiry"
},
{
@@ -142,7 +142,7 @@
"origin": "community",
"category": "authentication",
"latest": "3.0.1",
"downloads": 70,
"downloads": 68,
"registry": "https://registry.npmjs.org/verdaccio-bitbucket"
},
{
@@ -153,7 +153,7 @@
"origin": "community",
"category": "authentication",
"latest": "1.0.3",
"downloads": 13,
"downloads": 12,
"registry": "https://registry.npmjs.org/verdaccio-redis-search-patch"
},
{
@@ -164,7 +164,7 @@
"origin": "community",
"category": "authentication",
"latest": "2.0.6",
"downloads": 16,
"downloads": 15,
"registry": "https://registry.npmjs.org/verdaccio-auther-memory"
},
{
@@ -175,7 +175,7 @@
"origin": "community",
"category": "authentication",
"latest": "0.1.100",
"downloads": 416,
"downloads": 404,
"registry": "https://registry.npmjs.org/verdaccio-git"
},
{
@@ -186,7 +186,7 @@
"origin": "community",
"category": "authentication",
"latest": "6.0.0",
"downloads": 320,
"downloads": 334,
"registry": "https://registry.npmjs.org/verdaccio-ldap"
},
{
@@ -197,7 +197,7 @@
"origin": "community",
"category": "authentication",
"latest": "1.0.6",
"downloads": 19,
"downloads": 18,
"registry": "https://registry.npmjs.org/verdaccio-ldap-node"
},
{
@@ -208,7 +208,7 @@
"origin": "community",
"category": "authentication",
"latest": "1.0.0",
"downloads": 5,
"downloads": 4,
"registry": "https://registry.npmjs.org/verdaccio-badger"
},
{
@@ -219,7 +219,7 @@
"origin": "community",
"category": "authentication",
"latest": "10.3.2",
"downloads": 5,
"downloads": 4,
"registry": "https://registry.npmjs.org/@hamstudy/verdaccio-aws-s3-storage-sse"
},
{
@@ -241,7 +241,7 @@
"origin": "community",
"category": "authentication",
"latest": "1.0.5",
"downloads": 20,
"downloads": 19,
"registry": "https://registry.npmjs.org/verdaccio-github-auth"
},
{
@@ -252,7 +252,7 @@
"origin": "community",
"category": "authentication",
"latest": "3.0.1",
"downloads": 159,
"downloads": 157,
"registry": "https://registry.npmjs.org/verdaccio-gitlab"
},
{
@@ -263,7 +263,7 @@
"origin": "community",
"category": "authentication",
"latest": "1.3.4",
"downloads": 40,
"downloads": 39,
"registry": "https://registry.npmjs.org/verdaccio-bitbucket-server"
},
{
@@ -274,7 +274,7 @@
"origin": "community",
"category": "authentication",
"latest": "1.0.7",
"downloads": 40,
"downloads": 41,
"registry": "https://registry.npmjs.org/verdaccio-package-count"
},
{
@@ -307,7 +307,7 @@
"origin": "community",
"category": "authentication",
"latest": "1.1.8",
"downloads": 20,
"downloads": 19,
"registry": "https://registry.npmjs.org/verdaccio-dynamodb"
},
{
@@ -318,7 +318,7 @@
"origin": "community",
"category": "authentication",
"latest": "0.2.5",
"downloads": 87,
"downloads": 86,
"registry": "https://registry.npmjs.org/verdaccio-minio"
},
{
@@ -329,7 +329,7 @@
"origin": "community",
"category": "authentication",
"latest": "1.2.4",
"downloads": 43,
"downloads": 47,
"registry": "https://registry.npmjs.org/verdaccio-redis-storage"
},
{
@@ -340,7 +340,7 @@
"origin": "community",
"category": "authentication",
"latest": "1.2.0",
"downloads": 23,
"downloads": 20,
"registry": "https://registry.npmjs.org/verdaccio-mongodb"
},
{
@@ -374,7 +374,7 @@
"url": "https://www.npmjs.org/verdaccio-storage-proxy",
"registry": "https://registry.npmjs.org/verdaccio-storage-proxy",
"latest": "0.0.11",
"downloads": 32
"downloads": 34
},
{
"name": "verdaccio-local-storage-advance",
@@ -385,7 +385,7 @@
"url": "https://www.npmjs.org/verdaccio-local-storage-advance",
"registry": "https://registry.npmjs.org/verdaccio-local-storage-advance",
"latest": "0.0.10",
"downloads": 12
"downloads": 10
},
{
"name": "verdaccio-kuzzle",
@@ -407,7 +407,7 @@
"url": "https://www.npmjs.org/verdaccio-dist-tag-control",
"registry": "https://registry.npmjs.org/verdaccio-dist-tag-control",
"latest": "1.0.2",
"downloads": 13
"downloads": 12
},
{
"name": "verdaccio-doreamon-oauth2",
@@ -429,7 +429,7 @@
"url": "https://www.npmjs.org/@outcome-co/verdaccio-google-cloud",
"registry": "https://registry.npmjs.org/@outcome-co/verdaccio-google-cloud",
"latest": "1.1.8",
"downloads": 34
"downloads": 33
},
{
"name": "verdaccio-pg-storage",
@@ -440,7 +440,7 @@
"url": "https://www.npmjs.org/verdaccio-pg-storage",
"registry": "https://registry.npmjs.org/verdaccio-pg-storage",
"latest": "1.0.3",
"downloads": 12
"downloads": 7
},
{
"name": "verdaccio-local-storage-with-cache-db",
@@ -451,7 +451,7 @@
"url": "https://www.npmjs.org/verdaccio-local-storage-with-cache-db",
"registry": "https://registry.npmjs.org/verdaccio-local-storage-with-cache-db",
"latest": "9.7.7",
"downloads": 12
"downloads": 11
},
{
"name": "verdaccio-offline-storage",
@@ -462,7 +462,7 @@
"url": "https://www.npmjs.org/verdaccio-offline-storage",
"registry": "https://registry.npmjs.org/verdaccio-offline-storage",
"latest": "2.0.0",
"downloads": 31
"downloads": 28
},
{
"name": "verdaccio-aliyunoss-storage",
@@ -473,7 +473,7 @@
"url": "https://www.npmjs.org/verdaccio-aliyunoss-storage",
"registry": "https://registry.npmjs.org/verdaccio-aliyunoss-storage",
"latest": "1.0.10",
"downloads": 24
"downloads": 21
},
{
"name": "verdaccio-openid-connect",
@@ -484,7 +484,7 @@
"url": "https://www.npmjs.org/verdaccio-openid-connect",
"registry": "https://registry.npmjs.org/verdaccio-openid-connect",
"latest": "2.0.0",
"downloads": 80
"downloads": 81
},
{
"name": "verdaccio-github-oauth-ui",
@@ -505,7 +505,7 @@
"url": "https://www.npmjs.org/verdaccio-github-oauth",
"registry": "https://registry.npmjs.org/verdaccio-github-oauth",
"latest": "1.1.0",
"downloads": 19
"downloads": 18
},
{
"name": "verdaccio-auth-gitlab",
@@ -516,7 +516,7 @@
"url": "https://www.npmjs.org/verdaccio-auth-gitlab",
"registry": "https://registry.npmjs.org/verdaccio-auth-gitlab",
"latest": "2.0.0-beta.11",
"downloads": 54
"downloads": 56
},
{
"name": "verdaccio-auth0-ui",
@@ -527,7 +527,7 @@
"url": "https://www.npmjs.org/verdaccio-auth0-ui",
"registry": "https://registry.npmjs.org/verdaccio-auth0-ui",
"latest": "4.0.1",
"downloads": 46
"downloads": 39
},
{
"name": "verdaccio-tagauth",
@@ -548,7 +548,7 @@
"url": "https://www.npmjs.org/verdaccio-gitea-auth",
"registry": "https://registry.npmjs.org/verdaccio-gitea-auth",
"latest": "0.1.4",
"downloads": 10
"downloads": 12
},
{
"name": "verdaccio-platformatic-auth",
@@ -570,7 +570,7 @@
"url": "https://www.npmjs.org/verdaccio-google-oauth",
"registry": "https://registry.npmjs.org/verdaccio-google-oauth",
"latest": "1.0.1",
"downloads": 13
"downloads": 12
},
{
"name": "verdaccio-passport-google-oauth-ui",
@@ -581,7 +581,7 @@
"url": "https://www.npmjs.org/verdaccio-passport-google-oauth-ui",
"registry": "https://registry.npmjs.org/verdaccio-passport-google-oauth-ui",
"latest": "0.1.3",
"downloads": 28
"downloads": 27
},
{
"name": "verdaccio-aukilabs-npm-auth",
@@ -592,7 +592,7 @@
"url": "https://www.npmjs.org/verdaccio-aukilabs-npm-auth",
"registry": "https://registry.npmjs.org/verdaccio-aukilabs-npm-auth",
"latest": "0.0.2",
"downloads": 8
"downloads": 7
},
{
"name": "verdaccio-gitlab-hilio",
@@ -603,7 +603,7 @@
"url": "https://www.npmjs.org/verdaccio-gitlab-hilio",
"registry": "https://registry.npmjs.org/verdaccio-gitlab-hilio",
"latest": "1.1.17",
"downloads": 38
"downloads": 37
},
{
"name": "verdaccio-auth-knex",
@@ -614,7 +614,7 @@
"url": "https://www.npmjs.org/verdaccio-auth-knex",
"registry": "https://registry.npmjs.org/verdaccio-auth-knex",
"latest": "1.0.3",
"downloads": 12
"downloads": 11
},
{
"name": "verdaccio-qnapldap",
@@ -636,7 +636,7 @@
"url": "https://www.npmjs.org/verdaccio-fast-ldap",
"registry": "https://registry.npmjs.org/verdaccio-fast-ldap",
"latest": "4.2.1",
"downloads": 5
"downloads": 4
},
{
"name": "verdaccio-gitlab-oauth",
@@ -647,7 +647,7 @@
"url": "https://www.npmjs.org/verdaccio-gitlab-oauth",
"registry": "https://registry.npmjs.org/verdaccio-gitlab-oauth",
"latest": "1.0.4",
"downloads": 33
"downloads": 32
},
{
"name": "verdaccio-group-htpasswd",
@@ -658,7 +658,7 @@
"url": "https://www.npmjs.org/verdaccio-group-htpasswd",
"registry": "https://registry.npmjs.org/verdaccio-group-htpasswd",
"latest": "1.0.0",
"downloads": 6
"downloads": 5
},
{
"name": "verdaccio-groups",
@@ -669,7 +669,7 @@
"url": "https://www.npmjs.org/verdaccio-groups",
"registry": "https://registry.npmjs.org/verdaccio-groups",
"latest": "1.2.0",
"downloads": 16
"downloads": 14
},
{
"name": "verdaccio-github-token",
@@ -680,7 +680,7 @@
"url": "https://www.npmjs.org/verdaccio-github-token",
"registry": "https://registry.npmjs.org/verdaccio-github-token",
"latest": "1.0.0",
"downloads": 13
"downloads": 12
},
{
"name": "verdaccio-mysql",
@@ -691,7 +691,7 @@
"url": "https://www.npmjs.org/verdaccio-mysql",
"registry": "https://registry.npmjs.org/verdaccio-mysql",
"latest": "1.0.1",
"downloads": 13
"downloads": 12
},
{
"name": "verdaccio-qlchatauth",
@@ -702,7 +702,7 @@
"url": "https://www.npmjs.org/verdaccio-qlchatauth",
"registry": "https://registry.npmjs.org/verdaccio-qlchatauth",
"latest": "0.0.9",
"downloads": 14
"downloads": 13
},
{
"name": "verdaccio-azure-ad-login",
@@ -724,7 +724,7 @@
"url": "https://www.npmjs.org/verdaccio-oidc",
"registry": "https://registry.npmjs.org/verdaccio-oidc",
"latest": "0.0.0-namesquat",
"downloads": 12
"downloads": 11
},
{
"name": "verdaccio-regman",
@@ -735,7 +735,7 @@
"url": "https://www.npmjs.org/verdaccio-regman",
"registry": "https://registry.npmjs.org/verdaccio-regman",
"latest": "1.0.5",
"downloads": 16
"downloads": 15
},
{
"name": "verdaccio-level-auth",
@@ -746,7 +746,7 @@
"url": "https://www.npmjs.org/verdaccio-level-auth",
"registry": "https://registry.npmjs.org/verdaccio-level-auth",
"latest": "1.0.12",
"downloads": 24
"downloads": 23
},
{
"name": "verdaccio-activedirectory-extended",
@@ -768,7 +768,7 @@
"url": "https://www.npmjs.org/verdaccio-acl-plugin",
"registry": "https://registry.npmjs.org/verdaccio-acl-plugin",
"latest": "1.0.1",
"downloads": 7
"downloads": 6
},
{
"name": "verdaccio-auth-bearer",
@@ -779,7 +779,7 @@
"url": "https://www.npmjs.org/verdaccio-auth-bearer",
"registry": "https://registry.npmjs.org/verdaccio-auth-bearer",
"latest": "2.5.0",
"downloads": 6
"downloads": 5
},
{
"name": "verdaccio-steedos",
@@ -790,7 +790,7 @@
"url": "https://www.npmjs.org/verdaccio-steedos",
"registry": "https://registry.npmjs.org/verdaccio-steedos",
"latest": "1.0.0",
"downloads": 7
"downloads": 6
},
{
"name": "verdaccio-sqlite",
@@ -801,7 +801,7 @@
"url": "https://www.npmjs.org/verdaccio-sqlite",
"registry": "https://registry.npmjs.org/verdaccio-sqlite",
"latest": "1.0.2",
"downloads": 10
"downloads": 9
},
{
"name": "verdaccio-simplegroup",
@@ -812,7 +812,7 @@
"url": "https://www.npmjs.org/verdaccio-simplegroup",
"registry": "https://registry.npmjs.org/verdaccio-simplegroup",
"latest": "1.0.2",
"downloads": 12
"downloads": 11
},
{
"name": "verdaccio-betaversion",
@@ -823,7 +823,7 @@
"url": "https://www.npmjs.org/verdaccio-betaversion",
"registry": "https://registry.npmjs.org/verdaccio-betaversion",
"latest": "1.0.3",
"downloads": 19
"downloads": 18
},
{
"name": "verdaccio-auth-username",
@@ -834,7 +834,7 @@
"url": "https://www.npmjs.org/verdaccio-auth-username",
"registry": "https://registry.npmjs.org/verdaccio-auth-username",
"latest": "1.1.2",
"downloads": 19
"downloads": 17
},
{
"name": "verdaccio-apm-login",
@@ -856,7 +856,7 @@
"url": "https://www.npmjs.org/verdaccio-auth-stack",
"registry": "https://registry.npmjs.org/verdaccio-auth-stack",
"latest": "1.0.3",
"downloads": 9
"downloads": 7
},
{
"name": "verdaccio-auth-capi",
@@ -867,7 +867,7 @@
"url": "https://www.npmjs.org/verdaccio-auth-capi",
"registry": "https://registry.npmjs.org/verdaccio-auth-capi",
"latest": "1.0.2",
"downloads": 7
"downloads": 6
},
{
"name": "verdaccio-groupnames",
@@ -878,7 +878,7 @@
"url": "https://www.npmjs.org/verdaccio-groupnames",
"registry": "https://registry.npmjs.org/verdaccio-groupnames",
"latest": "1.1.0",
"downloads": 22
"downloads": 21
},
{
"name": "verdaccio-auth-mongo",
@@ -889,7 +889,7 @@
"url": "https://www.npmjs.org/verdaccio-auth-mongo",
"registry": "https://registry.npmjs.org/verdaccio-auth-mongo",
"latest": "1.0.2",
"downloads": 6
"downloads": 5
},
{
"name": "verdaccio-coauth",
@@ -900,7 +900,7 @@
"url": "https://www.npmjs.org/verdaccio-coauth",
"registry": "https://registry.npmjs.org/verdaccio-coauth",
"latest": "0.0.2",
"downloads": 12
"downloads": 11
},
{
"name": "verdaccio-simpleldap",
@@ -911,7 +911,7 @@
"url": "https://www.npmjs.org/verdaccio-simpleldap",
"registry": "https://registry.npmjs.org/verdaccio-simpleldap",
"latest": "0.1.1",
"downloads": 11
"downloads": 10
},
{
"name": "verdaccio-github-team",
@@ -922,7 +922,7 @@
"url": "https://www.npmjs.org/verdaccio-github-team",
"registry": "https://registry.npmjs.org/verdaccio-github-team",
"latest": "0.1.2",
"downloads": 8
"downloads": 7
},
{
"name": "verdaccio-api-auth",
@@ -933,7 +933,7 @@
"url": "https://www.npmjs.org/verdaccio-api-auth",
"registry": "https://registry.npmjs.org/verdaccio-api-auth",
"latest": "0.0.9",
"downloads": 26
"downloads": 25
},
{
"name": "verdaccio-delegated-auth",
@@ -944,7 +944,7 @@
"url": "https://www.npmjs.org/verdaccio-delegated-auth",
"registry": "https://registry.npmjs.org/verdaccio-delegated-auth",
"latest": "0.1.1",
"downloads": 23
"downloads": 22
},
{
"name": "verdaccio-delegated-basic-auth",
@@ -955,7 +955,7 @@
"url": "https://www.npmjs.org/verdaccio-delegated-basic-auth",
"registry": "https://registry.npmjs.org/verdaccio-delegated-basic-auth",
"latest": "0.0.2",
"downloads": 5
"downloads": 4
},
{
"name": "verdaccio-fixed-token",
@@ -987,7 +987,7 @@
"url": "https://www.npmjs.org/verdaccio-sentryrich",
"registry": "https://registry.npmjs.org/verdaccio-sentryrich",
"latest": "0.1.3",
"downloads": 13
"downloads": 14
},
{
"name": "verdaccio-sentry",
@@ -998,7 +998,7 @@
"url": "https://www.npmjs.org/verdaccio-sentry",
"registry": "https://registry.npmjs.org/verdaccio-sentry",
"latest": "0.0.2-beta",
"downloads": 7
"downloads": 6
},
{
"name": "verdaccio-openmetrics",
@@ -1009,7 +1009,7 @@
"url": "https://www.npmjs.org/verdaccio-openmetrics",
"registry": "https://registry.npmjs.org/verdaccio-openmetrics",
"latest": "1.2.0",
"downloads": 76
"downloads": 90
},
{
"name": "verdaccio-https",
@@ -1020,7 +1020,7 @@
"url": "https://www.npmjs.org/verdaccio-https",
"registry": "https://registry.npmjs.org/verdaccio-https",
"latest": "1.0.11",
"downloads": 25
"downloads": 24
},
{
"name": "verdaccio-badges",
@@ -1031,7 +1031,7 @@
"url": "https://www.npmjs.org/verdaccio-badges",
"registry": "https://registry.npmjs.org/verdaccio-badges",
"latest": "1.1.2",
"downloads": 40
"downloads": 41
},
{
"name": "verdaccio-npm-urls",
@@ -1053,7 +1053,7 @@
"url": "https://www.npmjs.org/verdaccio-static-token",
"registry": "https://registry.npmjs.org/verdaccio-static-token",
"latest": "1.0.1",
"downloads": 264
"downloads": 280
},
{
"name": "verdaccio-apm-server",
@@ -1064,7 +1064,7 @@
"url": "https://www.npmjs.org/verdaccio-apm-server",
"registry": "https://registry.npmjs.org/verdaccio-apm-server",
"latest": "1.0.14",
"downloads": 40
"downloads": 39
},
{
"name": "verdaccio-gae-ah",
@@ -1075,7 +1075,7 @@
"url": "https://www.npmjs.org/verdaccio-gae-ah",
"registry": "https://registry.npmjs.org/verdaccio-gae-ah",
"latest": "0.0.3",
"downloads": 11
"downloads": 10
},
{
"name": "verdaccio-oidc-ui",
@@ -1086,7 +1086,7 @@
"url": "https://www.npmjs.org/verdaccio-oidc-ui",
"registry": "https://registry.npmjs.org/verdaccio-oidc-ui",
"latest": "2.2.7",
"downloads": 33
"downloads": 34
},
{
"name": "verdaccio-github-oauth-ui-without-groups",

View File

@@ -1,56 +0,0 @@
---
id: amazon
title: 'Amazon Web Services'
---
This document describes several approaches for deploying Verdaccio in the AWS cloud.
## EC2 {#ec2}
[CloudFormation template for deploying this stack.](https://github.com/verdaccio/verdaccio/blob/master/contrib/aws/cloudformation-ec2-efs.yaml)
Architecture:
```
Clients
|
| (HTTPS)
v
Application Load Balancer
|
| (HTTP)
v
EC2 Auto Scaling Group (Amazon Linux 2)
Docker image (Verdaccio)
|
| (NFS)
v
Elastic File System
```
Architecture notes:
- Deploy this stack into the region closest to your users for maximum performance.
- We use an auto scaling group primarily for self-healing. The system requirements of Verdaccio are pretty low, so it's unlikely you'll need multiple instances to handle traffic load.
- Because Amazon Linux 2 doesn't include Node, we run Verdaccio as a Docker image rather than natively on the instance. This is faster and more secure than relying on third party package sources for Node.
- Elastic File System is cheap and stateful, and works across AZs. An alternative would be the [third-party S3 storage plugin](https://github.com/remitly/verdaccio-s3-storage).
- For backup, use AWS Backup
Estimated monthly cost for a small installation (in us-east-1):
- ALB (1 LCU average): $22.265/mo
- EC2 (t3.nano): $3.796/mo
- EBS (8gb): $0.80/mo
- EFS (5gb): $1.5/mo
- Data transfer: (10gb): $0.9/mo
- **TOTAL:** Under $30/mo
## ECS {#ecs}
You can deploy Verdaccio as a task with an [ECS Volume](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using_data_volumes.html) for persistent storage.
Note: Fargate doesn't support persistent volumes, so you have to use the S3 storage plugin.
## EKS {#eks}
See the documentation pages on [Kubernetes](kubernetes) and [Docker](docker).

View File

@@ -1,20 +0,0 @@
---
id: ansible
title: 'Ansible'
---
We have a customised solution for `verdaccio` in our organization.
[https://github.com/verdaccio/ansible-verdaccio](https://github.com/verdaccio/ansible-verdaccio)
#### Other options {#other-options}
- Ansible role for Gentoo users: [jirutka/ansible-role-sinopia](https://github.com/jirutka/ansible-role-sinopia).
- Ansible role for Ubuntu users: [jagregory/sinopia-ansible](https://github.com/jagregory/sinopia-ansible).
- ansible-verdaccio-role [https://github.com/refinery29/ansible-verdaccio-role](https://github.com/refinery29/ansible-verdaccio-role)
#### Related talks {#related-talks}
> Only in Spanish
<iframe width="560" height="315" src="https://www.youtube.com/embed/EWAxCgZQMAY?enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

View File

@@ -1,3 +0,0 @@
# 5.x API
Go to [Node-API](https://verdaccio.org/docs/verdaccio-programmatically).

View File

@@ -1,95 +0,0 @@
---
id: articles
title: 'Articles'
---
Below is a list of articles about Verdaccio. If you have written a blog post or tutorial that mentions Verdaccio, feel free to add it here!
> Any language is allowed
## Maintainer Articles {#maintainers-articles}
- [An Introduction to Verdaccio](https://medium.com/@jotadeveloper/an-introduction-to-verdaccio-f6c72e865425)
- [Five use cases where a npm private proxy fits in your workflow](https://medium.com/@jotadeveloper/five-use-cases-where-a-npm-private-proxy-fits-in-your-workflow-632a81779c14)
- [An Introduction to Verdaccio](https://medium.com/@jotadeveloper/an-introduction-to-verdaccio-f6c72e865425)
- [NPM Registry for your organisation](https://medium.com/@ayusharma.in/npm-registry-for-your-organisation-aeb8ea76144)
- [Verdaccio 3 released 🎉!!](https://medium.com/verdaccio/verdaccio-3-released-feb06ef38558)
- [The crazy story of Verdaccio](https://medium.com/verdaccio/the-crazy-story-of-verdaccio-d35d924728bc)
- [Verdaccio 4 alpha release 🚀](https://medium.com/verdaccio/verdaccio-4-alpha-release-400c7ed4884d)
- [Verdaccio and deterministic lock files](https://medium.com/verdaccio/verdaccio-and-deterministic-lock-files-5339d82d611e)
- [Setting up Verdaccio on DigitalOcean](https://medium.com/verdaccio/setting-up-verdaccio-on-digitalocean-61b5d08e4f0d)
- [How I learned React Js and how you can…](https://medium.com/verdaccio/how-i-learned-react-js-and-how-you-can-8663f938426c)
- [How did I fall in the open source world…and that was a nice thing!](https://medium.com/@priscilawebdev/how-do-i-fall-in-the-open-source-world-and-that-was-a-nice-thing-b0e85d05490d)
# Articles / Blogs / Tutorials (by Language)
### Remarkable Articles {#remarkable-articles}
- [Why Private Npm Registries Matter and How Verdaccio Makes It Easy](https://fusebit.io/blog/private-npm-verdaccio/?utm_source=verdaccio.org&utm_medium=referral)
- [Automating package publishing in JavaScript projects](https://blog.codecentric.de/en/2021/02/automating-package-publishing-in-javascript-projects/)
- [10 npm Security Best Practices](https://snyk.io/blog/ten-npm-security-best-practices/)
- [Cover Your Apps While Still Using npm](https://nodesource.com/blog/cover-your-apps-while-still-using-npm/)
- [Containerizing Node.js Applications with Docker](https://nodesource.com/blog/containerizing-node-js-applications-with-docker)
- [Verdaccio - A lightweight npm proxy registry - Interview with Juan Picado](https://survivejs.com/blog/verdaccio-interview/)
- [Host, Publish and Manage Private npm Packages with Verdaccio](https://www.sitepoint.com/private-npm-packages-verdaccio/)
- [Free Private NPM with Verdaccio and AWS](https://medium.com/@odahcam/free-private-npm-with-verdaccio-and-aws-a88e6f0f4beb)
- [Run your own Unity Package Server!](https://medium.com/@markushofer/run-your-own-unity-package-server-b4fe9995704e)
- [Ways to have your private npm registryand a final DIY solution](https://medium.com/engenharia-noalvo/ways-to-have-your-private-npm-registry-and-a-final-diy-solution-eed001a88e74)
- [How to set up a free private npm registry… for Windows](https://medium.com/@Anderson7301/how-to-set-up-a-free-private-npm-registry-for-windows-f532c6a381ce)
- [Setup a Private NPM Server on Azure in 45 Seconds](https://edi.wang/post/2020/7/7/setup-a-private-npm-server-on-azure-in-45-seconds)
### English {#english}
- [Testing your npm package before releasing it using Verdaccio + ngrok](https://medium.com/strapi/testing-your-npm-package-before-releasing-it-using-verdaccio-ngrok-28e2832c850a)
- [Host your own private NPM repository with Verdaccio](https://medium.com/devopslinks/host-your-own-private-npm-repository-with-verdaccio-e8a3202b97c5)
- [Local npm private registry with zero configuration](https://dev.to/iriskatastic/local-npm-private-registry-with-zero-configuration-njo)
- [It depends. On the registry](https://blog.softwaremill.com/it-depends-on-the-registry-8fa9d9c5a3b)
- [Host, Publish and Manage Private npm Packages with Verdaccio](http://allprowebdesigns.com/2017/01/host-publish-and-manage-private-npm-packages-with-verdaccio/)
- [Setting Up a Private NPM Registry](https://gir.me.uk/posts/private-npm-registry.html)
- [Testing NPM alpha / beta / rc packages](https://medium.com/@the1mills/testing-npm-alpha-beta-rc-packages-108b65eb03d2)
- [Running a local npm repository on Windows Server using Verdaccio](https://robertwray.co.uk/blog/running-a-local-npm-repository-on-windows-server-using-verdaccio)
- [Kubernetes private NPM registry](https://medium.com/@tompape/kubernetes-private-npm-registry-fb5f450fa611)
- [Verdaccio examples for Google Cloud and K8s setups. https://github.com/papezt/verdaccio-examples](https://github.com/papezt/verdaccio-examples)
- [Setting up a private NPM Registry Is Easier Than You Think](https://medium.com/@902Labs/setting-up-a-private-npm-registry-is-easier-than-you-think-455e1bd438f2)
### Japanese {#japanese}
- [Verdaccio でプライベート npm リポジトリをサクッと立てる](http://neos21.hatenablog.com/entry/2017/09/08/080000)
- [verdaccio で private な npm リポジトリを作成](https://qiita.com/mtokiwa/items/1bc22a2270e4408d4cdd)
- [Version control of my own UnityPackage with Unity × Verdaccio / Unity×Verdaccio で自作 UnityPackage をバージョン管理する](https://synamon.hatenablog.com/entry/2018/08/15/185607)
### Chinese {#chinese}
- [使用 verdaccio 搭建 npm 私有仓储](https://blog.sigoden.com/verdaccio--private-npm-registry/)
- [Verdaccio一个轻量级的私有 npm 代理注册表sinopia fork)](https://www.ctolib.com/verdaccio-verdaccio.html)
- [npm 私服工具 verdaccio 安装配置试用](http://www.cnblogs.com/rongfengliang/p/7811838.html)
- [搭建私有 npm 镜像](http://www.blackcater.win/2018/03/01/%E6%90%AD%E5%BB%BA%E7%A7%81%E6%9C%89npm%E9%95%9C%E5%83%8F/)
- [搭建离线 npm 私库——verdaccio](https://www.jishux.com/plus/view-765581-1.html)
- [[筆記] 建立自己的 npm, 以 npm Orgs 跟 Verdaccio 為例](https://medium.com/@ceall8650/%E7%AD%86%E8%A8%98-%E5%BB%BA%E7%AB%8B%E8%87%AA%E5%B7%B1%E7%9A%84-npm-%E4%BB%A5npm-orgs%E8%B7%9Fverdaccio%E7%82%BA%E4%BE%8B-cfb83b2307e6)
### French {#french}
- [Installer un registre NPM](https://allons-y.io/wiki/installer-un-registre-npm)
- [Verdaccio - Un registre de paquets npm](https://blog.yoannfleury.dev/verdaccio-un-registre-de-paquets-npm/)
### Spanish {#spanish}
- [NPM privado: instalar y configurar Verdaccio](https://www.todojs.com/npm-privado-con-verdaccio/)
- [NPM privado: 5 razones y 7 recomendaciones para utilizarlo](https://www.todojs.com/npm-privado-5-razones-y-7-recomendaciones/)
### Portuguese-BR {#portuguese-BR}
- [Problemas com pacotes do npm? Verdaccio pode ser a solução](https://dev.to/dxwebster/pt-br-problemas-com-pacotes-do-npm-verdaccio-pode-ser-a-solucao-2966)
### German {#german}
- [Struktur für große Angular-Anwendungen: Microservices, Module, MonoRepo?](https://jaxenter.de/struktur-angular-anwendungen-67467)
- [Angular in einer Microservices-Welt](https://jaxenter.de/angular-microservices-66445)
- [Privates NPM Repository mit Verdaccio (SSL & Docker)](https://blog.zotorn.de/privates-npm-repository-mit-verdaccio-ssl-docker-1/)
## Slides {#slides}
- [Introduction to Verdaccio VueJS Meetup 2018](https://www.slideshare.net/juancarlospicado/introduction-to-verdaccio)
- [Introduction Verdaccio Vienna JS Meetup 2019](https://docs.google.com/presentation/d/1eam_OtXCQh5IVYyia2GHhxVD8tb37B0yIadVa8wxQSk/edit?usp=sharing)
- [Cover Your Apps While Still Using npm](https://www.slideshare.net/TierneyCoren/cover-your-apps-while-still-using-npm)
- [Unity 2018-2019 を見据えた DeNA の Unity 開発のこれから [DeNA TechCon 2019]](https://www.slideshare.net/dena_tech/unity-20182019denaunity-dena-techcon-2019)

View File

@@ -1,86 +0,0 @@
---
id: authentication
title: 'Authentication'
---
The authentication is tied to the auth [plugin](plugins.md) you are using. The package restrictions are also handled by the [Package Access](packages.md).
The client authentication is handled by the `npm` client itself. Once you log in to the application:
```bash
npm adduser --registry http://localhost:4873
```
A token is generated in the `npm` configuration file hosted in your user home folder. For more information about `.npmrc` read the [official documentation](https://docs.npmjs.com/files/npmrc).
```bash
cat .npmrc
registry=http://localhost:5555/
//localhost:5555/:_authToken="secretVerdaccioToken"
//registry.npmjs.org/:_authToken=secretNpmjsToken
```
#### Anonymous publish {#anonymous-publish}
`verdaccio` allows you to enable anonymous publish. To achieve that you will need to correctly set up your [packages access](packages.md).
Eg:
```yaml
'my-company-*':
access: $anonymous
publish: $anonymous
proxy: npmjs
```
As is described [on issue #212](https://github.com/verdaccio/verdaccio/issues/212#issuecomment-308578500) until `npm@5.3.0` and all minor releases **won't allow you publish without a token**.
## Understanding Groups {#understanding-groups}
### The meaning of `$all` and `$anonymous` {#the-meaning-of-all-and-anonymous}
As you know _Verdaccio_ uses `htpasswd` by default. That plugin does not implement the methods `allow_access`, `allow_publish` and `allow_unpublish`.
Thus, _Verdaccio_ will handle that in the following way:
- If you are not logged in (you are anonymous), `$all` and `$anonymous` means exactly the same.
- If you are logged in, `$anonymous` won't be part of your groups and `$all` will match any logged user. A new group `$authenticated` will be added to your group list.
Please note: `$all` **will match all users, whether logged in or not**.
**The previous behavior only applies to the default authentication plugin**. If you are using a custom plugin and such plugin implements
`allow_access`, `allow_publish` or `allow_unpublish`, the resolution of the access depends on the plugin itself. Verdaccio will only set the default groups.
Let's recap:
- **logged in**: `$all` and `$authenticated` + groups added by the plugin.
- **logged out (anonymous)**: `$all` and `$anonymous`.
## Default htpasswd {#default-htpasswd}
In order to simplify the setup, `verdaccio` uses a plugin based on `htpasswd`. Since version v3.0.x the `verdaccio-htpasswd` plugin
is used by default.
```yaml
auth:
htpasswd:
file: ./htpasswd
# Maximum amount of users allowed to register, defaults to "+inf".
# You can set this to -1 to disable registration.
# max_users: 1000
# Hash algorithm, possible options are: "bcrypt", "md5", "sha1", "crypt".
algorithm: bcrypt # by default is crypt, but is recommended use bcrypt for new installations
# Rounds number for "bcrypt", will be ignored for other algorithms.
rounds: 10
```
> The default algorithm is `crypt`, considered not secure for production environments, it's recommended for new installations use `bcrypt` instead. Note after verdaccio 6.x
> the default will be `bcrypt`.
| Property | Type | Required | Example | Support | Description |
| --------- | ------ | -------- | --------------------- | -------- | ---------------------------------------------------------------- |
| file | string | Yes | ./htpasswd | all | file that host the encrypted credentials |
| max_users | number | No | 1000 | all | set limit of users |
| algorithm | string | No | bcrypt/md5/sha1/crypt | >=5.13.0 | set hasing password algorithm |
| rounds | number | No | 10 | >=5.13.0 | Rounds number for "bcrypt", will be ignored for other algorithms |
> In case you decide to prevent users from signing up themselves, you can set `max_users: -1`.

View File

@@ -1,193 +0,0 @@
---
id: best
title: 'Best Practices'
---
The following guide is a list of the best practices collected and that we usually recommend to all users. Do not take this guide as
mandatory, you might pick some of them according your needs.
**Feel free to suggest your best practices to the Verdaccio community**.
## Private Registry {#private-registry}
You can add users and manage which users can access which packages.
It is recommended that you define a prefix for your private packages, for example `local-*` or scoped `@my-company/*`, so all your private things will look like this: `local-foo`. This way you can clearly separate public packages from private ones.
```yaml
packages:
'@my-company/*':
access: $all
publish: $authenticated
'local-*':
access: $all
publish: $authenticated
'@*/*':
access: $all
publish: $authenticated
'**':
access: $all
publish: $authenticated
```
Always remember, **the order of packages access is important**, packages are matched always top to bottom.
### Using public packages from npmjs.org {#using-public-packages-from-npmjsorg}
If a package doesn't exist in the storage, the server will try to fetch it from npmjs.org. If npmjs.org is down, it serves packages from the cache pretending that no other packages exist. **Verdaccio will download only what's needed (requested by clients)**, and this information will be cached, so if the client requests the same thing a second time it can be served without asking npmjs.org for it.
**Example:**
If you successfully request `express@4.0.1` from the server once, you'll be able to do it again (with all of it's dependencies) any time, even if npmjs.org is down. Though note that `express@4.0.0` will not be downloaded until it's actually needed by somebody. And if npmjs.org is offline, the server will say that only `express@4.0.1` (what's in the cache) is published, but nothing else.
### Override public packages {#override-public-packages}
If you want to use a modified version of some public package `foo`, you can just publish it to your local server, so when your type `npm install foo`, **it'll consider installing your version**.
There's two options here:
1. You want to create a separate **fork** and stop synchronizing with public version.
If you want to do that, you should modify your configuration file so Verdaccio won't make requests regarding this package to npmjs anymore. Add a separate entry for this package to `config.yaml` and remove `npmjs` from `proxy` list and restart the server.
```yaml
packages:
'@my-company/*':
access: $all
publish: $authenticated
# comment it out or leave it empty
# proxy:
```
When you publish your package locally, **you should probably start with a version string higher than the existing package** so it won't conflict with that package in the cache.
2. You want to temporarily use your version, but return to the public one as soon as it's updated.
In order to avoid version conflicts, **you should use a custom pre-release suffix of the next patch version**. For example, if a public package has version 0.1.2, you can upload `0.1.3-my-temp-fix`.
```bash
npm version 0.1.3-my-temp-fix
npm publish --tag fix --registry http://localhost:4873
```
This way your package will be used until its original maintainer updates his public package to `0.1.3`.
## Security {#security}
> Security starts in your environment.
<iframe width="560" height="315" src="https://www.youtube.com/embed/qTRADSp3Hpo?enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
Additional reading:
- **[10 npm Security Best Practices](https://snyk.io/blog/ten-npm-security-best-practices/)** and following the steps outlined there.
- **[Avoiding npm substitution attacks](https://github.blog/2021-02-12-avoiding-npm-substitution-attacks/)**
- **[Dependency Confusion: When Are Your npm Packages Vulnerable?](https://blog.includesecurity.com/2021/02/dependency-confusion-when-are-your-npm-packages-vulnerable/)**
- **[Practical Mitigations For Dependency Confusion Attack](https://www.kernelcrypt.com/posts/depedency-confusion-explained/)**
> Feel free to attach here new useful articles to improve the security.
### Strong package access with `$authenticated` {#strong-package-access-with-authenticated}
By default all packages you publish in Verdaccio are accessible for all users. We recommend protecting your registry from external non-authorized users by updating the `access` property of your packages to `$authenticated`.
```yaml
packages:
'@my-company/*':
access: $authenticated
publish: $authenticated
'@*/*':
access: $authenticated
publish: $authenticated
'**':
access: $authenticated
publish: $authenticated
```
That way, **nobody can access your registry unless they are authorized, and private packages won't be displayed in the web interface**.
### Remove `proxy` to increase security at private packages {#remove-proxy-to-increase-security-at-private-packages}
After a clean installation, by default all packages will be resolved to the default uplink (the public registry `npmjs`).
```yaml
packages:
'@*/*':
access: $authenticated
publish: $authenticated
proxy: npmjs
'**':
access: $authenticated
publish: $authenticated
proxy: npmjs
```
This means that even if a private package like `@my-company/auth` is published locally, the server will look up at the public registry. If that's not your intention, remove the `proxy` property and use a configuration like this one:
```yaml
packages:
'@my-company/*':
access: $authenticated
publish: $authenticated
unpublish: $authenticated
'@*/*':
access: $authenticated
publish: $authenticated
proxy: npmjs
'**':
access: $authenticated
publish: $authenticated
proxy: npmjs
```
This will **avoid downloading tarballs, and merge metadata needlessly from external registries**.
## Server {#server}
### Secured Connections {#secured-connections}
Using **HTTPS** is a common recommendation. For this reason we recommend reading the [SSL](ssl.md) section to make Verdaccio secure, or alternatively using an HTTPS [reverse proxy](reverse-proxy.md) on top of Verdaccio.
### Expiring Tokens {#expiring-tokens}
Since `verdaccio@3.x` the tokens have no expiration date. For such reason we introduced in the next `verdaccio@4.x` the JWT feature [PR#896](https://github.com/verdaccio/verdaccio/pull/896)
```yaml
security:
api:
jwt:
sign:
expiresIn: 15d
notBefore: 0
web:
sign:
expiresIn: 1h
```
**Using this configuration will override the current system and you will be able to control how long the token will live**.
Using JWT also improves the performance with authentication plugins. The old system will perform an unpackage and validate the credentials on every request, while JWT will rely on the token signature instead, avoiding the overhead for the plugin.
As a side note, be aware at **npmjs** and the **legacy** verdaccio token never expires\*\* unless you invalidate manually.
### Rate Limit {#rate-limit}
Since version `v5.4.0` critical endpoints have enabled by default rate limit. The following commands are considered user endpoints:
- `npm token` all variants
- `npm login/adduser`
- `npm profile` all supported variants
- User website `/sec/login` endpoint.
The previous list of endpoints are limited to `100` request peer _15 minutes_ which is enough for a basic usage, if you need to increase this levels please check the `userRateLimit` configuration options.
```yaml
userRateLimit:
windowMs: 50000 <- (minutes * 60 * 1000)
max: 1000 (number of request peer windowMs)
```
The website endpoints as, _search_, _packages_, _sidebar_, and _detail_ are protected by default to 5,000 request peer 2 minutes, also configurable via web ui options.
We recommend customize this values to those that addapt your needs to avoid any kind of (DDoS) or _brute-force_ attack to the critical endpoints.
> The CLI API endpoints used by eg `npm install` are not limited at this point since are not considered critical, but if you find any good reason please open a discussion.

View File

@@ -1,75 +0,0 @@
---
id: caching
title: 'Caching strategies'
---
Verdaccio caches all packages by default into the `/storage` folder. But you can decide whether you want to follow
a different strategy. Using of plugins you might use the cloud or any sort of database.
## Caching scenarios {#caching-scenarios}
- Build a Node.js project on **Continuous Integration** (Bamboo, GitLab, Jenkins, etc) servers is a task that might take several times at a day, thus, the server will download tons of tarballs from the registry every time takes place. As usual, the CI tools clear the cache after each build and the process start over and over again. That is a waste of bandwidth and reduces the external traffic.
**You can use Verdaccio for caching tarballs and metadata in our internal network and give a boost in your build time.**
- **Latency and Connectivity**, not all countries enjoy a high-speed connection. For such reason cache packages locally in your network
is really handy. Either if you are traveling, or have a weak connection, roaming or countries with strong Firewalls that might affect the user experience (eg: corrupting tarballs).
- **Offline Mode**, all Node Package Managers nowadays uses their own internal cache, but it common that different projects might use
different tools, which implies lock files and so on. Those tools are unable to share cache, the unique solution is centralized and relies on
a proxy registry, Verdaccio cache all metadata and tarballs are downloaded by demand being able to share them across all your project.
- Avoid that any remote registry suddenly returns _HTTP 404_ error for tarballs were previously available a.k.a ([left-pad issue](https://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/)).
# Strategies for faster builds
> We are looking for more strategies, feel free to share your experience in this field
## Avoid Caching tarballs {#avoid-caching-tarballs}
If you have a limited storage space, you might need to avoid cache tarballs, enabling `cache` false in each
uplink will cache only metadata files.
```
uplinks:
npmjs:
url: https://registry.npmjs.org/
cache: false
```
## Extending Cache Expiration Time {#extending-cache-expiration-time}
Verdaccio by default waits 2 minutes to invalidate the cache metadata before fetching new information from the remote registry.
```yaml
uplinks:
npmjs:
url: https://registry.npmjs.org/
maxage: 30m
```
Increasing the value of `maxage` in each `uplink` remotes will be asked less frequently. This might be a valid strategy if
you don't update dependencies so often.
## Using the memory instead the hardrive {#using-the-memory-instead-the-hardrive}
Sometimes caching packages is not a critical step, rather than route packages from different registries and achieving
faster build times. There are two plugins that avoid write in a physical hard drive at all using the memory.
```bash
npm install -g verdaccio-auth-memory
npm install -g verdaccio-memory
```
The configuration looks like this
```yaml
auth:
auth-memory:
users:
foo:
name: test
password: test
store:
memory:
limit: 1000
```
Remember, once the server is restarted the data is being lost, we recommend this setup in cases where you do not
need to persist at all.

View File

@@ -1,15 +0,0 @@
---
id: chef
title: 'Chef Cookbook'
---
Using Chef Cookbook for Verdaccio
For further information:
- [https://github.com/verdaccio/verdaccio-cookbook](https://github.com/verdaccio/verdaccio-cookbook)
- [https://supermarket.chef.io/cookbooks/verdaccio](https://supermarket.chef.io/cookbooks/verdaccio)
> We are looking for contributors for this repository, if you are interested please notify the author via tickets.
Author: [Keli Grubb](https://github.com/kgrubb) && Barthelemy Vessemont.

View File

@@ -1,14 +0,0 @@
---
id: ci
title: 'Continuous Integration'
---
Verdaccio can be used with continuous integration (CI) platforms to install or publish packages.
When using NPM to install a private package in a CI environment for the first time, you may run
into some issues. The `npm login` command is designed to be used interactively. This poses an
issue in CI, scripts, etc. Below are some articles detailing how to use `npm login` on different
CI platforms.
- [Travis CI](https://remysharp.com/2015/10/26/using-travis-with-private-npm-deps)
- [Circle CI](https://circleci.com/docs/deploy-to-npm-registry)
- [GitHub Actions](https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages)

View File

@@ -1,10 +0,0 @@
---
id: cli-registry
title: 'Using a private registry'
---
Setting up a private registry is quite easy on all major Package managers and can be achieved in a few different ways depenging on your goals. The following links details how you can achieve this goal for each major package manager.
- [npm](setup-npm.md)
- [yarn](setup-yarn.md)
- [pnpm](setup-pnpm.md)

View File

@@ -1,46 +0,0 @@
---
id: cli
title: 'Command Line Tool'
---
The Verdaccio CLI is your tool to start and stop the application.
## Commands {#commands}
```bash
verdaccio --listen 4000 --config ~./config.yaml
```
| Command | Default | Example | Description |
| ------------------ | ------------------------------ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| --listen \ **-l** | http:localhost:4873 | 7000 | Define protocol + host + port ([formats](https://github.com/verdaccio/verdaccio/blob/08c36e688e8635733f92080eb3598239d43259cb/packages/node-api/src/cli-utils.ts#L7-L16)) |
| --config \ **-c** | ~/.local/verdaccio/config.yaml | ~./config.yaml | Set location of the configuration file |
| --info \ **-i** | | | Print local environment information |
| --version \ **-v** | | | Show version information |
## Default config file location {#default-config-file-location}
To locate the home directory, verdaccio relies on **$XDG_DATA_HOME** as a first choice and for Windows environments we look for the [APPDATA environment variable](https://www.howtogeek.com/318177/what-is-the-appdata-folder-in-windows/).
## Config file format {#config-file-format}
Config files should be YAML, JSON or a NodeJS module. YAML format is detected by parsing config file extension (yaml or yml, case insensitive).
## Default storage location {#default-storage-location}
We use the **$XDG_DATA_HOME** environment by variable default to locate the storage by default which [should be the same](https://askubuntu.com/questions/538526/is-home-local-share-the-default-value-for-xdg-data-home-in-ubuntu-14-04) as $HOME/.local/share.
If you are using a custom storage, this location is irrelevant.
You can use `VERDACCIO_STORAGE_PATH` to define an alternative storage path, read more about `VERDACCIO_STORAGE_PATH` [at the environment variables page](env.md#storage-path).
## Default database file location {#default-database-file-location}
The default database file location is in the storage location.
Starting with version 4.0.0, the database file name will be **.verdaccio-db.json** for a new installation of Verdaccio.
When upgrading an existing Verdaccio server, the file name will remain **.sinopia-db.json**.
> The database name `sinopia-db.json` is deprecated and support will be removed after v6.x
## Environment variables {#environment-variables}
[Full list of environment variables](env.md).

View File

@@ -1,436 +0,0 @@
---
id: configuration
title: 'Configuration File'
---
This file is the cornerstone of Verdaccio where you can modify the default behaviour, enable plugins and extend features.
A default configuration file `config.yaml` is created the very first time you run `verdaccio`.
## Default Configuration {#default-configuration}
The default configuration has support for **scoped** packages and allows any user to **access** all packages, but only authenticated users to **publish**.
```yaml
storage: ./storage
auth:
htpasswd:
file: ./htpasswd
uplinks:
npmjs:
url: https://registry.npmjs.org/
packages:
'@*/*':
access: $all
publish: $authenticated
proxy: npmjs
'**':
proxy: npmjs
log: { type: stdout, format: pretty, level: http }
```
## Sections {#sections}
The following sections explain what each property means and their different options.
### Storage {#storage}
Is the location of the default storage. **Verdaccio is by default based on local file system**.
```yaml
storage: ./storage
```
> Released at v5.6.0: The environment variable `VERDACCIO_STORAGE_PATH` could be used to replace the location of the storage (only for the default storage, does not apply to plugins unless it is implemented independently).
### The `.verdaccio-db` database {#.verdaccio-db}
The tiny database is used to store private packages published by the user. The database is based on a JSON file that contains
the list of private packages published and the secret token used for the token signature.
It is created automatically when starting the application for the first time.
The location of the database is based on the `config.yaml` folder location, for instance:
If the `config.yaml` is located in `/some_local_path/config.yaml`, the database will be created in `/some_local_path/storage/.verdaccio-db`.
:::info
For users who have been using Verdaccio for an extended period and the `.verdaccio-db` file already exist the secret
may be **64 characters** long. However, for newer installations, the length will be generated as **32 characters** long.
If the secret length is **64 characters** long:
- For users running Verdaccio 5.x on **Node.js 22** or higher, **the application will fail to start** if the secret length **is not** 32 characters long.
- For users running Verdaccio 5.x on **Node.js 21** or lower, the application will start, but it will display a deprecation warning at the console.
#### How to upgrade the token secret at the storage?
:warning: **If the secret is updated will invalidate all previous generated tokens.**
##### Option 1: Manually
Go to the [storage location](cli.md) and edit manually the secret to be 32 characters long.
##### Option 2: Automatically (since v5.31.0)
The `migrateToSecureLegacySignature` property is used to generate a new secret token if the length is 64 characters.
```
security:
api:
migrateToSecureLegacySignature: true
```
The token will be automatically updated to 32 characters long and the application will start without any issues.
The property won't have any other effect on the application and could be removed after the secret is updated.
:::
_The `.verdaccio-db` file database is only available if user does not use a custom storage_, by default verdaccio uses a tiny database to store private packages the `storage` property is defined in the `config.yaml` file.
The location might change based on your operating system. [Read the CLI section](cli.md) for more details about the location of files.
The structure of the database is based in JSON file, for instance:
```json
{
"list": ["package1", "@scope/pkg2"],
"secret": "secret_token_32_characters_long"
}
```
- `list`: Is an array with the list of the private packages published, any item on this list is considered being published by the user.
- `secret`: The secret field is used for the token signature and verification, either for _JWT_ or legacy token signature.
### Plugins {#plugins}
Is the location of the plugin directory. Useful for Docker/Kubernetes-based deployments.
```yaml
plugins: ./plugins
```
### Authentication {#authentication}
The authentication setup is done here. The default auth is based on `htpasswd` and is built in. You can modify this behaviour via [plugins](plugins.md). For more information about this section read the [auth page](auth.md).
```yaml
auth:
htpasswd:
file: ./htpasswd
max_users: 1000
```
### Security {#security}
The security block permits customization of the token signature with two options. The configuration is divided into
two sections, `api` and `web`. When using JWT on `api`, it must be defined; otherwise, the legacy token signature (`aes192`) will be utilized.
#### How to the token is generated?
The token signature requires a **secret token** generated by custom plugin that creates the `.verdaccio-db` database or in case a custom storage is used,
the secret token is fetched from the plugin implementation itself. In any case the _secret token_ is required to start the application.
#### Legacy Token Signature
The `legacy` property is used to enable the legacy token signature. **By default is enabled**. The legacy feature only applies to the API, the web UI uses JWT by default.
:::info
In 5.x versions using Node.js 21 or lower, there will see the warning `[DEP0106] DeprecationWarning: crypto.createDecipher is deprecated`. printed in your terminal.
This warning indicates that Node.js has deprecated a function utilized by the legacy signature.
If verdaccio runs on **Node.js 22** or higher, you will not see this warning since a new modern legacy signature has been implemented.
The **migrateToSecureLegacySignature** property is only available for versions higher than 5.31.0 and is **false** by default.
:::info
```yaml
security:
api:
legacy: true # by default is true even if this section is not defined
migrateToSecureLegacySignature: true # will generate a new secret token if the length is 64 characters
```
#### JWT Token Signature
To enable a new [JWT (JSON Web Tokens)](https://jwt.io/) signature, the `jwt` block needs to be added to the `api` section; `jwt` is utilized by default in `web`.
By using the JWT signature is also possible to customize the [signature](https://github.com/auth0/node-jsonwebtoken#jwtsignpayload-secretorprivatekey-options-callback) and the token [verification](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback) with your own properties.
```yaml
security:
api:
legacy: true
migrateToSecureLegacySignature: true # will generate a new secret token if the length is 64 characters
jwt:
sign:
expiresIn: 29d
verify:
someProp: [value]
web:
sign:
expiresIn: 1h # 1 hour by default
verify:
someProp: [value]
```
### Server {#server}
A set of properties to modify the behavior of the server application, specifically the API (Express.js).
> You can specify HTTP/1.1 server keep alive timeout in seconds for incoming connections.
> A value of 0 makes the http server behave similarly to Node.js versions prior to 8.0.0, which did not have a keep-alive timeout.
> WORKAROUND: Through given configuration you can workaround following issue https://github.com/verdaccio/verdaccio/issues/301. Set to 0 in case 60 is not enough.
```yaml
server:
keepAliveTimeout: 60
```
### Web UI {#web-ui}
This property allow you to modify the look and feel of the web UI. For more information about this section read the [web UI page](web.md).
```yaml
web:
enable: true
title: Verdaccio
logo: logo.png
scope:
```
### Uplinks {#uplinks}
Uplinks add the ability to fetch packages from remote registries when those packages are not available locally. For more information about this section read the [uplinks page](uplinks.md).
```yaml
uplinks:
npmjs:
url: https://registry.npmjs.org/
```
### Packages {#packages}
This section allows you to control how packages are accessed. For more information about this section read the [packages page](packages.md).
```yaml
packages:
'@*/*':
access: $all
publish: $authenticated
proxy: npmjs
```
## Advanced Settings {#advanced-settings}
### Offline Publish {#offline-publish}
By default `verdaccio` does not allow you to publish packages when the client is offline. This can be can be overridden by setting this value to _true_.
```yaml
publish:
allow_offline: false
```
<small>Since: `verdaccio@2.3.6` due [#223](https://github.com/verdaccio/verdaccio/pull/223)</small>
### URL Prefix {#url-prefix}
The prefix is intended to be used when the server runs behinds the proxy and won't work properly if is used without a reverse proxy, check the **reverse proxy setup** page for more details.
The internal logic builds correctly the public url, validates the `host` header and and bad shaped `url_prefix`.
eg: `url_prefix: /verdaccio`, `url_prefix: verdaccio/`, `url_prefix: verdaccio` would be `/verdaccio/`
```yaml
url_prefix: /verdaccio/
```
The new `VERDACCIO_PUBLIC_URL` is intended to be used behind proxies, this variable will be used for:
- Used as base path to serve UI resources as (js, favicon, etc)
- Used on return metadata `dist` base path
- Ignores `host` and `X-Forwarded-Proto` headers
- If `url_prefix` is defined would be appended to the env variable.
Read more about `VERDACCIO_PUBLIC_URL` [at the environment variables page](env.md#public-url).
### User Agent {#user-agent}
<small>Since: `verdaccio@5.4.0`</small>
The user agent is disabled by default, in exchange the user agent client (package manager, browser, etc ...) is being bypassed to the remote. To enable the previous behaviour use boolean values.
```yaml
user_agent: true
user_agent: false
user_agent: 'custom user agent'
```
### User Rate Limit {#user-rate-limit}
<small>Since: [verdaccio@5.4.0](https://github.com/verdaccio/verdaccio/releases/tag/v5.4.0)</small>
Add default rate limit to user endpoints, `npm token`, `npm profile`, `npm login/adduser` and login website to 100 request peer 15 min, customizable via:
```
userRateLimit:
windowMs: 50000
max: 1000
```
Additonal configuration (only feature flags) is also possible via the [middleware docs](https://github.com/nfriedly/express-rate-limit/#configuration-options).
### Max Body Size {#max-body-size}
By default the maximum body size for a JSON document is `10mb`, if you run into errors that state `"request entity too large"` you may increase this value.
```yaml
max_body_size: 10mb
```
### Listen Port {#listen-port}
`verdaccio` runs by default on the port `4873`. Changing the port can be done via [CLI](cli.md) or in the configuration file. The following options are valid:
```yaml
listen:
# - localhost:4873 # default value
# - http://localhost:4873 # same thing
# - 0.0.0.0:4873 # listen on all addresses (INADDR_ANY)
# - https://example.org:4873 # if you want to use https
# - "[::1]:4873" # ipv6
# - unix:/tmp/verdaccio.sock # unix socket
```
### HTTPS {#https}
To enable `https` in `verdaccio` it's enough to set the `listen` flag with the protocol _https://_. For more information about this section read the [SSL page](ssl.md).
```yaml
https:
key: ./path/verdaccio-key.pem
cert: ./path/verdaccio-cert.pem
ca: ./path/verdaccio-csr.pem
```
### Proxy {#proxy}
Proxies are special-purpose HTTP servers designed to transfer data from remote servers to local clients.
#### http_proxy and https_proxy {#http_proxy-and-https_proxy}
If you have a proxy in your network you can set a `X-Forwarded-For` header using the following properties:
```yaml
http_proxy: http://something.local/
https_proxy: https://something.local/
```
#### no_proxy {#no_proxy}
This variable should contain a comma-separated list of domain extensions that the proxy should not be used for.
```yaml
no_proxy: localhost,127.0.0.1
```
### Notifications {#notifications}
Enabling notifications to third-party tools is fairly easy via webhooks. For more information about this section read the [notifications page](notifications.md).
```yaml
notify:
method: POST
headers: [{ 'Content-Type': 'application/json' }]
endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'
```
> For more detailed configuration settings, please [check the source code](https://github.com/verdaccio/verdaccio/tree/master/packages/config/src/conf).
### Logger {#logger}
:::warning
Since v5.22.0 the logger property is renamed to `logs` but `log` still compatible but displaying a warning
:::
Two logger types are supported, you may chose only one of them:
#### console output (the default)
```
log: { type: stdout, format: pretty, level: http }
```
#### file output
```
log: { type: file, path: verdaccio.log, level: info }
```
For full information - see here: [Features/logger](logger.md)
### Audit {#audit}
<small>Since: `verdaccio@3.0.0`</small>
`npm audit` is a new command released with [npm 6.x](https://github.com/npm/npm/releases/tag/v6.1.0). Verdaccio includes
a built-in middleware plugin to handle this command.
> If you have a new installation it comes by default, otherwise you need to add the following props to your config file
```yaml
middlewares:
audit:
enabled: true
# timeout: 10000
```
### Experiments {#experiments}
This release includes a new property named `experiments` that can be placed in the `config.yaml` and is completely optional.
We want to be able to ship new things without affecting production environments. This flag allows us to add new features and get feedback from the community who decides to use them.
The features under this flag might not be stable or might be removed in future releases.
Here is one example:
```yaml
experiments:
changePassword: false
```
> To disable the experiments warning in the console, you must comment out the whole `experiments` section.
### Config Builder API {#builder}
After version `v5.23.1` the new advanced configuration builder API is available. The API is a flexible way to generate programmatically configuration outputs either in JSON or YAML using the builder pattern, for example:
```typescript
import { ConfigBuilder } from 'verdaccio';
const config = ConfigBuilder.build();
config
.addUplink('upstream', { url: 'https://registry.upstream.local' })
.addUplink('upstream2', { url: 'https://registry.upstream2.local' })
.addPackageAccess('upstream/*', {
access: 'public',
publish: 'foo, bar',
unpublish: 'foo, bar',
proxy: 'some',
})
.addLogger({ level: 'info', type: 'stdout', format: 'json' })
.addStorage('/tmp/verdaccio')
.addSecurity({ api: { legacy: true } });
// generate JSON object as output
config.getConfig();
// generate output as yaml
config.getAsYaml();
```

View File

@@ -1,279 +0,0 @@
---
id: docker
title: Docker
---
<iframe width="560" height="515" src="https://www.youtube.com/embed/zRI0skF1f8I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
To pull the latest pre-built [docker image](https://hub.docker.com/r/verdaccio/verdaccio/):
```bash
docker pull verdaccio/verdaccio
```
![Docker pull](/img/docker_verdaccio.gif)
## Tagged Versions {#tagged-versions}
![alt Docker Pulls Count](https://dockeri.co/image/verdaccio/verdaccio 'Docker Pulls Count')
Since version `v2.x` you can pull docker images by [tag](https://hub.docker.com/r/verdaccio/verdaccio/tags/), as follows:
For a major version:
```bash
docker pull verdaccio/verdaccio:4
```
For a minor version:
```bash
docker pull verdaccio/verdaccio:4.0
```
For a specific (patch) version:
```bash
docker pull verdaccio/verdaccio:4.0.0
```
> If you are interested on a list of tags, [please visit the Docker Hub website](https://hub.docker.com/r/verdaccio/verdaccio/tags/).
## Running Verdaccio using Docker {#running-verdaccio-using-docker}
To run the docker container:
```bash
docker run -it --rm --name verdaccio -p 4873:4873 verdaccio/verdaccio
```
The last argument defines which image to use.
The above line will pull the latest prebuilt image from dockerhub, if you haven't done that already.
If you have [build an image locally](#build-your-own-docker-image) use `verdaccio` as the last argument.
You can use `-v` to bind mount `conf`, `storage` and `plugins` to the hosts filesystem (example below).
Note that if you do mount conf like this, that [you first need to supply a copy of config.yaml in that directory](https://github.com/verdaccio/verdaccio/tree/master/docker-examples/v5/plugins/docker-build-install-plugin). The Docker container will not start properly if this file is missing.
You can copy this file initially from https://github.com/verdaccio/verdaccio/blob/5.x/conf/docker.yaml.
However, note the security warnings in that file; you will definitely want to lock it down in production.
```bash
V_PATH=/path/for/verdaccio; docker run -it --rm --name verdaccio \
-p 4873:4873 \
-v $V_PATH/conf:/verdaccio/conf \
-v $V_PATH/storage:/verdaccio/storage \
-v $V_PATH/plugins:/verdaccio/plugins \
verdaccio/verdaccio
```
> if you are running in a server, you might want to add -d to run it in the background
> Note: Verdaccio runs as a non-root user (uid=10001) inside the container, if you use bind mount to override default,
> you need to make sure the mount directory is assigned to the right user. In above example, you need to run `sudo chown -R 10001:65533 /path/for/verdaccio` otherwise
> you will get permission errors at runtime.
> [Use docker volume](https://docs.docker.com/storage/volumes/) is recommended over using bind mount.
### Environment variables
Verdaccio provides a new set of environment variables to modify either permissions, port or http protocol, see them at [the environment variables page](env.md#docker).
### SELinux {#selinux}
If SELinux is enforced in your system, the directories to be bind-mounted in the container need to be relabeled. Otherwise verdaccio will be forbidden from reading those files.
```
fatal--- cannot open config file /verdaccio/conf/config.yaml: Error: CONFIG: it does not look like a valid config file
```
If verdaccio can't read files on a bind-mounted directory and you are unsure, please check `/var/log/audit/audit.log` to confirm that it's a SELinux issue. In this example, the error above produced the following AVC denial.
```
type=AVC msg=audit(1606833420.789:9331): avc: denied { read } for pid=1251782 comm="node" name="config.yaml" dev="dm-2" ino=8178250 scontext=system_u:system_r:container_t:s0:c32,c258 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0
```
`chcon` can change the labels of shared files and directories. To make a directory accessible to containers, change the directory type to `container_file_t`.
```sh
$ chcon -Rt container_file_t ./conf
```
If you want to make the directory accessible only to a specific container, use `chcat` to specify a matching SELinux category.
An alternative solution is to use [z and Z flags](https://docs.docker.com/storage/bind-mounts/#configure-the-selinux-label). To add the `z` flag to the mountpoint `./conf:/verdaccio/conf` simply change it to `./conf:/verdaccio/conf:z`. The `z` flag relabels the directory and makes it accessible by every container while the `Z` flags relables the directory and makes it accessible only to that specific container. However using these flags is dangerous. A small configuration mistake, like mounting `/home/user` or `/var` can mess up the labels on those directories and make the system unbootable.
## Plugins {#plugins}
Plugins can be installed in a separate directory and mounted using Docker or Kubernetes, however make sure you build plugins with native dependencies using the same base image as the Verdaccio Dockerfile.
### Creating your own `Dockerfile` using `verdaccio/verdaccio:tag` as base
If the plugin already exist in some registry, it could be installed globally with `npm` command.
```docker
FROM verdaccio/verdaccio:5
ADD docker.yaml /verdaccio/conf/config.yaml
USER root
RUN npm install --global verdaccio-static-token \
&& npm install --global verdaccio-auth-memory
USER $VERDACCIO_USER_UID
```
For more detailed plugin example, check the with `docker-examples` [folder](https://github.com/verdaccio/verdaccio/tree/master/docker-examples/v5/plugins/docker-build-install-plugin).
### Adding plugins with local plugins a `Dockerfile`
If you don't have the packages available some registry and you want to try out a local plugin, you can use the folder `/verdaccio/plugins` for it, _verdaccio_ will look at this folder for plugins on startup.
1. Create a base image with multi stage support.
2. `ADD` the local plugin into the image
3. Install dependencies, required if your plugin has dependencies, you might need to build in case you need a transpilation step (tsc, babel).
4. Copying the final folder into the final image and applying permissions so verdaccio can find the folders (verdaccio uses custom user `$VERDACCIO_USER_UID`, read more [here](env.md#docker)).
```
FROM node:lts-alpine as builder
RUN mkdir -p /verdaccio/plugins
ADD plugins/verdaccio-docker-memory /verdaccio/plugins/verdaccio-docker-memory
RUN cd /verdaccio/plugins/verdaccio-docker-memory \
&& npm install --production
FROM verdaccio/verdaccio:5
ADD docker.yaml /verdaccio/conf/config.yaml
COPY --chown=$VERDACCIO_USER_UID:root --from=builder \
/verdaccio/plugins/verdaccio-docker-memory \
/verdaccio/plugins/verdaccio-docker-memory
```
For more detailed plugin example, check the with `docker-examples` [folder](https://github.com/verdaccio/verdaccio/tree/master/docker-examples/v5/plugins/docker-local-plugin).
### Adding plugins without creating a new image
1. Using `docker-compose.yaml` [example below](docker.md#using-docker-compose).
2. Mapping volumes in docker, verdaccio will look up for plugins at `/verdaccio/plugins` by default.
```
V_PATH=/path/for/verdaccio; docker run -it --rm --name verdaccio \
-p 4873:4873 \
-v $V_PATH/conf:/verdaccio/conf \
-v $V_PATH/storage:/verdaccio/storage \
-v $V_PATH/plugins:/verdaccio/plugins \
verdaccio/verdaccio
```
### Docker and custom port configuration {#docker-and-custom-port-configuration}
Any `host:port` configured in `conf/config.yaml` under `listen` **is currently ignored when using docker**.
If you want to reach Verdaccio docker instance under different port, lets say `5000`
in your `docker run` command add the environment variable `VERDACCIO_PORT=5000` and then expose the port `-p 5000:5000`.
```bash
V_PATH=/path/for/verdaccio; docker run -it --rm --name verdaccio \
-e "VERDACCIO_PORT=8080" -p 8080:8080 \
verdaccio/verdaccio
```
Of course the numbers you give to the `-p` parameter need to match.
### Using HTTPS with Docker {#using-https-with-docker}
You can configure the protocol verdaccio is going to listen on, similarly to the port configuration.
You have to overwrite the default value("http") of the `PROTOCOL` environment variable to "https", after you specified the certificates in the config.yaml.
```bash
docker run -it --rm --name verdaccio \
--env "VERDACCIO_PROTOCOL=https" -p 4873:4873
verdaccio/verdaccio
```
### Using docker-compose {#using-docker-compose}
1. Get the latest version of [docker-compose](https://github.com/docker/compose).
2. Build and run the container:
```bash
$ docker-compose up --build
```
You can set the port to use (for both container and host) by prefixing the above command with `VERDACCIO_PORT=5000 `.
```yaml
version: '3.1'
services:
verdaccio:
image: verdaccio/verdaccio
container_name: 'verdaccio'
networks:
- node-network
environment:
- VERDACCIO_PORT=4873
ports:
- '4873:4873'
volumes:
- './storage:/verdaccio/storage'
- './config:/verdaccio/conf'
- './plugins:/verdaccio/plugins'
networks:
node-network:
driver: bridge
```
Docker will generate a named volume in which to store persistent application data. You can use `docker inspect` or `docker volume inspect` to reveal the physical location of the volume and edit the configuration, such as:
```bash
$ docker volume inspect verdaccio_verdaccio
[
{
"Name": "verdaccio_verdaccio",
"Driver": "local",
"Mountpoint": "/var/lib/docker/volumes/verdaccio_verdaccio/_data",
"Labels": null,
"Scope": "local"
}
]
```
## Build your own Docker image {#build-your-own-docker-image}
Go to the [`5.x` branch](https://github.com/verdaccio/verdaccio/tree/5.x) and run:
```bash
docker build -t verdaccio .
```
There is also an yarn script for building the docker image, so you can also do:
```bash
yarn run build:docker
```
Note: The first build takes some minutes to build because it needs to run `yarn install`,
and it will take that long again whenever you change any file that is not listed in `.dockerignore`.
Please note that for any of the above docker commands you need to have docker installed on your machine and the docker executable should be available on your `$PATH`.
## Docker Examples {#docker-examples}
There is a separate repository that hosts multiple configurations to compose Docker images with `verdaccio`, for instance, as reverse proxy:
[https://github.com/verdaccio/docker-examples](https://github.com/verdaccio/verdaccio/tree/master/docker-examples)
## Docker Custom Builds {#docker-custom-builds}
> If you have made an image based on Verdaccio, feel free to add it to this list.
- [docker-verdaccio-multiarch](https://github.com/hertzg/docker-verdaccio-multiarch) Multiarch image mirrors
- [docker-verdaccio-gitlab](https://github.com/snics/docker-verdaccio-gitlab)
- [docker-verdaccio](https://github.com/deployable/docker-verdaccio)
- [docker-verdaccio-s3](https://github.com/asynchrony/docker-verdaccio-s3) Private NPM container that can backup to s3
- [docker-verdaccio-ldap](https://github.com/snadn/docker-verdaccio-ldap)
- [verdaccio-ldap](https://github.com/nathantreid/verdaccio-ldap)
- [verdaccio-compose-local-bridge](https://github.com/shingtoli/verdaccio-compose-local-bridge)
- [docker-verdaccio](https://github.com/Global-Solutions/docker-verdaccio)
- [verdaccio-docker](https://github.com/idahobean/verdaccio-docker)
- [verdaccio-server](https://github.com/andru255/verdaccio-server)
- [coldrye-debian-verdaccio](https://github.com/coldrye-docker/coldrye-debian-verdaccio) docker image providing verdaccio from coldrye-debian-nodejs.
- [verdaccio-github-oauth-ui](https://github.com/n4bb12/verdaccio-github-oauth-ui/blob/master/Dockerfile)

View File

@@ -1,101 +0,0 @@
---
id: e2e
title: 'End to End testing'
---
### Testing the integrity of React components by publishing in a private registry
> The final stage of a react component is when it is being published and distributed. How can I ensure my packages wont crash in production? This talk will help you to test your React components by publishing them to a private registry and running End-to-End tests against them.
<iframe width="300" height="600" src="https://www.youtube.com/embed/bRKZbrlQqLY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
- [Slides](https://docs.google.com/presentation/d/1a2xkqj1KlUayR1Bva1bVYvavwOPVuLplxFtup9MI_U4/edit?usp=sharing)
- [Demo](https://github.com/juanpicado/verdaccio-end-to-end-tests)
## End to End and Verdaccio
Some projects organize packages in multi-packages repositories or [monorepos](https://github.com/babel/babel/blob/master/doc/design/monorepo.md). End to End testing is a topic that usually is only relevant for User Interfaces, but from a Node.js perspective, **publishing packages also need to be tested**.
Such approach has been really hard to achieve considering:
- Populate canary packages on public services seems not to be a good idea
- Some self-hosted OSS registries are too heavy
- Offline environments (private networks)
**Verdaccio** is a lightweight registry with zero-configuration that **fits perfectly in any E2E + CI workflow**.
## Implementation {#implementation}
There is no a silver bullet yet, each implementation seems to be specific for each project, you can check some of them in
the following thread [clicking here](https://stackoverflow.com/a/50222427/308341).
## Examples in Open Source
The following projects have examples using Verdaccio in Open Source
### Bash Examples
- [Bun ![Stars](https://img.shields.io/github/stars/oven-sh/bun?label=⭐️)](https://github.com/oven-sh/bun/commits/main/test/cli/install/registry/verdaccio.yaml)
- [Babel.js ![Stars](https://img.shields.io/github/stars/babel/babel?label=⭐️)](https://github.com/babel/babel)
- [Docusaurus ![Stars](https://img.shields.io/github/stars/facebook/docusaurus?label=⭐️)](https://github.com/facebook/docusaurus)
- [create-react-app ![Stars](https://img.shields.io/github/stars/facebook/create-react-app?label=⭐️)](https://github.com/facebook/create-react-app/blob/master/CONTRIBUTING.md#contributing-to-e2e-end-to-end-tests)
- [pnpm ![Stars](https://img.shields.io/github/stars/pnpm/pnpm?label=⭐️)](https://github.com/pnpm/pnpm)
- [Uppy ![Stars](https://img.shields.io/github/stars/transloadit/uppy?label=⭐️)](https://github.com/transloadit/uppy)
- [ethereum/web3.js ![Stars](https://img.shields.io/github/stars/ethereum/web3.js?label=⭐️)](https://github.com/ethereum/web3.js)
- [adobe react-spectrum ![Stars](https://img.shields.io/github/stars/adobe/react-spectrum?label=⭐️)](https://github.com/adobe/react-spectrum/pull/2432)
- [Mozilla Neutrino ![Stars](https://img.shields.io/github/stars/neutrinojs/neutrino?label=⭐️)](https://github.com/neutrinojs/neutrino)
This is the simplest example using Verdaccio in a bash script (extracted from _create-react-app_).
```bash
#!/bin/sh
set -e
local_registry="http://0.0.0.0:4873"
# start local registry
tmp_registry_log=`mktemp`
sh -c "mkdir -p $HOME/.config/verdaccio"
sh -c "cp --verbose /config.yaml $HOME/.config/verdaccio/config.yaml"
sh -c "nohup verdaccio --config $HOME/.config/verdaccio/config.yaml &>$tmp_registry_log &"
# wait for `verdaccio` to boot
grep -q 'http address' <(tail -f $tmp_registry_log)
# login so we can publish packages
sh -c "npm-auth-to-token -u test -p test -e test@test.com -r $local_registry"
# Run nmp command
sh -c "npm --registry $local_registry publish"
```
### Docker Examples
- [Hyperledger](https://github.com/hyperledger/fabric-chaincode-node)
### Programmatic Examples
- [Storybook ![Stars](https://img.shields.io/github/stars/storybooks/storybook?label=⭐️)](https://github.com/storybooks/storybook)
- [Gatsby ![Stars](https://img.shields.io/github/stars/gatsbyjs/gatsby?label=⭐️)](https://github.com/gatsbyjs/gatsby)
#### Verdaccio module
Via CLI:
- [Aurelia Framework ![Stars](https://img.shields.io/github/stars/aurelia/framework?label=⭐️)](https://github.com/aurelia)
- [Netlify CLI ![Stars](https://img.shields.io/github/stars/netlify/cli?label=⭐️)](https://github.com/netlify/cli)
- [Embark ![Stars](https://img.shields.io/github/stars/embarklabs/embark?label=⭐️)](https://embark.status.im/)
- [Microsoft Beachball ![Stars](https://img.shields.io/github/stars/microsoft/beachball?label=⭐️)](https://github.com/microsoft/beachball)
#### Node.js `child_process` examples
- [Angular CLI ![Stars](https://img.shields.io/github/stars/angular/angular-cli?label=⭐️)](https://github.com/angular/angular-cli)
- [bit ![Stars](https://img.shields.io/github/stars/teambit/bit?label=⭐️)](https://github.com/teambit/bit)
- [pnpm ![Stars](https://img.shields.io/github/stars/pnpm/pnpm?label=⭐️)](https://github.com/pnpm/pnpm)
- [aws-sdk cli v3 ![Stars](https://img.shields.io/github/stars/aws/aws-sdk-js-v3?label=⭐️)](https://github.com/aws/aws-sdk-js-v3)
- [angular-eslint ![Stars](https://img.shields.io/github/stars/angular-eslint/angular-eslint?label=⭐️)](https://github.com/angular-eslint/angular-eslint)
## Example repositories
- [e2e-ci-example-gh-actions](https://github.com/juanpicado/e2e-ci-example-gh-actions)
- [verdaccio-end-to-end-tests](https://github.com/juanpicado/verdaccio-end-to-end-tests)
- [verdaccio-fork](https://github.com/juanpicado/verdaccio-fork)
- [simplified e2e testing using verdaccio](https://github.com/rluvaton/e2e-verdaccio-example)

View File

@@ -1,24 +0,0 @@
---
id: github-actions
title: 'GitHub Actions'
---
With [GitHub Actions](https://github.com/features/actions) you can automate your workflow, each GitHub Action performs a specific step in a process.
![actions](/img/github-actions.png)
## Testing your packages {#testing-your-packages}
Verdaccio provides a custom action for easy integration in your flow by adding the following to your workflow file's `steps` key.
```yaml
- name: Publish with Verdaccio
uses: verdaccio/github-actions/publish@master
```
The action will perform a `npm publish` and if the publishing finishes successfully, the workflow will continue to the next step, otherwise the step will fail.
If there are any issues publishing a package you will notice using this action.
Within the image uses `verdaccio-auth-memory` and `verdaccio-memory` plugins to handle authentification and storage to speed up the process.
If you want to know more about the action, [visit our repository](https://github.com/verdaccio/github-actions) dedicated for GitHub Actions.

View File

@@ -1,129 +0,0 @@
---
id: aws
title: 'Amazon Web Services'
---
This document describes simple steps to setup Verdaccio private registry on Amazon Web Services platform using EC2 service. This assumes you have already created an EC2 Amazon Linux instance; if not then please check this tutorial on [AWS EC2 Setup](https://www.howtoinmagento.com/2018/04/aws-cli-commands-for-aws-ec2-amazon.html).
## Setup & Configuration {#setup--configuration}
**Step 1:** Open SSH & Login in using your EC2 key.
**Step 2:** Install Node Version Manager (nvm) first, close and re-open the SSH using your EC2 key.
`sudo apt update`
`wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash`
`exit`
**Step 3:** Install Node using Node Version Manager (nvm)
`nvm install node`
**Step 4:** Install Verdaccio & pm2, will require to run Verdaccio service in background
`npm i -g verdaccio pm2`
**Step 5:** Set the verdaccio registry as a source. By default original NPM registry set.
`npm set registry http://localhost:4873`
`npm set ca null`
**Step 6:** Run Verdaccio and stop it (ctrl+c). It will create a config file we will use.
`verdaccio`
**Step 7:** Now do below configuration for listening to all addresses on that server machine / EC2 instance. [(read more)](https://github.com/verdaccio/verdaccio/blob/master/conf/full.yaml)
Open and edit `config.yaml` file:
` nano .config/verdaccio/config.yaml` or ` nano ~/verdaccio/config.yaml`
Add below lines at the end. [(read more)](https://github.com/verdaccio/verdaccio/blob/ff409ab7c05542a152100e3bc39cfadb36a8a080/conf/full.yaml#L113)
```
listen:
- 0.0.0.0:4873
```
Change below line so that only authenticated person can access our registry
`Replace "access: $all" with "access: $authenticated"`
(Optional) Change below line according to how many users you wish to grant access to the scoped registry
`Replace "#max_users: 1000" with "max_users: 1"`
There are some more parameters available to configure it. Like storage, proxy, default port change. [(read more)](https://github.com/verdaccio/verdaccio/blob/ff409ab7c05542a152100e3bc39cfadb36a8a080/conf/full.yaml#L113)
**Step 8:** Run Verdaccio in background using PM2:
`pm2 start verdaccio`
**Step 9:** Now, You can access your Verdaccio web UI.
The URL will look like something:
`http://ec2-..compute.amazonaws.com:4873`
{or}
`http://your-ec2-public-ip-address:4873 (You can check your EC2 instance public ip from AWS console)`
To confirm Verdaccio's running status, run the command below:
` pm2 list`
To make Verdaccio launch on startup, run the commands below:
`pm2 stop verdaccio`
`pm2 delete verdaccio`
`pm2 startup` This will show a command in your terminal. Copy / paste it and execute it to have pm2 make a startup service for you.
`which verdaccio` Copy the path shown by this command.
`pm2 start /home/ubuntu/.nvm/versions/node/v17.1.0/bin/verdaccio` (put the path you copied from command above).
`pm2 status` This should show "online" on the status of verdaccio service.
`pm2 save` Now when you reboot the EC2 instance, it should launch verdaccio.
**Step 10:** Registering a user in verdaccio registry
` npm set always-auth true`
` npm adduser`
It will ask for username, password and valid email id to be entered. Make a note of this details that will use later to login in verdaccio registry to publish our library.
**Step 11:** Now we are ready to use our AWS server instance work as a private registry.
Login into verdaccio registry. Enter the same username, password and email id set in above Step.
` npm set registry http://your-ec2-public-ip-address:4873`
` npm login`
**Step 12:** Go to your custom library package path. In my case this is my Angular 7 package path -> `/libraries/dist/your-library-name/your-library-name-0.0.1.tgz`
If you like to know how to create angular 7 library/package then [(click here)](https://www.howtoinmagento.com/2019/11/how-to-create-your-first-angular-7.html)
` cd [custom library package path]`
**Step 13:** Finally publish our library `your-library-name-0.0.1.tgz` on verdaccio registry
` [custom library package path] >> npm publish your-library-name-0.0.1.tgz`
{or}
` [custom library package path] >> npm publish`
{or}
` [custom library package path] >> npm publish --registry http://your-ec2-public-ip-address:4873`
Now browse ` http://your-ec2-public-ip-address:4873` and you will see new library package there.

View File

@@ -1,129 +0,0 @@
---
id: iss-server
title: 'Installing on IIS server'
---
These instructions were written for Windows Server 2016, IIS 10, [Node.js 10.15.0](https://nodejs.org/), [iisnode 0.2.26](https://github.com/Azure/iisnode) and [verdaccio 3.11.0](https://github.com/verdaccio/verdaccio).
- Install IIS Install [iisnode](https://github.com/Azure/iisnode).
Make sure you install prerequisites (Url Rewrite Module & node) as explained in the instructions for iisnode.
- Create a new folder in Explorer where you want to host verdaccio.
For example `C:\verdaccio`.
Save [package.json](#packagejson),
[start.js](#startjs)
and [web.config](#webconfig) in this folder.
- Create a new site in Internet Information Services Manager. You can name it whatever you want.
I'll call it verdaccio in these [instructions](http://www.iis.net/learn/manage/configuring-security/application-pool-identities). Specify the path to where you saved all files and a port number.
- Go back to Explorer and give the user that runs the application pool modify rights to the folder you just created. If you've named the new site verdaccio and did not change the app pool, it's running under an ApplicationPoolIdentity and you should give the user IIS AppPool\verdaccio modify rights see instructions if you need help. (You can restrict access later if you want so that it only has modify rights on the iisnode and verdaccio\storage)
- Start a command prompt and execute the commands below to download verdaccio:
```
cd c:\verdaccio
npm install
```
- Make sure you have an inbound rule accepting TCP traffic to the port in Windows Firewall
- Thats it! Now you can navigate to the host and port that you specified
I wanted the `verdaccio` site to be the default site in IIS so I did the following:
- I stopped the "Default Web Site" and only start the site "verdaccio" site in IIS
- I set the bindings to "http", ip address "All Unassigned" on port 80, ok any warning or prompts
These instructions are based on [Host Sinopia in IIS
on Windows](https://gist.github.com/HCanber/4dd8409f79991a09ac75). I had to tweak my web config as per below but you may find the original from the
for mentioned link works better
A default configuration file will be created `c:\verdaccio\verdaccio\config.yaml`
### package.json {#packagejson}
```json
{
"name": "iisnode-verdaccio",
"version": "1.0.0",
"description": "Hosts verdaccio in iisnode",
"main": "start.js",
"dependencies": {
"verdaccio": "^3.11.0"
}
}
```
### start.js {#startjs}
```bash
process.argv.push('-l', 'unix:' + process.env.PORT, '-c', './config.yaml');
require('./node_modules/verdaccio/build/lib/cli.js');
```
### Alternate start.js for Verdaccio versions < v3.0 {#alternate-startjs-for-verdaccio-versions--v30}
```bash
process.argv.push('-l', 'unix:' + process.env.PORT);
require('./node_modules/verdaccio/src/lib/cli.js');
```
### web.config {#webconfig}
```xml
<configuration>
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<!-- indicates that the start.js file is a node.js application
to be handled by the iisnode module -->
<handlers>
<remove name="WebDAV" />
<add name="iisnode" path="start.js" verb="*" modules="iisnode" resourceType="Unspecified" requireAccess="Execute" />
<add name="WebDAV" path="*" verb="*" modules="WebDAVModule" resourceType="Unspecified" requireAccess="Execute" />
</handlers>
<rewrite>
<rules>
<!-- iisnode folder is where iisnode stores it's logs. These should
never be rewritten -->
<rule name="iisnode" stopProcessing="true">
<match url="iisnode*" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="None" />
</rule>
<!-- Rewrite all other urls in order for verdaccio to handle these -->
<rule name="verdaccio">
<match url="/*" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="start.js" />
</rule>
</rules>
</rewrite>
<!-- exclude node_modules directory and subdirectories from serving
by IIS since these are implementation details of node.js applications -->
<security>
<requestFiltering>
<hiddenSegments>
<add segment="node_modules" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
```
### Troubleshooting {#troubleshooting}
- **The web interface does not load when hosted with https as it tries to download scripts over http.**
Make sure that you have enabled `X-Forwarded-Proto` in IISNode using `enableXFF`. See [the related issue](https://github.com/verdaccio/verdaccio/issues/2003).
```
<configuration>
<system.webServer>
<iisnode enableXFF="true" />
</system.webServer>
</configuration>
```

View File

@@ -1,144 +0,0 @@
---
id: installation
title: 'Installation'
---
Verdaccio is a Node.js private and proxy registry. To install it, you need a few basic prerequisites.
## Prerequisites {#prerequisites}
1. **Node.js** `v14` or higher.
2. Your favorite Node Package Manager `npm`, `pnpm` or `yarn` (classic and berry).
> We highly recommend to use the latest versions of Node Package Manager clients `> npm@6.x | yarn@1.x | | yarn@2.x | pnpm@6.x`. Don't support `npm@5.x` or older.
3. A modern web browser to run the web interface. We actually support `Chrome, Firefox, Edge`.
> Verdaccio will support latest Node.js version according the [Node.js Release Working Group](https://github.com/nodejs/Release) recomendations.
Are you still using **Verdaccio 4**?. Check the [migration guide](https://verdaccio.org/blog/2021/04/14/verdaccio-5-migration-guide).
### Quick Introduction {#quick-introduction}
Learn the basics before getting started, how to install, where is the location of the configuration file and more.
<iframe width="560" height="515" src="https://www.youtube.com/embed/hDIFKzmoCaA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
## Installing the CLI {#installing-the-cli}
> Before using Verdaccio in production, please read and be [aware of the best practices](best-practices.md).
`Verdaccio` must be installed globally using either of the following methods:
Using `npm`
```bash
npm install -g verdaccio
```
or using `yarn`
```bash
yarn global add verdaccio
```
or using `pnpm`
```bash
pnpm install -g verdaccio
```
![install verdaccio](/img/install_verdaccio.gif)
### Next major release (verdaccio 6 alpha) {#next-major-release}
Next [major release is under development](https://github.com/verdaccio/verdaccio/discussions/2970), byt can try it out already, either for testing purposes or helping to catch any possible bug, if you find something report it under the label [6.x bugs](https://github.com/verdaccio/verdaccio/labels/6.x%20bugs).
```bash
npm install -g verdaccio@7-next
```
or with the docker image
```bash
docker pull verdaccio/verdaccio:nightly-master
```
> The docker image `verdaccio/verdaccio:nightly-master` is alinged with the latest commits in master branch, while the npmjs version has a longer release cycle. **It is highly recommended don't use alpha versions for production**.
## Basic Usage {#basic-usage}
Once it has been installed, you only need to execute the CLI command:
```bash
$> verdaccio
warn --- config file - /home/.config/verdaccio/config.yaml
warn --- http address - http://localhost:4873/ - verdaccio/5.0.0
```
For more information about the CLI, please [read the cli section](cli.md).
You can set the registry by using the following command.
```bash
npm set registry http://localhost:4873/
```
you can pass a `--registry` flag when needed.
```bash
npm install --registry http://localhost:4873
```
define in your `.npmrc` a `registry` field.
```bash title=".npmrc"
registry=http://localhost:4873
```
Or a `publishConfig` in your `package.json`
```json
{
"publishConfig": {
"registry": "http://localhost:4873"
}
}
```
For alternative configurations, please read the [Using a private registry](cli-registry.md) section.
## Create Your Own Private NPM Package Tutorial {#create-your-own-private-npm-package-tutorial}
If you'd like a broader explanation, don't miss the tutorial created by [thedevlife](https://mybiolink.co/thedevlife) on how to Create Your Own Private NPM Package using Verdaccio.
<iframe width="560" height="315" src="https://www.youtube.com/embed/Co0RwdpEsag?enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
## Docker Image {#docker-image}
```bash
docker run -it --rm --name verdaccio -p 4873:4873 verdaccio/verdaccio
```
`Verdaccio` has an official docker image you can use, and in most cases, the default configuration is good enough. For more information about how to install the official image, [read the docker section](docker.md), furthermore you can learn more about combining Docker images in our [docker-examples](https://github.com/verdaccio/verdaccio/tree/master/docker-examples) repository.
## Helm Chart {#helm-chart}
```bash
$ helm repo add verdaccio https://charts.verdaccio.org
$ helm repo update
$ helm install verdaccio/verdaccio
```
## Cloudron {#cloudron}
`Verdaccio` is also available as a 1-click install on [Cloudron](https://cloudron.io)
[![Install](https://cloudron.io/img/button.svg)](https://cloudron.io/button.html?app=org.eggertsson.verdaccio)
## Heroku with Docker
For easy deployment you could use [Heroku](https://www.heroku.com/home), the _free_ dyno tier allows you to test their platform using a Docker container, check this example.
[https://github.com/juanpicado/verdaccio-heroku-example](https://github.com/juanpicado/verdaccio-heroku-example)

View File

@@ -1,139 +0,0 @@
---
id: kubernetes
title: 'Kubernetes'
---
You can find instructions to deploy Verdaccio on a Kubernetes cluster on the
[verdaccio/docker-example](https://github.com/verdaccio/verdaccio/tree/5.x/docker-examples/kubernetes-example)
repository. However, the recommended method to install Verdaccio on a Kubernetes
cluster is to use [Helm](https://helm.sh). Helm is a
[Kubernetes](https://kubernetes.io) package manager which bring multiple
advantages.
## Helm {#helm}
### Setup Helm {#setup-helm}
If you haven't used Helm before, you need to setup the Helm controller called
Tiller:
```bash
helm init
```
### Install {#install}
> ⚠️ If you are using this helm chart, please [be aware of the migration of the repository](https://github.com/verdaccio/verdaccio/issues/1767).
Deploy the Helm [verdaccio/verdaccio](https://github.com/verdaccio/charts)
chart.
### Add repository {#add-repository}
```
helm repo add verdaccio https://charts.verdaccio.org
```
In this example we use `npm` as release name:
```bash
helm install npm verdaccio/verdaccio
```
### Deploy a specific version {#deploy-a-specific-version}
```bash
helm install npm --set image.tag=3.13.1 verdaccio/verdaccio
```
### Upgrading Verdaccio {#upgrading-verdaccio}
```bash
helm upgrade npm verdaccio/verdaccio
```
### Uninstalling {#uninstalling}
```bash
helm uninstall npm
```
**Note:** this command delete all the resources, including packages that you may
have previously published to the registry.
### Custom Verdaccio configuration {#custom-verdaccio-configuration}
You can customize the Verdaccio configuration using a Kubernetes _configMap_.
#### Prepare {#prepare}
Copy the [existing configuration](https://github.com/verdaccio/verdaccio/blob/master/conf/docker.yaml)
and adapt it for your use case:
```bash
wget https://raw.githubusercontent.com/verdaccio/verdaccio/master/packages/config/src/conf/docker.yaml -O config.yaml
```
**Note:** Make sure you are using the right path for the storage that is used for
persistency:
```yaml
storage: /verdaccio/storage/data
auth:
htpasswd:
file: /verdaccio/storage/htpasswd
```
#### Deploy the configMap {#deploy-the-configmap}
Deploy the `configMap` to the cluster
```bash
kubectl create configmap verdaccio-config --from-file ./config.yaml
```
#### Deploy Verdaccio {#deploy-verdaccio}
Now you can deploy the Verdaccio Helm chart and specify which configuration to
use:
```bash
helm install npm --set existingConfigMap=verdaccio-config verdaccio/verdaccio
```
### Authenticate with private upstreams using Helm
As of version `4.8.0` of the helm chart, a new `secretEnvVars` field has been added.
This allows you to inject sensitive values to the container via a [Kubernetes Secret](https://kubernetes.io/docs/concepts/configuration/secret/).
1. Update your Verdaccio config according to the [Uplinks](./uplinks.md#auth-property) documentation
2. Pass the secret environment variable to your values file or via `--set secretEnvVars.FOO_TOKEN=superSecretBarToken`
```yaml
# values.yaml
secretEnvVars:
FOO_TOKEN: superSecretBarToken
```
#### NGINX proxy body-size limit {#nginx-proxy-body-size-limit}
The standard k8s NGINX ingress proxy allows for 1MB for body-size which can be increased
by modifying the default deployment options according to the [documentation](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#custom-max-body-size):
```yaml
...
annotations:
...
kubernetes.io/proxy-body-size: 20m
....
...
```
## Rancher Support {#rancher-support}
[Rancher](http://rancher.com/) is a complete container management platform that makes managing and using containers in production really easy.
- [verdaccio-rancher](https://github.com/lgaticaq/verdaccio-rancher)

View File

@@ -1,97 +0,0 @@
---
id: linking-remote-registry
title: 'Linking a Remote Registry'
---
Verdaccio is a proxy and by default [links](uplinks.md) the public registry.
```yaml
uplinks:
npmjs:
url: https://registry.npmjs.org/
```
You can link multiple registries, the following document will drive you through some helpful configurations.
## Using Associating Scope {#using-associating-scope}
The unique way to access multiple registries using the `.npmrc` is the scope feature as follows:
```
// .npmrc
registry=https://registry.npmjs.org
@mycompany:registry=http://localhost:4873
```
This approach is valid, but comes with several disadvantages:
- It **only works with scopes**
- Scope must match, **no Regular Expressions are allowed**
- One scope **cannot fetch from multiple registries**
- Tokens/passwords **must be defined within** `.npmrc` and checked in into the repo.
See a full example [here](https://stackoverflow.com/questions/54543979/npmrc-multiple-registries-for-the-same-scope/54550940#54550940).
## Linking a Registry {#linking-a-registry}
Linking a registry is fairly simple. First, define a new section in the `uplinks` section. Note, the order here is irrelevant.
```yaml
uplinks:
private:
url: https://private.registry.net/npm
... [truncated] ...
'webpack':
access: $all
publish: $authenticated
proxy: private
```
Add a `proxy` section to define the selected registry you want to proxy.
## Linking Multiple Registries {#linking-multiple-registries}
```yaml
uplinks:
server1:
url: https://server1.registry.net/npm
server2:
url: https://server2.registry.net/npm
... [truncated] ...
'webpack':
access: $all
publish: $authenticated
proxy: server1 server2
```
Verdaccio supports multiple registries on the `proxy` field. The request will be resolved with the first in the list; if that
fails, it will try with the next in the list and so on.
## Offline Registry {#offline-registry}
Having a full Offline Registry is completely possible. If you don't want any connectivity with external remotes you
can do the following.
```yaml
auth:
htpasswd:
file: ./htpasswd
uplinks:
packages:
'@my-company/*':
access: $all
publish: none
'@*/*':
access: $all
publish: $authenticated
'**':
access: $all
publish: $authenticated
```
Remove all `proxy` fields within each section of `packages`. The registry will become full offline.

View File

@@ -1,39 +0,0 @@
---
id: logger
title: 'Logger'
---
:::warning
Since v5.22.0 the logger property is renamed from `logs` to `log`, it is still backward compatible but displaying a warning
:::
As with any web application, Verdaccio has a customizable built-in logger. You can define multiple types of outputs.
```yaml
# console output
log: { type: stdout, format: pretty, level: http }
```
or file output.
```yaml
# file output
log: { type: file, path: verdaccio.log, level: info }
```
> Verdaccio 5 does not support rotation file anymore, [here more details](https://verdaccio.org/blog/2021/04/14/verdaccio-5-migration-guide#pinojs-is-the-new-logger).
Use `SIGUSR2` to notify the application, the log-file was rotated and it needs to reopen it.
Note: Rotating log stream is not supported in cluster mode. [See here](https://github.com/trentm/node-bunyan#stream-type-rotating-file)
### Configuration {#configuration}
| Property | Type | Required | Example | Support | Description |
| -------- | ------- | -------- | ---------------------------------------------- | ------- | ------------------------------------------------- |
| type | string | No | [stdout, file] | all | define the output |
| path | string | No | verdaccio.log | all | if type is file, define the location of that file |
| format | string | No | [pretty, pretty-timestamped] | all | output format |
| level | string | No | [fatal, error, warn, info, http, debug, trace] | all | verbose level |
| colors | boolean | No | false | v5.7.0 | disable or enable colors |

View File

@@ -1,59 +0,0 @@
---
id: logo
title: 'Logotype'
---
The logotype was designed by **[Breno Rodrigues](https://github.com/rodriguesbreno)** which
won the [contest](https://github.com/verdaccio/verdaccio/issues/237)
([last stage](https://github.com/verdaccio/verdaccio/issues/328)) and donated his work to this project.
> All logos are licensed under [Creative Commons](https://github.com/verdaccio/verdaccio/blob/master/LICENSE-docs).
Special thanks to _[@Lisapressmar](https://github.com/Lisapressmar)_ for her contribution
with multiple image formats and sizes.
## Symbols {#symbols}
**With text**
![symbol tiny with text](/img/logo/symbol/png/logo-small-header-bottom.png)
![symbol medium with text](/img/logo/symbol/png/logo-small-header-bottom@2x.png)
![symbol big with text](/img/logo/symbol/png/logo-small-header-bottom@3x.png)
**SVG**
![symbol svg](/img/logo/symbol/svg/logo-small-header-bottom.svg)
**No text**
![symbol tiny](/img/logo/symbol/png/verdaccio-tiny.png)
![symbol medium](/img/logo/symbol/png/verdaccio-tiny@2x.png)
![symbol big](/img/logo/symbol/png/verdaccio-tiny@3x.png)
**SVG**
![svg format symbol no text](/img/logo/symbol/svg/verdaccio-tiny.svg)
### Black&White {#blackwhite}
![symbol bw small](/img/logo/symbol/png/verdaccio-blackwhite.png)
![symbol bw medium](/img/logo/symbol/png/verdaccio-blackwhite@2x.png)
![symbol bw big](/img/logo/symbol/png/verdaccio-blackwhite@3x.png)
**SVG**
![symbol bw svg](/img/logo/symbol/svg/verdaccio-blackwhite.svg)
## Banner {#banner}
![banner small](/img/logo/banner/png/verdaccio-banner.png)
![banner medium](/img/logo/banner/png/verdaccio-banner@2x.png)
![banner big](/img/logo/banner/png/verdaccio-banner@3x.png)

View File

@@ -1,83 +0,0 @@
---
id: node-api
title: 'Node API'
---
Verdaccio can be invoked programmatically. The Node API was introduced after version `verdaccio@3.0.0`.
## Usage {#usage}
#### Programmatically {#programmatically}
```js
const startServer = require("verdaccio").default;
let config = {
storage: "./storage",
auth: {
htpasswd: {
file: "./htpasswd"
}
},
uplinks: {
npmjs: {
url: "https://registry.npmjs.org/",
}
},
self_path: "./",
packages: {
"@*/*": {
access: "$all",
publish: "$authenticated",
proxy: "npmjs",
},
"**": {
proxy: "npmjs"
}
},
log: {
type: "stdout",
format: "pretty",
level: "http",
};
};
startServer(
config,
6000,
undefined,
"1.0.0",
"verdaccio",
(webServer, addrs) => {
webServer.listen(
addrs.port || addrs.path,
addrs.host,
() => {
console.log(`verdaccio running on : ${addrs.host}:${addrs.port}`);
}
);
}
);
```
## Other implementations {#other-implementations}
- [verdaccio-server](https://github.com/boringame/verdaccio-server) local npm registry proxy server
```js
// js
import * as verdaccioServer from 'verdaccio-server';
verdaccioServer.start();
verdaccioServer.stop();
verdaccioServer.list();
verdaccioServer.stopAll();
verdaccioServer.show();
verdaccioServer.cli();
// windows .net2
verdaccioServer.serviceInstall();
verdaccioServer.serviceUninstall();
verdaccioServer.serviceStart();
verdaccioServer.serviceStop();
verdaccioServer.serviceRestart();
```

View File

@@ -1,167 +0,0 @@
---
id: notifications
title: 'Notifications'
---
Notify was built primarily to use with Slack's Incoming
webhooks, but will also deliver a simple payload to
any endpoint. This is currently only active for the `npm publish`
command.
## Usage {#usage}
An example with a **HipChat**, **Stride** and **Google Hangouts Chat** hook:
> Verdaccio supports any API, feel free to add more examples.
#### Single notification {#single-notification}
```yaml
notify:
method: POST
headers: [{ 'Content-Type': 'application/json' }]
endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'
```
#### Multiple notification {#multiple-notification}
```yaml
notify:
'example-google-chat':
method: POST
headers: [{ 'Content-Type': 'application/json' }]
endpoint: https://chat.googleapis.com/v1/spaces/AAAAB_TcJYs/messages?key=myKey&token=myToken
content: '{"text":"New package published: `{{ name }}{{#each versions}} v{{version}}{{/each}}`"}'
'example-hipchat':
method: POST
headers: [{ 'Content-Type': 'application/json' }]
endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'
'example-stride':
method: POST
headers: [{ 'Content-Type': 'application/json' }, { 'authorization': 'Bearer secretToken' }]
endpoint: https://api.atlassian.com/site/{cloudId}/conversation/{conversationId}/message
content: '{"body": {"version": 1,"type": "doc","content": [{"type": "paragraph","content": [{"type": "text","text": "New package published: * {{ name }}* Publisher name: * {{ publisher.name }}"}]}]}}'
```
## Template {#template}
We use [Handlebars](https://handlebarsjs.com/) as main template engine.
### Format Examples {#format-examples}
```
# iterate all versions
{{ name }}{{#each versions}} v{{version}}{{/each}}
# publisher and `dist-tag` package published
{{ publisher.name }} has published {{ publishedPackage }}
```
### Properties {#properties}
List of properties accesible via template
- Metadata
- Publisher (who is publishing)
- Package Published (package@1.0.0)
### Metadata {#metadata}
Package metadata that the template has access
```
{
"_id": "@test/pkg1",
"name": "@test/pkg1",
"description": "",
"dist-tags": {
"beta": "1.0.54"
},
"versions": {
"1.0.54": {
"name": "@test/pkg1",
"version": "1.0.54",
"description": "some description",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": {
"name": "Author Name",
"email": "author@domain.com"
},
"license": "MIT",
"dependencies": {
"webpack": "4.12.0"
},
"readmeFilename": "README.md",
"_id": "@ test/pkg1@1.0.54",
"_npmVersion": "6.1.0",
"_nodeVersion": "9.9.0",
"_npmUser": {},
"dist": {
"integrity": "sha512-JlXWpLtMUBAqvVZBvH7UVLhXkGE1ctmXbDjbH/l0zMuG7wVzQ7GshTYvD/b5C+G2vOL2oiIS1RtayA/kKkTwKw==",
"shasum": "29c55c52c1e76e966e706165e5b9f22e32aa9f22",
"tarball": "http://localhost:4873/@test/pkg1/-/@test/pkg1-1.0.54.tgz"
}
}
},
"readme": "# test",
"_attachments": {
"@test/pkg1-1.0.54.tgz": {
"content_type": "application/octet-stream",
"data": "H4sIAAAAAAAAE+y9Z5PjyJIgOJ ...",
"length": 33112
}
},
"time": {}
}
```
### Publisher {#publisher}
You can get access to the package publisher information in the `content` of a webhook using the `publisher` object.
See below the `publisher` object type:
```
{
name: string,
groups: string[],
real_groups: string[]
}
```
An example:
```
notify:
method: POST
headers: [{'Content-Type': 'application/json'}]
endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
content: '{"color":"green","message":"New package published: * {{ name }}*. Publisher name: * {{ publisher.name }} *.","notify":true,"message_format":"text"}'
```
**Note:** it's not possible to get the publisher information if the `package.json` file already has the `publisher` property.
### Package Published {#package-published}
You can access to the package is being published with the keyword `{{publishedPackage}}` as follows.
```
{{ publisher.name }} has published {{ publishedPackage }}
```
## Configuration {#configuration}
| Property | Type | Required | Support | Default | Description |
| ------------------- | ------------ | -------- | ------- | ------- | -------------------------------------------------------------------------------------------- |
| method | string | No | all | | HTTP verb |
| packagePattern | string | No | all | | Only run this notification if the package name matches the regular expression |
| packagePatternFlags | string | No | all | | Any flags to be used with the regular expression |
| headers | array/object | Yes | all | | If this endpoint requires specific headers, set them here as an array of key: value objects. |
| endpoint | string | Yes | all | | set the URL endpoint for this call |
| content | string | Yes | all | | any [Handlebar](https://handlebarsjs.com/) expressions |

View File

@@ -1,200 +0,0 @@
---
id: packages
title: 'Package Access'
---
This is a series of constraints that allow or restrict access to the local storage based on specific criteria.
The security constraints remain on the shoulders of the plugin being used, by default `verdaccio` uses the [htpasswd plugin](https://github.com/verdaccio/verdaccio-htpasswd). If you use a different plugin the behaviour might be different. The default plugin does not handle `allow_access` and `allow_publish` by itself, it uses an internal fallback in case the plugin is not ready for it.
For more information about permissions visit [the authentification section in the wiki](auth.md).
### Usage {#usage}
```yaml
packages:
# scoped packages
'@scope/*':
access: $all
publish: $all
proxy: server2
'private-*':
access: $all
publish: $all
proxy: uplink1
'**':
# allow all users (including non-authenticated users) to read and
# publish all packages
access: $all
publish: $all
proxy: uplink2
```
if none is specified, the default one remains
```yaml
packages:
'**':
access: $all
publish: $authenticated
```
The list internal groups handled by `verdaccio` are:
```js
'$all', '$anonymous', '@all', '@anonymous', 'all', 'undefined', 'anonymous';
```
All users receive all those set of permissions independently of is anonymous or not plus the groups provided by the plugin, in case of `htpasswd` return the username as a group. For instance, if you are logged as `npmUser` the list of groups will be.
```js
// groups without '$' are going to be deprecated eventually
'$all', '$anonymous', '@all', '@anonymous', 'all', 'undefined', 'anonymous', 'npmUser';
```
If you want to protect specific set packages under your group, you need to do something like this. Let's use a `Regex` that covers all prefixed `npmuser-` packages. We recommend using a prefix for your packages, in that way it will be easier to protect them.
```yaml
packages:
'npmuser-*':
access: npmuser
publish: npmuser
```
Restart `verdaccio` and in your console try to install `npmuser-core`.
```bash
$ npm install npmuser-core
npm install npmuser-core
npm ERR! code E403
npm ERR! 403 Forbidden: npmuser-core@latest
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/user/.npm/_logs/2017-07-02T12_20_14_834Z-debug.log
```
You can change the existing behaviour using a different plugin authentication. `verdaccio` just checks whether the user that tried to access or publish a specific package belongs to the right group.
Please note that if you set the `access` permission of a package to something that requires Verdaccio to check your identity, for example `$authenticated`, npm does not send your access key by default when fetching packages. This means all requests for downloading packages will be rejected as they are made anonymously even if you have logged in. To make npm include you access key with all requests, you should set the [always-auth](https://docs.npmjs.com/cli/v7/using-npm/config#always-auth) npm setting to true on any client machines. This can be accomplished by running:
```bash
$ npm config set always-auth=true
```
#### Set multiple groups {#set-multiple-groups}
Defining multiple access groups is fairly easy, just define them with a white space between them.
```yaml
'company-*':
access: admin internal
publish: admin
proxy: server1
'supersecret-*':
access: secret super-secret-area ultra-secret-area
publish: secret ultra-secret-area
proxy: server1
```
#### Blocking access to set of packages {#blocking-access-to-set-of-packages}
If you want to block the access/publish to a specific group of packages. Just do not define `access` and `publish`.
```yaml
packages:
'old-*':
'**':
access: $all
publish: $authenticated
```
#### Blocking proxying a set of specific packages {#blocking-proxying-a-set-of-specific-packages}
You might want to block one or several packages from fetching from remote repositories., but, at the same time, allow others to access different _uplinks_.
Let's see the following example:
```yaml
packages:
'jquery':
access: $all
publish: $all
'my-company-*':
access: $all
publish: $authenticated
'@my-local-scope/*':
access: $all
publish: $authenticated
'**':
access: $all
publish: $authenticated
proxy: npmjs
```
Let's describe what we want with the above example:
- I want to host my own `jquery` dependency but I need to avoid proxying it.
- I want all dependencies that match with `my-company-*` but I need to avoid proxying them.
- I want all dependencies that are in the `my-local-scope` scope but I need to avoid proxying them.
- I want proxying for all the rest of the dependencies.
Be **aware that the order of your packages definitions is important and always use double wilcard**. Because if you do not include it `verdaccio` will include it for you and the way that your dependencies are resolved will be affected.
#### Use multiple uplinks {#use-multiple-uplinks}
You may assign multiple uplinks for use as a proxy to use in the case of failover, or where there may be other private registries in use.
```yaml
'**':
access: $all
publish: $authenticated
proxy: npmjs uplink2
```
#### Unpublishing Packages {#unpublishing-packages}
The property `publish` handle permissions for `npm publish` and `npm unpublish`. But, if you want to be more specific, you can use the property
`unpublish` in your package access section, for instance:
```yaml
packages:
'jquery':
access: $all
publish: $all
unpublish: root
'my-company-*':
access: $all
publish: $authenticated
unpublish:
'@my-local-scope/*':
access: $all
publish: $authenticated
# unpublish: property commented out
'**':
access: $all
publish: $authenticated
proxy: npmjs
```
In the previous example, the behaviour would be described:
- all users can publish the `jquery` package, but only the user `root` would be able to unpublish any version.
- only authenticated users can publish `my-company-*` packages, but **nobody would be allowed to unpublish them**.
- If `unpublish` is commented out, the access will be granted or denied by the `publish` definition.
### Configuration {#configuration}
You can define mutiple `packages` and each of them must have an unique `Regex`. The syntax is based on [minimatch glob expressions](https://github.com/isaacs/minimatch).
| Property | Type | Required | Example | Support | Description |
| -------- | ------ | -------- | -------------- | -------------- | ------------------------------------------------------------------------- |
| access | string | No | $all | all | define groups allowed to access the package |
| publish | string | No | $authenticated | all | define groups allowed to publish |
| proxy | string | No | npmjs | all | limit look ups for specific uplink |
| storage | string | No | string | `/some-folder` | it creates a subfolder whithin the storage folder for each package access |
> We higlight that we recommend to not use **allow_access**/**allow_publish** and **proxy_access** anymore, those are deprecated and will soon be removed, please use the short version of each of those (**access**/**publish**/**proxy**).
If you want more information about how to use the **storage** property, please refer to this [comment](https://github.com/verdaccio/verdaccio/issues/1383#issuecomment-509933674).

View File

@@ -1,304 +0,0 @@
---
id: plugin-auth
title: 'Authentication Plugin'
---
## What's an authentication plugin? {#whats-an-authentication-plugin}
Is a sort plugin that allows to handle who access or publish to a specific package. By default the `htpasswd` is built-in, but can
easily be replaced by your own.
## Getting Started
The authentication plugins are defined in the `auth:` section, as follows:
```yaml
auth:
htpasswd:
file: ./htpasswd
```
also multiple plugins can be chained:
```yaml
auth:
htpasswd:
file: ./htpasswd
anotherAuth:
foo: bar
bar: foo
lastPlugin:
foo: bar
bar: foo
```
> If one of the plugin in the chain is able to resolve the request, the next ones will be ignored.
## How do the authentication plugin works? {#how-do-the-authentication-plugin-works}
Basically we have to return an object with a single method called `authenticate` that will receive 3 arguments (`user, password, callback`).
On each request, `authenticate` will be triggered and the plugin should return the credentials, if the `authenticate` fails, it will fallback to the `$anonymous` role by default.
### API {#api}
```typescript
interface IPluginAuth<T> extends IPlugin<T> {
authenticate(user: string, password: string, cb: AuthCallback): void;
adduser?(user: string, password: string, cb: AuthCallback): void;
changePassword?(user: string, password: string, newPassword: string, cb: AuthCallback): void;
allow_publish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
allow_access?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
allow_unpublish?(
user: RemoteUser,
pkg: AllowAccess & PackageAccess,
cb: AuthAccessCallback
): void;
apiJWTmiddleware?(helpers: any): Function;
}
```
> Only `adduser`, `allow_access`, `apiJWTmiddleware`, `allow_publish` and `allow_unpublish` are optional, verdaccio provide a fallback in all those cases.
#### `apiJWTmiddleware` method {#apijwtmiddleware-method}
Since `v4.0.0`
`apiJWTmiddleware` was introduced on [PR#1227](https://github.com/verdaccio/verdaccio/pull/1227) in order to have full control of the token handler, overriding this method will disable `login/adduser` support. We recommend don't implement this method unless is totally necessary. See a full example [here](https://github.com/verdaccio/verdaccio/pull/1227#issuecomment-463235068).
## What should I return in each of the methods? {#what-should-i-return-in-each-of-the-methods}
Verdaccio relies on `callback` functions at time of this writing. Each method should call the method and what you return is important, let's review how to do it.
### `authentication` callback {#authentication-callback}
Once the authentication has been executed there is 2 options to give a response to `verdaccio`.
##### If the authentication fails {#if-the-authentication-fails}
If the auth was unsuccessful, return `false` as the second argument.
```typescript
callback(null, false);
```
##### If the authentication success {#if-the-authentication-success}
The auth was successful.
`groups` is an array of strings where the user is part of.
```
callback(null, groups);
```
##### If the authentication produce an error {#if-the-authentication-produce-an-error}
The authentication service might fails, and you might want to reflect that in the user response, eg: service is unavailable.
```
import { getInternalError } from '@verdaccio/commons-api';
callback(getInternalError('something bad message), null);
```
> A failure on login is not the same as service error, if you want to notify user the credentials are wrong, just return `false` instead string of groups. The behaviour mostly depends of you.
### `adduser` callback {#adduser-callback}
##### If adduser success {#if-adduser-success}
If the service is able to create an user, return `true` as the second argument.
```typescript
callback(null, true);
```
##### If adduser fails {#if-adduser-fails}
Any other action different than success must return an error.
```typescript
import { getConflict } from '@verdaccio/commons-api';
const err = getConflict('maximum amount of users reached');
callback(err);
```
### `changePassword` callback {#changepassword-callback}
##### If the request is successful {#if-the-request-is-successful}
If the service is able to create an user, return `true` as the second argument.
```typescript
const user = serviceUpdatePassword(user, password, newPassword);
callback(null, user);
```
##### If the request fails {#if-the-request-fails}
Any other action different than success must return an error.
```typescript
import { getNotFound } from '@verdaccio/commons-api';
const err = getNotFound('user not found');
callback(err);
```
### `allow_access`, `allow_publish`, or `allow_unpublish` callback {#allow_access-allow_publish-or-allow_unpublish-callback}
These methods aims to allow or deny trigger some actions.
##### If the request success {#if-the-request-success}
If the service is able to create an user, return a `true` as the second argument.
```typescript
allow_access(user: RemoteUser, pkg: PackageAccess, cb: Callback): void {
const isAllowed: boolean = checkAction(user, pkg);
callback(null, isAllowed)
}
```
##### If the request fails {#if-the-request-fails-1}
Any other action different than success must return an error.
```typescript
import { getNotFound } from '@verdaccio/commons-api';
const err = getForbidden('not allowed to access package');
callback(err);
```
## Generate an authentication plugin {#generate-an-authentication-plugin}
For detailed info check our [plugin generator page](plugin-generator). Run the `yo` command in your terminal and follow the steps.
```
➜ yo verdaccio-plugin
Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator
_-----_ ╭──────────────────────────╮
| | │ Welcome to │
|--(o)--| │ generator-verdaccio-plug │
`---------´ │ in plugin generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What is the name of your plugin? service-name
? Select Language typescript
? What kind of plugin you want to create? auth
? Please, describe your plugin awesome auth plugin
? GitHub username or organization myusername
? Author's Name Juan Picado
? Author's Email jotadeveloper@gmail.com
? Key your keywords (comma to split) verdaccio,plugin,auth,awesome,verdaccio-plugin
create verdaccio-plugin-authservice-name/package.json
create verdaccio-plugin-authservice-name/.gitignore
create verdaccio-plugin-authservice-name/.npmignore
create verdaccio-plugin-authservice-name/jest.config.js
create verdaccio-plugin-authservice-name/.babelrc
create verdaccio-plugin-authservice-name/.travis.yml
create verdaccio-plugin-authservice-name/README.md
create verdaccio-plugin-authservice-name/.eslintrc
create verdaccio-plugin-authservice-name/.eslintignore
create verdaccio-plugin-authservice-name/src/index.ts
create verdaccio-plugin-authservice-name/index.ts
create verdaccio-plugin-authservice-name/tsconfig.json
create verdaccio-plugin-authservice-name/types/index.ts
create verdaccio-plugin-authservice-name/.editorconfig
I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
⸨ ░░░░░░░░░░░░░░░░░⸩ ⠋ fetchMetadata: sill pacote range manifest for @babel/plugin-syntax-jsx@^7.7.4 fetc
```
After the install finish, access to your project scalfold.
```
➜ cd verdaccio-plugin-service-name
➜ cat package.json
{
"name": "verdaccio-plugin-service-name",
"version": "0.0.1",
"description": "awesome auth plugin",
...
```
## Full implementation ES5 example {#full-implementation-es5-example}
```javascript
function Auth(config, stuff) {
var self = Object.create(Auth.prototype);
self._users = {};
// config for this module
self._config = config;
// verdaccio logger
self._logger = stuff.logger;
// pass verdaccio logger to ldapauth
self._config.client_options.log = stuff.logger;
return self;
}
Auth.prototype.authenticate = function (user, password, callback) {
var LdapClient = new LdapAuth(self._config.client_options);
....
LdapClient.authenticate(user, password, function (err, ldapUser) {
...
var groups;
...
callback(null, groups);
});
};
module.exports = Auth;
```
And the configuration will looks like:
```yaml
auth:
htpasswd:
file: ./htpasswd
```
Where `htpasswd` is the sufix of the plugin name. eg: `verdaccio-htpasswd` and the rest of the body would be the plugin configuration params.
### List Community Authentication Plugins {#list-community-authentication-plugins}
- [verdaccio-bitbucket](https://github.com/idangozlan/verdaccio-bitbucket): Bitbucket authentication plugin for verdaccio.
- [verdaccio-bitbucket-server](https://github.com/oeph/verdaccio-bitbucket-server): Bitbucket Server authentication plugin for verdaccio.
- [verdaccio-ldap](https://www.npmjs.com/package/verdaccio-ldap): LDAP auth plugin for verdaccio.
- [verdaccio-active-directory](https://github.com/nowhammies/verdaccio-activedirectory): Active Directory authentication plugin for verdaccio
- [verdaccio-gitlab](https://github.com/bufferoverflow/verdaccio-gitlab): use GitLab Personal Access Token to authenticate
- [verdaccio-gitlab-ci](https://github.com/lab360-ch/verdaccio-gitlab-ci): Enable GitLab CI to authenticate against verdaccio.
- [verdaccio-htpasswd](https://github.com/verdaccio/verdaccio-htpasswd): Auth based on htpasswd file plugin (built-in) for verdaccio
- [verdaccio-github-oauth](https://github.com/aroundus-inc/verdaccio-github-oauth): Github oauth authentication plugin for verdaccio.
- [verdaccio-github-oauth-ui](https://github.com/n4bb12/verdaccio-github-oauth-ui): GitHub OAuth plugin for the verdaccio login button.
- [verdaccio-groupnames](https://github.com/deinstapel/verdaccio-groupnames): Plugin to handle dynamic group associations utilizing `$group` syntax. Works best with the ldap plugin.
- [verdaccio-sqlite](https://github.com/bchanudet/verdaccio-sqlite): SQLite Authentication plugin for Verdaccio
- [verdaccio-okta-auth](https://github.com/hogarthww-labs/verdaccio-okta-auth) Verdaccio Okta Auth
- [verdaccio-azure-ad-login](https://github.com/IhToN/verdaccio-azure-ad-login) Let your users authenticate into Verdaccio via Azure AD OAuth 2.0 API
- [verdaccio-auth-gitlab](https://github.com/pfdgithub/verdaccio-auth-gitlab) Verdaccio authentication plugin by gitlab personal access tokens.
**Have you developed a new plugin? Add it here !**

View File

@@ -1,42 +0,0 @@
---
id: plugin-filter
title: 'Filter Plugin'
---
## What's a filter plugin? {#whats-a-filter-plugin}
:::caution
Filter plugins are **experimental** and requires more users feedback
:::caution
### When to use a filter plugin? {#when-to-use}
If you need to mutate the metadata for different reasons this is a way to do it, all manifest request are intercepted, but the tarballs, user, profile or tokens requests are not included. A good example to review is the [verdaccio-plugin-secfilter](https://github.com/Ansile/verdaccio-plugin-secfilter).
### Plugin structure {#build-structure}
The plugin only has one async method named `filter_metadata` that reference of the manifest and must return a copy (or modified object but not recommended) of the metadata.
```ts
export default class VerdaccioMiddlewarePlugin implements IPluginStorageFilter<CustomConfig> {
async filter_metadata(metadata: Readonly<Manifest>): Promise<Package> {
// modify the metadata
const newMetadata = { ...metadata, ...{ name: 'fooName' } };
return newMetadata;
}
}
```
### Configuration
Just add `filters` to the `config.yaml` file and your own plugin options.
```yaml
filters:
storage-filter-blackwhitelist:
filter_file: /path/to/file
```
More [info in the PR](https://github.com/verdaccio/verdaccio/pull/1161).

View File

@@ -1,82 +0,0 @@
---
id: plugin-generator
title: 'Plugin Generator'
---
## Installing the Yeoman Generator {#installing-the-yeoman-generator}
Verdaccio is a pluggable application, with the objective to help developers to generate new plugins, we have a custom generator based in **[Yeoman](https://yeoman.io/)** for generate all sort of plugins.
To install the generator, as first step you must install the _yeoman_ command `yo`.
```bash
npm install -g yo@4
```
then, install the custom generator running the following in your terminal.
```
npm i -g generator-verdaccio-plugin
```
:::caution
`generator-verdaccio-plugin` is not compatible with yeoman version 5 yet. You must use version 4 for it to function correctly.
:::
## Using the generator {#using-the-generator}
Use `yeoman` is quite straighforward, you can read more information about it [here](https://yeoman.io/learning/index.html).
After a success install, run `yo verdaccio-plugin` in your terminal and follow the steps.
```
➜ yo verdaccio-plugin
Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator
_-----_ ╭──────────────────────────╮
| | │ Welcome to │
|--(o)--| │ generator-verdaccio-plug │
`---------´ │ in plugin generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What is the name of your plugin? (customname)
```
### Best practices {#best-practices}
- We recommend using **Typescript** for developing new plugins, we provide an extense support of Types which help you along the development.
```
? What is the name of your plugin? my-plugin
? Select Language (Use arrow keys)
typescript
javascript
```
- On describe your plugin, be brief and explicit, remember a good description will increase your chances your pluing to be used.
```
? Please, describe your plugin (An amazing verdaccio plugin)
```
- Don't hesitate to include meaningful keywords, as `verdaccio`, `plugin` or your plugin type. Good keywords will help us to find you and future improvement in our collect information about all plugins.
```
? Key your keywords (comma to split) verdaccio,plugin,storage,minio,verdaccio-plugin
```
- Keep your generator **updated**, don't miss any bug-fixes and performance improvements.
### Contributing {#contributing}
Help us to improve the generator, you can contribute in the following repository.
[https://github.com/verdaccio/generator-verdaccio-plugin](https://github.com/verdaccio/generator-verdaccio-plugin)

View File

@@ -1,119 +0,0 @@
---
id: plugin-middleware
title: 'Middleware Plugin'
---
## What's a middleware plugin? {#whats-a-middleware-plugin}
Middleware plugins have the capability to modify the API (web and cli) layer, either adding new endpoints or intercepting requests.
### API {#api}
```typescript
interface IPluginMiddleware<T> extends IPlugin<T> {
register_middlewares(app: any, auth: IBasicAuth<T>, storage: IStorageManager<T>): void;
}
```
### `register_middlewares` {#register_middlewares}
The method provide full access to the authentification and storage via `auth` and `storage`. `app` is the express application that allows you to add new endpoints.
```typescript
public register_middlewares(
app: Application,
auth: IBasicAuth<CustomConfig>,
storage: IStorageManager<CustomConfig>
): void {
const router = Router();
router.post(
'/custom-endpoint',
(req: Request, res: Response & { report_error?: Function }, next: NextFunction): void => {
const encryptedString = auth.aesEncrypt(Buffer.from(this.foo, 'utf8'));
res.setHeader('X-Verdaccio-Token-Plugin', encryptedString.toString());
next();
}
);
app.use('/-/npm/something-new', router);
}
```
The `auth` and `storage` are instances and can be extended, but we don't recommend this approach unless is well founded.
> A good example of a middleware plugin is the [verdaccio-audit](https://github.com/verdaccio/monorepo/tree/master/plugins/audit).
## Generate an middleware plugin {#generate-an-middleware-plugin}
For detailed info check our [plugin generator page](plugin-generator). Run the `yo` command in your terminal and follow the steps.
```
➜ yo verdaccio-plugin
Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator
_-----_ ╭──────────────────────────╮
| | │ Welcome to │
|--(o)--| │ generator-verdaccio-plug │
`---------´ │ in plugin generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What is the name of your plugin? custom-endpoint
? Select Language typescript
? What kind of plugin you want to create? middleware
? Please, describe your plugin awesome middleware plugin
? GitHub username or organization myusername
? Author's Name Juan Picado
? Author's Email jotadeveloper@gmail.com
? Key your keywords (comma to split) verdaccio,plugin,middleware,awesome,verdaccio-plugin
create verdaccio-plugin-custom-endpoint/package.json
create verdaccio-plugin-custom-endpoint/.gitignore
create verdaccio-plugin-custom-endpoint/.npmignore
create verdaccio-plugin-custom-endpoint/jest.config.js
create verdaccio-plugin-custom-endpoint/.babelrc
create verdaccio-plugin-custom-endpoint/.travis.yml
create verdaccio-plugin-custom-endpoint/README.md
create verdaccio-plugin-custom-endpoint/.eslintrc
create verdaccio-plugin-custom-endpoint/.eslintignore
create verdaccio-plugin-custom-endpoint/src/index.ts
create verdaccio-plugin-custom-endpoint/index.ts
create verdaccio-plugin-custom-endpoint/tsconfig.json
create verdaccio-plugin-custom-endpoint/types/index.ts
create verdaccio-plugin-custom-endpoint/.editorconfig
I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
⸨ ░░░░░░░░░░░░░░░░░⸩ ⠋ fetchMetadata: sill pacote range manifest for @babel/plugin-syntax-jsx@^7.7.4 fetc
```
After the install finish, access to your project scalfold.
```
➜ cd verdaccio-plugin-auth-service-name
➜ cat package.json
{
"name": "verdaccio-plugin-custom-endpoint",
"version": "0.0.1",
"description": "awesome middleware plugin",
...
```
The middleware are registrered after built-in endpoints, thus, it is not possible to override the implemented ones.
### List Community Middleware Plugins {#list-community-middleware-plugins}
- [verdaccio-audit](https://github.com/verdaccio/verdaccio-audit): verdaccio plugin for _npm audit_ cli support (built-in) (compatible since 3.x)
- [verdaccio-profile-api](https://github.com/ahoracek/verdaccio-profile-api): verdaccio plugin for _npm profile_ cli support and _npm profile set password_ for _verdaccio-htpasswd_ based authentificaton
- [verdaccio-https](https://github.com/honzahommer/verdaccio-https) Verdaccio middleware plugin to redirect to https if x-forwarded-proto header is set
- [verdaccio-badges](https://github.com/tavvy/verdaccio-badges) A verdaccio plugin to provide a version badge generator endpoint
- [verdaccio-openmetrics](https://github.com/freight-hub/verdaccio-openmetrics) Verdaccio plugin exposing an OpenMetrics/Prometheus endpoint with health and traffic metrics
- [verdaccio-sentry](https://github.com/juanpicado/verdaccio-sentry) sentry loggin errors
- [verdaccio-pacman](https://github.com/PaddeK/verdaccio-pacman) Verdaccio Middleware Plugin to manage tags and versions of packages

View File

@@ -1,116 +0,0 @@
---
id: plugin-storage
title: 'Storage Plugin'
---
## What's a storage plugin? {#whats-an-storage-plugin}
Verdaccio by default uses a file system storage plugin [local-storage](https://github.com/verdaccio/verdaccio/tree/master/packages/plugins/local-storage). The default storage can be easily replaced, either using a community plugin or creating one by your own.
### API {#api}
Storage plugins are composed of two objects, the `IPluginStorage<T>` and the `IPackageStorage`.
- The `IPluginStorage` object handle the local database for private packages.
```typescript
interface IPluginStorage<T> extends IPlugin<T>, ITokenActions {
logger: Logger;
config: T & Config;
add(name: string, callback: Callback): void;
remove(name: string, callback: Callback): void;
get(callback: Callback): void;
getSecret(): Promise<string>;
setSecret(secret: string): Promise<any>;
getPackageStorage(packageInfo: string): IPackageStorage;
search(
onPackage: onSearchPackage,
onEnd: onEndSearchPackage,
validateName: onValidatePackage
): void;
}
```
- The `IPackageStorage` is an object that is created by each request that handles the I/O actions for the metadata and tarballs.
```typescript
interface IPackageStorage {
logger: Logger;
writeTarball(pkgName: string): IUploadTarball;
readTarball(pkgName: string): IReadTarball;
readPackage(fileName: string, callback: ReadPackageCallback): void;
createPackage(pkgName: string, value: Package, cb: CallbackAction): void;
deletePackage(fileName: string, callback: CallbackAction): void;
removePackage(callback: CallbackAction): void;
updatePackage(
pkgFileName: string,
updateHandler: StorageUpdateCallback,
onWrite: StorageWriteCallback,
transformPackage: PackageTransformer,
onEnd: CallbackAction
): void;
savePackage(fileName: string, json: Package, callback: CallbackAction): void;
}
```
## Generate an middleware plugin {#generate-an-middleware-plugin}
For detailed info check our [plugin generator page](plugin-generator). Run the `yo` command in your terminal and follow the steps.
```
➜ yo verdaccio-plugin
Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator
_-----_ ╭──────────────────────────╮
| | │ Welcome to │
|--(o)--| │ generator-verdaccio-plug │
`---------´ │ in plugin generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What is the name of your plugin? custom-endpoint
? Select Language typescript
? What kind of plugin you want to create? storage
? Please, describe your plugin awesome storage plugin
? GitHub username or organization myusername
? Author's Name Juan Picado
? Author's Email jotadeveloper@gmail.com
? Key your keywords (comma to split) verdaccio,plugin,storage,awesome,verdaccio-plugin
create verdaccio-plugin-storage-package-database/package.json
create verdaccio-plugin-storage-package-database/.gitignore
create verdaccio-plugin-storage-package-database/.npmignore
create verdaccio-plugin-storage-package-database/jest.config.js
create verdaccio-plugin-storage-package-database/.babelrc
create verdaccio-plugin-storage-package-database/.travis.yml
create verdaccio-plugin-storage-package-database/README.md
create verdaccio-plugin-storage-package-database/.eslintrc
create verdaccio-plugin-storage-package-database/.eslintignore
create verdaccio-plugin-storage-package-database/src/PackageStorage.ts
create verdaccio-plugin-storage-package-database/src/index.ts
create verdaccio-plugin-storage-package-database/src/plugin.ts
create verdaccio-plugin-storage-package-database/index.ts
create verdaccio-plugin-storage-package-database/tsconfig.json
create verdaccio-plugin-storage-package-database/types/index.ts
create verdaccio-plugin-storage-package-database/.editorconfig
I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
⸨ ░░░░░░░░░░░░░░░░░⸩ ⠋ fetchMetadata: sill pacote range manifest for @babel/plugin-syntax-jsx@^7.7.4 fetc
```
### List Community Storage Plugins {#list-community-storage-plugins}
The following list of plugins are implementing the Storage API and might be used them as example.
- [verdaccio-memory](https://github.com/verdaccio/verdaccio-memory) Storage plugin to host packages in Memory
- [verdaccio-s3-storage](https://github.com/remitly/verdaccio-s3-storage) Storage plugin to host packages **Amazon S3**
- [verdaccio-aws-s3-storage](https://github.com/verdaccio/monorepo/tree/master/plugins/aws-s3-storage) Storage plugin to host packages **Amazon S3** (maintained by Verdaccio core team)
- [verdaccio-google-cloud](https://github.com/verdaccio/verdaccio-google-cloud) Storage plugin to host packages **Google Cloud Storage**
- [verdaccio-minio](https://github.com/barolab/verdaccio-minio) A verdaccio plugin for storing data in Minio
- [verdaccio-offline-storage](https://github.com/g3ngar/verdaccio-offline-storage) local-storage plugin BUT with locally available packages as first class citizens.

View File

@@ -1,182 +0,0 @@
---
id: plugin-theme
title: 'Theme Plugin'
---
## What's a theme plugin? {#whats-a-theme-plugin}
Verdaccio uses by default a [custom UI](https://www.npmjs.com/package/@verdaccio/ui-theme) that provides a good set of feature to visualize the packages, but might be case your team needs some custom extra features and here is where a custom theme is an option. The plugin store static assets that will be loaded in the client side when the page is being rendered.
### How a theme plugin load phase works?
```mermaid
stateDiagram-v2
state if_loads <<choice>>
state if_load_fails <<choice>>
start : Verdaccio start
Yes: Loading custom plugin
No: Custom plugin not found
Yes_loads: Plugin loads successfully
No_loads: Plugin fails on load
load_default: Load default theme (@verdaccio/theme-ui)
Crash: Verdaccio stops
[*] --> start
start --> if_loads
if_loads --> No: false
if_loads --> Yes : true
Yes --> if_load_fails
No --> load_default
if_load_fails --> No_loads: false
if_load_fails --> Yes_loads : true
No_loads --> Crash
```
### How the assets of the theme loads? {#loads}
:::caution
By default the application loads on `http://localhost:4873`, but in cases where a resverse proxy with custom domain are involved the assets are loaded based on the property `__VERDACCIO_BASENAME_UI_OPTIONS.base` and `__VERDACCIO_BASENAME_UI_OPTIONS.basename`, thus only one domain configuration can be used.
:::caution
The theme loads only in the client side, the application renders HTML with `<script>` tags to render the application, the bundler takes care of load any other assets as `svg`, `images` or _chunks_ associated with it.
### The `__VERDACCIO_BASENAME_UI_OPTIONS` object
The `window.__VERDACCIO_BASENAME_UI_OPTIONS` is available in the browser global context, the shape is documented is defined by the [here](https://verdaccio.org/docs/next/api/types/modules/#templateuioptions) at the `TemplateUIOptions` types definitions.
```js
// output example
{
"darkMode": false,
"basename": "/",
"base": "https://registry.my.org/",
"primaryColor": "#4b5e40",
"version": "5.20.1",
"pkgManagers": [
"yarn",
"pnpm",
"npm"
],
"login": true,
"logo": "",
"title": "Verdaccio Registry",
"scope": "",
"language": "es-US"
}
```
### Theme Configuration {#theme-configuration}
By default verdaccio loads the `@verdaccio/ui-theme` which is bundled in the main package, if you want to load your custom plugin has to be installed where could be found.
```bash
$> npm install --global verdaccio-theme-dark
```
:::caution
The plugin name prefix must start with `verdaccio-theme-xxx`, otherwise the plugin will be ignored.
:::caution
You can load only **one theme at a time (if more are provided the first one is being selected)** and pass through options if you need it.
```yaml
theme:
dark:
option1: foo
option2: bar
```
These options will be available
### Plugin structure {#build-structure}
If you have a custom user interface theme has to follow a specific structure:
```
{
"name": "verdaccio-theme-xxxx",
"version": "1.0.0",
"description": "my custom user interface",
"main": "index.js",
}
```
The main file `index.js` file should contain the following content.
```
module.exports = () => {
return {
// location of the static files, webpack output
staticPath: path.join(__dirname, 'static'),
// webpack manifest json file
manifest: require('./static/manifest.json'),
// main manifest files to be loaded
manifestFiles: {
js: ['runtime.js', 'vendors.js', 'main.js'],
},
};
};
```
If any of the following properties are not available, the plugin won't load, thus follow this structure.
- `staticPath`: is the absolute/relative location of the statics files, could be any path either with `require.resolve` or build your self, what's important is inside of the package or any location that the Express.js middleware is able to find, behind the scenes the [`res.sendFile`](https://expressjs.com/en/api.html#res.sendFile) is being used.
- `manifest`: A Webpack manifest object.
- `manifestFiles`: A object with one property `js` and the array (order matters) of the manifest id to be loaded in the template dynamically.
- The `manifestFiles` refers to the main files must be loaded as part of the `html` scripts in order to load the page, you don't have to include the _chunks_ since are dynamically loaded by the bundler.
#### Manifest file {#manifest-and-webpack}
Verdaccio requires a [manifest](https://webpack.js.org/concepts/manifest/) object to render the html dynamically, in combination with the `manifestFiles` the application understand what to render.
> Currently only support `js` but if you also need `css`, we are open to discuss it and further improvements.
```
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
plugins: [
...
new WebpackManifestPlugin({
// this is optional depends of your implementation
removeKeyHash: true,
}),
...
],
```
#### Manifest with other bundlers
There is no feedback with other bundlers being used with theme plugins, but with `esbuild` could be possible generate manifests.
Alternatives:
- https://www.npmjs.com/package/esbuild-plugin-manifest
## Components UI {#components}
:::note
The components UI is an experimental feature can be used since verdccio@5.x, it's open to changes and **feedback is welcome**.
:::note
Create a new user interface from scratch is big effort, to facilitate the task exist the [@verdaccio/ui-components](https://www.npmjs.com/package/@verdaccio/ui-components) package. The components are based on the **React** library and **Material UI**.
The package export parts of the user interface that could be reused:
- React Hooks
- Providers (React Context API)
- Components
- Sections: **(Sidebar, Detail, Header, Home Page and Footer)**
https://ui-components.verdaccio.org
<iframe src="https://ui-components.verdaccio.org" height="900"></iframe>

View File

@@ -1,165 +0,0 @@
---
id: plugins
title: 'Plugins'
---
Verdaccio is a pluggable application. It can be extended in many ways, either new authentication methods, adding endpoints or using a custom storage.
There are 5 types of plugins:
- [Authentication](plugin-auth.md)
- [Middleware](plugin-middleware.md)
- [Storage](plugin-storage.md)
- [Theme UI](plugin-theme.md)
- [Filters](plugin-filter.md)
## Usage {#usage}
### Installation {#installation}
```bash
$> npm install --global verdaccio-activedirectory
```
`verdaccio` as a sinopia fork it has backward compatibility with plugins that are compatible with `sinopia@1.4.0`. In such case the installation is the same.
```
$> npm install --global sinopia-memory
```
### Configuration {#configuration}
Open the `config.yaml` file and update the `auth` section as follows:
The default configuration looks like this, due we use a build-in `htpasswd` plugin by default that you can disable just commenting out the following lines.
### Naming convention {#naming-convention}
Since version `2.0.0` until version plugins must start with the following convention:
- `sinopia-xxx` (deprecated and will be removed on 6.x.x)
- `verdaccio-xxx`
After version `5.12.0` scoped plugins are supported, for example:
```yaml
auth:
'@my-org/auth-awesome-plugin':
foo: some value
bar: another value
store:
'@my-org/store-awesome-plugin':
foo: some value
bar: another value
middleware:
'@my-org/middleware-awesome-plugin':
foo: some value
bar: another value
```
### Authentication Configuration {#authentication-configuration}
```yaml
auth:
htpasswd:
file: ./htpasswd
# max_users: 1000
```
and replacing them with (in case you decide to use a `ldap` plugin.
```yaml
auth:
activedirectory:
url: 'ldap://10.0.100.1'
baseDN: 'dc=sample,dc=local'
domainSuffix: 'sample.local'
```
#### Multiple Authentication plugins {#multiple-authentication-plugins}
This is technically possible, making the plugin order important, as the credentials will be resolved in order.
```yaml
auth:
htpasswd:
file: ./htpasswd
#max_users: 1000
activedirectory:
url: 'ldap://10.0.100.1'
baseDN: 'dc=sample,dc=local'
domainSuffix: 'sample.local'
```
### Middleware Configuration {#middleware-configuration}
Example how to set up a middleware plugin. All middleware plugins must be defined in the **middlewares** namespace.
```yaml
middlewares:
audit:
enabled: true
```
> You might follow the [audit middle plugin](https://github.com/verdaccio/verdaccio-audit) as base example.
### Storage Configuration {#storage-configuration}
:::caution
If the `store` property is defined in the `config.yaml` file, the `storage` property is being ignored.
:::caution
Example how to set up a storage plugin. All storage plugins must be defined in the **store** namespace.
```yaml
store:
memory:
limit: 1000
```
### Theme Configuration {#theme-configuration}
```bash
npm install --global verdaccio-theme-dark
```
You can load only one theme at a time and pass through options if you need it.
```yaml
theme:
dark:
option1: foo
option2: bar
```
## Legacy plugins {#legacy-plugins}
### Sinopia Plugins {#sinopia-plugins}
:::caution
Plugins from sinopia era are deprecated but still available in verdaccio@5.x versions but already removed from next 6.x versions, consider migrate them or stop using them for future updates.
:::caution
> If you are relying on any sinopia plugin, remember are deprecated and might no work in the future.
- [sinopia-npm](https://www.npmjs.com/package/sinopia-npm): auth plugin for sinopia supporting an npm registry.
- [sinopia-memory](https://www.npmjs.com/package/sinopia-memory): auth plugin for sinopia that keeps users in memory.
- [sinopia-github-oauth-cli](https://www.npmjs.com/package/sinopia-github-oauth-cli).
- [sinopia-crowd](https://www.npmjs.com/package/sinopia-crowd): auth plugin for sinopia supporting atlassian crowd.
- [sinopia-activedirectory](https://www.npmjs.com/package/sinopia-activedirectory): Active Directory authentication plugin for sinopia.
- [sinopia-github-oauth](https://www.npmjs.com/package/sinopia-github-oauth): authentication plugin for sinopia2, supporting github oauth web flow.
- [sinopia-delegated-auth](https://www.npmjs.com/package/sinopia-delegated-auth): Sinopia authentication plugin that delegates authentication to another HTTP URL
- [sinopia-altldap](https://www.npmjs.com/package/sinopia-altldap): Alternate LDAP Auth plugin for Sinopia
- [sinopia-request](https://www.npmjs.com/package/sinopia-request): An easy and fully auth-plugin with configuration to use an external API.
- [sinopia-htaccess-gpg-email](https://www.npmjs.com/package/sinopia-htaccess-gpg-email): Generate password in htaccess format, encrypt with GPG and send via MailGun API to users.
- [sinopia-mongodb](https://www.npmjs.com/package/sinopia-mongodb): An easy and fully auth-plugin with configuration to use a mongodb database.
- [sinopia-htpasswd](https://www.npmjs.com/package/sinopia-htpasswd): auth plugin for sinopia supporting htpasswd format.
- [sinopia-leveldb](https://www.npmjs.com/package/sinopia-leveldb): a leveldb backed auth plugin for sinopia private npm.
- [sinopia-gitlabheres](https://www.npmjs.com/package/sinopia-gitlabheres): Gitlab authentication plugin for sinopia.
- [sinopia-gitlab](https://www.npmjs.com/package/sinopia-gitlab): Gitlab authentication plugin for sinopia
- [sinopia-ldap](https://www.npmjs.com/package/sinopia-ldap): LDAP auth plugin for sinopia.
- [sinopia-github-oauth-env](https://www.npmjs.com/package/sinopia-github-oauth-env) Sinopia authentication plugin with github oauth web flow.

View File

@@ -1,96 +0,0 @@
---
id: verdaccio-programmatically
title: 'Node.js API'
---
Verdaccio is a binary command which is available in your enviroment when you install globally the package eg `npm i -g verdaccio`, but also can be dependency in your project and use it programmatically.
### Using `fork` from `child_process` module
Using the binary is the faster way to use verdaccio programatically, you need to add to the config file the `_debug: true` to enable the messaging system, when verdaccio is ready will send `verdaccio_started` string as message as the following example.
> If you are using ESM modules the `require` won't be available.
```typescript
export function runRegistry(args: string[] = [], childOptions: {}): Promise<ChildProcess> {
return new Promise((resolve, reject) => {
const childFork = fork(require.resolve('verdaccio/bin/verdaccio'), args, childOptions);
childFork.on('message', (msg: { verdaccio_started: boolean }) => {
if (msg.verdaccio_started) {
resolve(childFork);
}
});
childFork.on('error', (err: any) => reject([err]));
childFork.on('disconnect', (err: any) => reject([err]));
});
}
```
You can see the full example on this repository.
[https://github.com/juanpicado/verdaccio-fork](https://github.com/juanpicado/verdaccio-fork)
### Using the module API
Feature available in `v5.11.0` and higher.
> Using const verdaccio = require('verdaccio'); as the default module is not encoraged, it's deprecated and recommend use `runServer` for future compability.
There are three ways to use it:
- No input, it will find the `config.yaml` as is you would run `verdaccio` in the console.
- With a absolute path.
- With an object (there is a catch here, see below).
```js
const {runServer} = require('verdaccio');
const app = await runServer(); // default configuration
const app = await runServer('./config/config.yaml');
const app = await runServer({ configuration });
app.listen(4000, (event) => {
// do something
});
```
With an object you need to add `self_path`, manually (it's not nice but would be a breaking change changing it now) on v6 this is not longer need it.
```js
const { runServer, parseConfigFile } = require('verdaccio');
const configPath = join(__dirname, './config.yaml');
const c = parseConfigFile(configPath);
// workaround
// on v5 the `self_path` still exists and will be removed in v6
c.self_path = 'foo';
runServer(c).then(() => {});
```
Feature available minor than `v5.11.0`.
> This is a valid way but is discoragued for future releases.
```js
const fs = require('fs');
const path = require('path');
const verdaccio = require('verdaccio').default;
const YAML = require('js-yaml');
const getConfig = () => {
return YAML.load(fs.readFileSync(path.join(__dirname, 'config.yaml'), 'utf8'));
};
const cache = path.join(__dirname, 'cache');
const config = Object.assign({}, getConfig(), {
self_path: cache,
});
verdaccio(config, 6000, cache, '1.0.0', 'verdaccio', (webServer, addrs, pkgName, pkgVersion) => {
try {
webServer.unref();
webServer.listen(addrs.port || addrs.path, addrs.host, () => {
console.log('verdaccio running');
});
} catch (error) {
console.error(error);
}
});
```

View File

@@ -1,45 +0,0 @@
---
id: protect-your-dependencies
title: 'Protecting packages'
---
Verdaccio allows you protect publishing to your registry. To achieve that you will need to set up correctly configure your [packages access](packages).
### Package configuration {#package-configuration}
Let's see for instance the following set up. You have a set of dependencies that are prefixed with `my-company-*` and you need to protect them from anonymous or other non-authorized logged-in users.
```yaml
'my-company-*':
access: admin teamA teamB teamC
publish: admin teamA
```
With this configuration, we allow the groups **admin** and **teamA** to _publish_ and **teamA**, **teamB** and **teamC** to _access_ the specified dependencies.
### Use case: teamD tries to access the dependency {#use-case-teamd-tries-to-access-the-dependency}
So, if I am logged as **teamD**. I shouldn't be able to access all dependencies that match the `my-company-*` pattern.
```bash
➜ npm whoami
teamD
```
I won't have access to such dependencies and they also won't be visible via the web interface for user **teamD**. If I try to access it, the following will happen:
```bash
➜ npm install my-company-core
npm ERR! code E403
npm ERR! 403 Forbidden: webpack-1@latest
```
or with `yarn`:
```bash
➜ yarn add my-company-core
yarn add v0.24.6
info No lockfile found.
[1/4] 🔍 Resolving packages...
error An unexpected error occurred: "http://localhost:5555/webpack-1: unregistered users are not allowed to access package my-company-core".
```

View File

@@ -1,24 +0,0 @@
---
id: puppet
title: 'Puppet'
---
Install verdaccio for Debian, Ubuntu, Fedora, and RedHat.
# Usage
There are two variants to install verdaccio using this Puppet module:
- Apply-mode (with puppet-apply and no puppetmaster setup needed)
- Master-Agent-mode (with puppet-agent accessing your configuration through the puppetmaster).
In both variants you have to explicitly call "class nodejs {}" in your puppet script because
the puppet-verdaccio module only defines this as a requirement, so you have all the flexibility you want when installing nodejs.
Scroll down for details about Master-Agent-mode variant.
For further information:
[https://github.com/verdaccio/puppet-verdaccio](https://github.com/verdaccio/puppet-verdaccio)
> We are looking for active contributors for this integration, if you are interested
> [refers to this ticket](https://github.com/verdaccio/puppet-verdaccio/issues/11).

View File

@@ -1,8 +0,0 @@
---
id: repositories
title: Source Code
---
`verdaccio` is composed or multiple repositories you might contribute. Look into the **issues** tab whether there is a ticket waiting for you 🤠.
To see the complete list of repositories, [click here](https://github.com/verdaccio/verdaccio/wiki/Repositories).

View File

@@ -1,258 +0,0 @@
---
id: reverse-proxy
title: 'Reverse Proxy Setup'
---
Using a reverse proxy is a common practice. The following configurations are the
most recommended and used ones.
**Important**, the headers are considered to resolve the public are `X-Forwarded-Proto` for the protocol and `Host` for the domain, please include them in your configuration.
# Apache
Apache and `mod_proxy` should **not decode/encode slashes** and leave them as they are:
For installing at relative path, `/npm`, on the server
```
<VirtualHost *:80>
AllowEncodedSlashes NoDecode
ProxyPass /npm http://127.0.0.1:4873 nocanon
ProxyPassReverse /npm http://127.0.0.1:4873
</VirtualHost>
```
For installing at root path, `/`, on the server
```
<VirtualHost *:80>
ServerName your.domain.com
ServerAdmin hello@your.domain.com
ProxyPreserveHost On
AllowEncodedSlashes NoDecode
ProxyPass / http://127.0.0.1:4873/ nocanon
ProxyPassReverse / http://127.0.0.1:4873/
</VirtualHost>
```
### Configuration with SSL {#configuration-with-ssl}
Apache virtual server configuration.
```apache
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName npm.your.domain.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/npm.your.domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/npm.your.domain.com/privkey.pem
SSLProxyEngine On
ProxyRequests Off
ProxyPreserveHost On
AllowEncodedSlashes NoDecode
ProxyPass / http://127.0.0.1:4873/ nocanon
ProxyPassReverse / http://127.0.0.1:4873/
RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>
</IfModule>
```
## Invalid checksum
Sometimes the gzip compression can mess with the request when running `npm install` and result in error messages like this:
```
npm WARN tar TAR_ENTRY_INVALID checksum failure
npm WARN tar zlib: incorrect data check
```
A possible fix for this, can be by disabling gzip compression for the virtual host, by adding this to your config:
```
SetEnv no-gzip 1
```
Resulting in a config like so:
```
<VirtualHost *:80>
AllowEncodedSlashes NoDecode
SetEnv no-gzip 1
ProxyPass /npm http://127.0.0.1:4873 nocanon
ProxyPassReverse /npm http://127.0.0.1:4873
</VirtualHost>
```
You should only add it to your virtual host config, if you are experiencing the issue.
# Nginx
The following snippet is a full `docker` example can be tested in our [Docker examples repository](https://github.com/verdaccio/verdaccio/tree/5.x/docker-examples/reverse_proxy/nginx).
```nginx
upstream verdaccio_v4 {
server verdaccio_relative_path_v4:4873;
keepalive 8;
}
upstream verdaccio_v4_root {
server verdaccio_relative_path_v4_root:8000;
keepalive 8;
}
upstream verdaccio_v3 {
server verdaccio_relative_path_latest_v3:7771;
keepalive 8;
}
server {
listen 80 default_server;
access_log /var/log/nginx/verdaccio.log;
charset utf-8;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://verdaccio_v4_root;
proxy_redirect off;
}
location ~ ^/verdaccio/(.*)$ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://verdaccio_v4/$1;
proxy_redirect off;
}
location ~ ^/verdacciov3/(.*)$ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://verdaccio_v3/$1;
proxy_redirect off;
}
}
```
## SSL example {#ssl-example}
```nginx
server {
listen 80;
return 302 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name localhost;
ssl_certificate /etc/nginx/cert.crt;
ssl_certificate_key /etc/nginx/cert.key;
ssl on;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://verdaccio_v4_root;
proxy_read_timeout 600;
proxy_redirect off;
}
location ~ ^/verdaccio/(.*)$ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://verdaccio_v4_root/$1;
proxy_redirect off;
}
}
```
## Run behind reverse proxy with different domain and port {#run-behind-reverse-proxy-with-different-domain-and-port}
### Sub-directory {#sub-directory}
If the whole URL is being used for Verdaccio, you don't need to define a `url_prefix`, otherwise
you would need something like this in your `config.yaml`.
```yaml
url_prefix: /sub_directory/
```
If you run Verdaccio behind reverse proxy, you may noticed all resource file served as relative path, like `http://127.0.0.1:4873/-/static`
To resolve this issue, **you should send real domain and port to Verdaccio with `Host` header**
Nginx configure should look like this:
```nginx
location / {
proxy_pass http://127.0.0.1:4873/;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
```
For this case, `url_prefix` should **NOT** set in Verdaccio config
---
or a sub-directory installation:
```nginx
location ~ ^/verdaccio/(.*)$ {
proxy_pass http://127.0.0.1:4873/$1;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
```
For this case, `url_prefix` should set to `/verdaccio/`
> Note: There is a slash after the install path (`https://your-domain:port/verdaccio/`)!
### Overriding the public url
> Since `verdaccio@5.0.0`
The new `VERDACCIO_PUBLIC_URL` is intended to be used behind proxies, this variable will be used for:
- Used as base path to serve UI resources as (js, favicon, etc)
- Used on return metadata `dist` base path
- Ignores `host` and `X-Forwarded-Proto` headers
- If `url_prefix` is defined would be appened to the env variable.
```
VERDACCIO_PUBLIC_URL='https://somedomain.org';
url_prefix: '/my_prefix'
// url -> https://somedomain.org/my_prefix/
VERDACCIO_PUBLIC_URL='https://somedomain.org';
url_prefix: '/'
// url -> https://somedomain.org/
VERDACCIO_PUBLIC_URL='https://somedomain.org/first_prefix';
url_prefix: '/second_prefix'
// url -> https://somedomain.org/second_prefix/'
```
![Screenshot from 2021-03-24 20-20-11](https://user-images.githubusercontent.com/558752/112371003-5fa1ce00-8cde-11eb-888c-70c4e9776c57.png)

View File

@@ -1,6 +0,0 @@
---
id: security-policy
title: 'Security Policy'
---
Follow our security policy on [GitHub](https://github.com/verdaccio/verdaccio/security/policy)

View File

@@ -1,94 +0,0 @@
---
id: server-configuration
title: 'Server Configuration'
---
This is mostly basic Linux server configuration stuff but I felt it important to document and share the steps I took to get Verdaccio running permanently on my server. You will need root (or sudo) permissions for the following steps.
## Running as a separate user {#running-as-a-separate-user}
First create a Verdaccio user:
```bash
$ sudo adduser --system --gecos 'Verdaccio NPM mirror' --group --home /var/lib/verdaccio verdaccio
```
Or, in case you do not have `adduser`:
```bash
$ sudo useradd --system --comment 'Verdaccio NPM mirror' --create-home --home-dir /var/lib/verdaccio --shell /sbin/nologin verdaccio
```
You create a shell as the Verdaccio user using the following command:
```bash
$ sudo su -s /bin/bash verdaccio
$ cd
```
The `cd` command sends you to the home directory of the Verdaccio user. Make sure you run Verdaccio at least once to generate the config file. Edit it according to your needs.
## Listening on all addresses {#listening-on-all-addresses}
If you want to listen to every external address set the listen directive in the config to:
```yaml
# you can specify listen address (or simply a port)
listen: 0.0.0.0:4873
```
If you are running Verdaccio in a Amazon EC2 Instance, [you will need set the listen in change your config file](https://github.com/verdaccio/verdaccio/issues/314#issuecomment-327852203) as is described above.
> Configure Apache or nginx? Please check out the [Reverse Proxy Setup](reverse-proxy.md)
## Keeping Verdaccio running forever {#keeping-verdaccio-running-forever}
You can use a Node package called ['forever'](https://github.com/nodejitsu/forever) to keep Verdaccio running all the time.
First install `forever` globally:
```bash
$ sudo npm install -g forever
```
Make sure you've run Verdaccio at least once to generate the config file and write down the created admin user. You can then use the following command to start Verdaccio:
```bash
$ forever start `which verdaccio`
```
You can check the documentation for more information on how to use forever.
## Surviving server restarts {#surviving-server-restarts}
You can use `crontab` and `forever` together to start Verdaccio after a server reboot.
When you're logged in as the Verdaccio user do the following:
```bash
$ crontab -e
```
This might ask you to choose an editor. Pick your favorite and proceed.
Add the following entry to the file:
```
@reboot /usr/bin/forever start /usr/lib/node_modules/verdaccio/bin/verdaccio
```
The locations may vary depending on your server setup. If you want to know where your files are you can use the 'which' command:
```bash
$ which forever
$ which verdaccio
```
## Using systemd {#using-systemd}
Instead of `forever` you can use `systemd` for starting Verdaccio and keeping it running. Verdaccio installation has systemd unit, you only need to copy it:
```bash
$ sudo cp /usr/lib/node_modules/verdaccio/systemd/verdaccio.service /lib/systemd/system/ && sudo systemctl daemon-reload
```
This unit assumes you have configuration in `/etc/verdaccio/config.yaml` and store data in `/var/lib/verdaccio`, so either move your files to those locations or edit the unit.

View File

@@ -1,46 +0,0 @@
---
id: setup-bun
title: 'bun'
---
# bun {#bun}
- [Example repository](https://github.com/juanpicado/verdaccio-with-bun)
## Using registry for a specific project {#specific}
Create a `bunfig.toml` file at the root of the project and set
```toml
[install]
registry = "http://localhost:4873"
```
On run `bun install` command the installation will be done from the local registry.
To enable authenticated access to the registry, you can set the token in the `bunfig.toml` file.
```toml
[install.scopes]
# as an object with token
"@scope" = { token = "$npm_token", url = "https://localhost:4873/" }
```
Bun provides other ways to configure the registry, you can find more information in the official documentation.
- [Override the default npm registry for bun install](https://bun.sh/guides/install/custom-registry)
- [Configure a private registry for an organization scope with bun install](https://bun.sh/guides/install/registry-scope)
## Troubleshooting {#troubleshooting}
### Clear cache with `bun`
To remove the cache, seems that you need to remove the `bun.lock` file, this file is created when you run `bun install` and it's located in the root of the project.
> It may be a better way to do this, please share new solutions.
```bash
rm bun.lockb
```

View File

@@ -1,44 +0,0 @@
---
id: setup-deno
title: 'deno'
---
- [Example repository](https://github.com/juanpicado/verdaccio-with-deno)
# deno {#deno}
The minimum supported [deno](https://deno.com/blog/v1.44) version is >1.44.0
## Using registry for a specific project {#specific}
Create a `.npmrc` file and set
```bash
registry=http://localhost:4873
```
On run `deno` command the installation will be done from the local registry.
## Troubleshooting {#troubleshooting}
### Clear cache with `deno`
```bash
> deno info
DENO_DIR location: /Users/user/Library/Caches/deno
Remote modules cache: /Users/user/Library/Caches/deno/deps
npm modules cache: /Users/user/Library/Caches/deno/npm
Emitted modules cache: /Users/user/Library/Caches/deno/gen
Language server registries cache: /Users/user/Library/Caches/deno/registries
Origin storage: /Users/user/Library/Caches/deno/location_data
```
And remove the local cache for th specific registry you have set (by default is `localhost_4873`)
```bash
// for MAC OS users (other OS may vary)
rm -Rf /Users/user/Library/Caches/deno/npm/localhost_4873
```
> It's not clear if there is a better way to do this, please refer to the [following discussion](https://github.com/denoland/deno/discussions/9419) for more information.

View File

@@ -1,144 +0,0 @@
---
id: setup-npm
title: 'npm'
---
# npm {#npm}
The minimum supported NPM version is 5.
## Setting up global registry for all projects {#all}
To set the registry for all your local projects in any terminal window run:
```bash
npm set registry http://localhost:4873/
```
This will set the registry for your operational system user and you can find it on the file `~/.npmrc`.
## Using registry for a specific project {#specific}
To set this value for a specific project open its root folder on a terminal window and run:
```bash
npm set registry http://localhost:4873/ --location project
```
This will set the registry in a `.npmrc` file in your project root directory.
or by specific scope eg: `@my-scope/auth`:
```
npm config set @my-scope:registry http://localhost:4873
```
## Using registry only on specific command {#command}
If you want one single use append `--registry http://localhost:4873/` to the required command.
Some examples:
```bash
npm ci --registry http://localhost:4873
npm install --registry http://localhost:4873
npm install lodash --registry http://localhost:4873
```
## How to prevent your package from being published in other registries
If you only want to publish your package to Verdaccio but keep installing from other registries you can setup the `publishConfig` in your `package.json` as [described in the official documentation](https://docs.npmjs.com/cli/v8/using-npm/registry#how-can-i-prevent-my-package-from-being-published-in-the-official-registry).
```json
{
"publishConfig": {
"registry": "http://localhost:4873"
}
}
```
## Creating user {#creating-user}
With npm 8 or below, either `adduser` or `login` are able to create users and login at the same time.
```bash
npm adduser --registry http://localhost:4873
```
after version `npm@9` the commands works separately:
- `login` does not create users.
```bash
npm login --registry http://localhost:4873
```
- `adduser` does not login users.
```bash
npm adduser --registry http://localhost:4873
```
Both commands relies on web login by default, but adding `--auth-type=legacy` you can get back the previous behaviour.
> [Web login is not supported for verdaccio.](https://github.com/verdaccio/verdaccio/issues/3413)
## Troubleshooting {#troubleshooting}
### `npm login` with npm@9 or higher
If you are running into issues login with `npm@9.x` or higher you could try use the legacy mode (see above).
For progress on the native support on future you can track the following [issue#3413](https://github.com/verdaccio/verdaccio/issues/3413).
### npm does not save authToken when authenticating to Verdaccio
If you are using either `npm@5.4.x` or `npm@5.5.x`, there are [known issues with tokens](https://github.com/verdaccio/verdaccio/issues/509#issuecomment-359193762), please upgrade to either `6.x` or downgrade to `npm@5.3.0`.
### SSL and certificates {#ssl-and-certificates}
When using Verdaccio under SSL without a valid certificate, defining `strict-ssl` in your config file is required otherwise you will get `SSL Error: SELF_SIGNED_CERT_IN_CHAIN` errors.
`npm` does not support [invalid certificates anymore](https://blog.npmjs.org/post/78085451721/npms-self-signed-certificate-is-no-more) since 2014.
```bash
npm config set ca ""
npm config set strict-ssl false
```
### Mixed registries in lockefile (npm v7+)
Since version 7 npm got more strict with the introduction of `lockfileVersion: 2`. If you have mixed `resolved` fields in your lockfile, for instance, having this in your lockfile:
```json
{
"name": "npm7",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"lodash": "4.17.20",
"underscore": "^1.11.0"
}
},
..... // removed for simplicity
},
"dependencies": {
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
},
"underscore": {
"version": "1.11.0",
"resolved": "http://localhost:4873/underscore/-/underscore-1.11.0.tgz",
"integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw=="
}
}
}
```
Either running `npm i --registry https://registry.npmjs.org` or using `.npmrc` will fail your installation.

View File

@@ -1,15 +0,0 @@
---
id: setup-pnpm
title: 'pnpm'
---
### pnpm {#pnpm}
> This includes 6.x or higher series.
`pnpm` recognize by default the configuration at `.npmrc` and also the `--registry` value.
This means that you can follow the same commands described in [npm](setup-npm.md) replacing `npm` by `pnpm`.
## Troubleshooting
The most of problems might be resolved with the [npm troubleshooting list](setup-npm.md##troubleshooting) since are highly compatible in most of the commands.

View File

@@ -1,77 +0,0 @@
---
id: setup-yarn
title: 'yarn'
---
# yarn {#yarn}
#### `yarn` classic (1.x) {#yarn-classic-1x}
> Be aware `.npmrc` file configuration is recognized by yarn classic.
The classic version is able to regonise the `.npmrc` file, but also provides their own configuration file named `.yarnrc`.
To set up a registry, create a file and define a registry.
```
// .yarnrc
registry "http://localhost:4873"
```
`yarn@1.x` by default does not send the token on every request unless is being opt-in manually, this might causes `403 error` if you have protected the access of your packages.
To change this behaviour enable `always-auth` in your configuration :
```
always-auth=true
```
or running
```
npm config set always-auth true
```
#### `yarn` modern (>=2.x) {#yarn-modern-2x}
> Yarn modern does not recognize `--registry` or `.npmrc` file anymore.
For defining a registry you must use the `.yarnrc.yml` located in the root of your project or global configuration.
When you publish a package the `npmRegistryServer` must be used. Keep in mind the `publishConfig.registry` in the `package.json` will override this configuration.
```yaml
// .yarnrc.yml
npmRegistryServer: "http://localhost:4873"
unsafeHttpWhitelist:
- localhost
```
> `unsafeHttpWhitelist` is only need it if you don't use `https` with a valid certificate.
Using scopes is also possible and more segmented, you can define a token peer scope if is required.
```
npmRegistries:
"https://registry.myverdaccio.org":
npmAlwaysAuth: true
npmAuthToken: <TOKEN>
npmScopes:
my-company:
npmRegistryServer: https://registry.myverdaccio.org
npmPublishRegistry: https://registry.myverdaccio.org
```
for logging via CLi use:
```
yarn npm login --scope my-company
```
## Troubleshooting {#troubleshooting}
### Known issues
- `yarn npm login` issues, read [verdaccio#1737](https://github.com/verdaccio/verdaccio/issues/1737) or [yarn-berry#1848](https://github.com/yarnpkg/berry/pull/1848).
- `yarn npm publish` does not send README, read [verdaccio#1905](https://github.com/verdaccio/verdaccio/issues/1905) or [yarn-berry#1702](https://github.com/yarnpkg/berry/issues/1702).

View File

@@ -1,53 +0,0 @@
---
id: ssl
title: 'Set up the SSL Certificates'
---
Follow these instructions to configure an SSL certificate to serve an npm registry over HTTPS.
- Update the listen property in your `~/.config/verdaccio/config.yaml`:
```
listen: 'https://your.domain.com/'
```
Once you've updated the listen property and try to run verdaccio again, it will ask for certificates.
- Generate your certificates
```
$ openssl genrsa -out /Users/user/.config/verdaccio/verdaccio-key.pem 2048
$ openssl req -new -sha256 -key /Users/user/.config/verdaccio/verdaccio-key.pem -out /Users/user/.config/verdaccio/verdaccio-csr.pem
$ openssl x509 -req -in /Users/user/.config/verdaccio/verdaccio-csr.pem -signkey /Users/user/.config/verdaccio/verdaccio-key.pem -out /Users/user/.config/verdaccio/verdaccio-cert.pem
```
- Edit your config file `/Users/user/.config/verdaccio/config.yaml` and add the following section:
```
https:
key: /Users/user/.config/verdaccio/verdaccio-key.pem
cert: /Users/user/.config/verdaccio/verdaccio-cert.pem
ca: /Users/user/.config/verdaccio/verdaccio-csr.pem
```
Alternatively, if you have a certificate with the `server.pfx` format, you can add the following configuration section: (The passphrase is optional and only needed if your certificate is encrypted.)
```
https:
pfx: /Users/user/.config/verdaccio/server.pfx
passphrase: 'secret'
```
You can find more info on the `key`, `cert`, `ca`, `pfx`, and `passphrase` arguments in the [Node documentation](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options)
- Run `verdaccio` in your command line.
- Open the browser and visit `https://your.domain.com:port/`
These instructions are mostly valid under OSX and Linux; on Windows the paths will vary, but the steps are the same.
## Docker
If you are using the Docker image, you have to set the `VERDACCIO_PROTOCOL` environment variable to `https`, as the `listen` argument is provided in the [Dockerfile](https://github.com/verdaccio/verdaccio/blob/master/Dockerfile#L43) and thus ignored from your config file.
You can also set the `VERDACCIO_PORT` environment variable if you are using a port other than `4873`.

View File

@@ -1,88 +0,0 @@
---
id: uplinks
title: 'Uplinks'
---
An _uplink_ is a link with an external registry that provides access to external packages.
![Uplinks](https://user-images.githubusercontent.com/558752/52976233-fb0e3980-33c8-11e9-8eea-5415e6018144.png)
### Usage {#usage}
```yaml
uplinks:
npmjs:
url: https://registry.npmjs.org/
server2:
url: http://mirror.local.net/
timeout: 100ms
server3:
url: http://mirror2.local.net:9000/
baduplink:
url: http://localhost:55666/
```
### Configuration {#configuration}
You can define mutiple uplinks and each of them must have an unique name (key). They can have the following properties:
| Property | Type | Required | Example | Support | Description | Default |
| ------------- | ------- | -------- | --------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| url | string | Yes | https://registry.npmjs.org/ | all | The registry url | npmjs |
| ca | string | No | ~./ssl/client.crt' | all | SSL path certificate | No default |
| timeout | string | No | 100ms | all | set new timeout for the request | 30s |
| maxage | string | No | 10m | all | the time threshold to the cache is valid | 2m |
| fail_timeout | string | No | 10m | all | defines max time when a request becomes a failure | 5m |
| max_fails | number | No | 2 | all | limit maximun failure request | 2 |
| cache | boolean | No | [true,false] | >= 2.1 | cache all remote tarballs in storage | true |
| auth | list | No | [see below](uplinks.md#auth-property) | >= 2.5 | assigns the header 'Authorization' [more info](http://blog.npmjs.org/post/118393368555/deploying-with-npm-private-modules) | disabled |
| headers | list | No | authorization: "Bearer SecretJWToken==" | all | list of custom headers for the uplink | disabled |
| strict_ssl | boolean | No | [true,false] | >= 3.0 | If true, requires SSL certificates be valid. | true |
| agent_options | object | No | maxSockets: 10 | >= 4.0.2 | options for the HTTP or HTTPS Agent responsible for managing uplink connection persistence and reuse [more info](https://nodejs.org/api/http.html#http_class_http_agent) | No default |
#### Auth property {#auth-property}
The `auth` property allows you to use an auth token with an uplink. Using the default environment variable:
```yaml
uplinks:
private:
url: https://private-registry.domain.com/registry
auth:
type: bearer
token_env: true # by defaults points to the environment variable `NPM_TOKEN`
```
or via a specified _custom_ environment variable:
```yaml
uplinks:
private:
url: https://private-registry.domain.com/registry
auth:
type: bearer
token_env: FOO_TOKEN # override the default `NPM_TOKEN` by a custom one
```
`token_env: FOO_TOKEN `internally will use `process.env['FOO_TOKEN']`
or by directly specifying a token oh the configuration file (not recommended by security corcerns):
```yaml
uplinks:
private:
url: https://private-registry.domain.com/registry
auth:
type: bearer
token: 'token'
```
> Note: `token` has priority over `token_env`
### You Must know {#you-must-know}
- Uplinks must be registries compatible with the `npm` endpoints. Eg: _verdaccio_, `sinopia@1.4.0`, _npmjs registry_, _yarn registry_, _JFrog_, _Nexus_ and more.
- Setting `cache` to false will help to save space in your hard drive. This will avoid store `tarballs` but [it will keep metadata in folders](https://github.com/verdaccio/verdaccio/issues/391).
- Multiple uplinks might slow down the lookup of your packages. For each request an npm client makes, verdaccio makes 1 call to each configured uplink.
- The (timeout, maxage and fail_timeout) format follow the [NGINX measurement units](http://nginx.org/en/docs/syntax.html)
- When using the [Helm Chart](https://github.com/verdaccio/charts), you can use `secretEnvVars` to inject sensitive environment variables, which can be used to configure private uplink auth.

View File

@@ -1,96 +0,0 @@
---
id: webui
title: 'Web User Interface'
---
![Uplinks](https://user-images.githubusercontent.com/558752/52916111-fa4ba980-32db-11e9-8a64-f4e06eb920b3.png)
Verdaccio has a web user interface to display only the private packages and can be customised to your liking.
```yaml
web:
enable: true
title: Verdaccio
logo: http://somedomain/somelogo.png
primary_color: '#4b5e40'
gravatar: true | false
scope: '@scope'
sort_packages: asc | desc
darkMode: false
favicon: http://somedomain/favicon.ico | /path/favicon.ico
rateLimit:
windowMs: 50000
max: 1000
pkgManagers:
- npm
- yarn
- pnpm
login: true
scriptsBodyAfter:
- '<script type="text/javascript" src="https://my.company.com/customJS.min.js"></script>'
metaScripts:
- '<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>'
- '<script type="text/javascript" src="https://browser.sentry-cdn.com/5.15.5/bundle.min.js"></script>'
- '<meta name="robots" content="noindex" />'
scriptsbodyBefore:
- '<div id="myId">html before webpack scripts</div>'
html_cache: true
showInfo: true
showSettings: true
# In combination with darkMode you can force specific theme
showThemeSwitch: true
showFooter: true
showSearch: true
showDownloadTarball: true
showRaw: true
```
All access restrictions defined to [protect your packages](protect-your-dependencies.md) will also apply to the Web Interface.
> The `primary_color` and `scope` must be wrapped by quotes: eg: ('#000000' or "#000000")
The `primary_color` **must be a valid hex representation**.
### Internationalization {#internationalization}
_Since v4.5.0_, there are translations available.
```yaml
i18n:
web: en-US
```
> ⚠️ Only the enabled languages on this [file](https://github.com/verdaccio/verdaccio/blob/master/packages/plugins/ui-theme/src/i18n/enabledLanguages.ts) are available, you can contribute by adding new more languages. The default
> one is en-US
### Configuration {#configuration}
| Property | Type | Required | Example | Support | Description |
| ------------------- | ----------------- | -------- | ------------------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| enable | boolean | No | true/false | all | allow to display the web interface |
| title | string | No | Verdaccio | all | HTML head title description (if is not define set "Verdaccio" by default). |
| gravatar | boolean | No | true | `>v4` | Gravatars will be generated under the hood if this property is enabled |
| sort_packages | [asc,desc] | No | asc | `>v4` | By default private packages are sorted by ascending |
| logo | string | No | `/local/path/to/my/logo.png` `http://my.logo.domain/logo.png` | all | a URI where logo is located (header logo) |
| primary_color | string | No | "#4b5e40" | `>4` | The primary color to use throughout the UI (header, etc) |
| scope | string | No | @myscope | `>v3.x` | If you're using this registry for a specific module scope, specify that scope to set it in the webui instructions header |
| darkMode | boolean | No | false | `>=v4.6.0` | This mode is an special theme for those want to live in the dark side |
| favicon | string | No | false | `>=v5.0.1` | Display a custom favicon, can be local resource or valid url |
| rateLimit | object | No | use `userRateLimit` configuration | `>=v5.4.0` | Increase or decrease rate limit, by default is 5k request every 2 minutes, only limit web api endpoints, the CSS, JS, etcc are ingnored |
| pkgManagers | npm, pnpm or yarn | No | npm | `>=v5.5.0` | Allow customise which package managers on the side bar and registry information dialog are visible |
| login | boolean | No | true or false | `>=v5.5.0` | Allow disable login on the UI (also include web endpoints). |
| scriptsBodyAfter | string[] | No | any list of strings | `>=5.0.0` | inject scripts after the <body/> tag |
| metaScripts | string[] | No | any list of strings | `>=5.0.0` | inject scripts inside <head/> |
| scriptsbodyBefore | string[] | No | any list of strings | `>=5.0.0` | inject scripts before the <body/> |
| html_cache | boolean | No | true | `>=v5.9.0` | whether the html cache is enabled, default true |
| showInfo | boolean | No | true | `>=v5.10.0` | display the info button on the header |
| showSettings | boolean | No | true | `>=v5.10.0` | display the settings button on the header |
| showThemeSwitch | boolean | No | true | `>=v5.10.0` | display the theme switch button on the header |
| showFooter | boolean | No | true | `>=v5.10.0` | allow hide footer |
| showSearch | boolean | No | true | `>=v5.10.0` | allow hide search component |
| showDownloadTarball | boolean | No | true | `>=v5.10.0` | allow hide download button on the sidebar |
| showRaw | boolean | No | true | `>=v5.10.0` | allow hide manifest button on the sidebar (experimental feature) |
> The recommended logo size is `40x40` pixels.
> The `darkMode` can be enabled via UI and is persisted in the browser local storage. If you combine `showThemeSwitch: false` with `darkMode` users will be forced to use an specific theme. Furthermore, also void `primary_color` and dark cannot be customized.

View File

@@ -1,68 +0,0 @@
---
id: what-is-verdaccio
title: 'What is Verdaccio?'
---
Verdaccio is a **lightweight private npm proxy registry** built in **Node.js**
Using a private npm registry like Verdaccio is one of the [Top 10 NPM Security Best Practices](https://cheatsheetseries.owasp.org/cheatsheets/NPM_Security_Cheat_Sheet.html#6-use-a-local-npm-proxy)
recommended by the Open Web Application Security Project ([OWASP](https://owasp.org/)).
<iframe width="560" height="515" src="https://www.youtube.com/embed/qRMucS3i3kQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
## What's a registry? {#whats-a-registry}
- A registry is a repository for packages, that implements the **CommonJS Compliant Package Registry specification** for reading package's information.
- Provide a compatible API with npm clients **(yarn/npm/pnpm)**.
- Semantic Versioning compatible **(semver)**.
```bash
$> verdaccio
```
![registry](/img/verdaccio_server.gif)
## Using Verdaccio {#using-verdaccio}
Using Verdaccio with any Node.js package manager client is quite straightforward.
![registry](/img/npm_install.gif)
You can use a custom registry either by setting it globally for all your projects
```bash
npm set registry http://localhost:4873
```
or by using it in command line as an argument `--registry` in npm (slightly different in yarn)
```bash
npm install lodash --registry http://localhost:4873
```
```bash
yarn config set registry http://localhost:4873
```
To have a more detailed explanation, I invite you to watch the full explanation **Angular Library: How To Use a Library in a poly-repo Using Verdaccio** by [_Fanis Prodromou_](https://twitter.com/prodromouf) on his [YouTube channel](https://www.youtube.com/channel/UCgJAoZCYx1Dk3iGPHSIgV1A).
<iframe width="560" height="515" src="https://www.youtube.com/embed/tSIC3wna_d0?enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
## Private {#private}
All packages that you publish are private and only accessible based in your configuration.
## Proxy {#proxy}
Verdaccio cache all dependencies on demand and speed up installations in local or private networks.
## In a Nutshell {#in-a-nutshell}
- It's a web app based on Node.js
- It's a private npm registry
- It's a local network proxy
- It's a Pluggable application
- It's fairly easy to install and to use
- We offer Docker and Kubernetes support
- It is 100% compatible with yarn, npm and pnpm
- Verdaccio means **A green color popular in late medieval Italy for fresco painting**.

View File

@@ -1,32 +0,0 @@
---
id: who-is-using
title: 'Who is using Verdaccio?'
---
### As a Business {#as-a-business}
_If you are using Verdaccio in your business and want to share your experience, let us know. We will be happy to listen to you._
- [SheetJS](https://sheetjs.com/)
- [Satispay](https://www.satispay.com/)
### Open Source Projects {#open-source-projects}
> **Feel free to suggest other OSS are using Verdaccio.**
- [pnpm](https://pnpm.js.org/)
- [Storybook](https://storybook.js.org/)
- [Mozilla Neutrino](https://neutrinojs.org/)
- [create-react-app](https://github.com/facebook/create-react-app/blob/master/CONTRIBUTING.md#contributing-to-e2e-end-to-end-tests)
- [Gatsby](https://github.com/gatsbyjs/gatsby)
- [Apollo GraphQL](https://github.com/apollographql)
- [Uppy](https://github.com/transloadit/uppy)
- [Aurelia Framework](https://github.com/aurelia/framework)
- [bit](https://github.com/teambit/bit)
- [Wix Yoshi](https://github.com/wix/yoshi)
- [The AWS Cloud Development Kit](https://github.com/awslabs/aws-cdk)
- [Hyperledger Caliper](https://github.com/hyperledger/caliper)
#### Readme Recommendations {#readme-recommendations}
- [react-native-cli](https://github.com/react-native-community/react-native-cli/blob/master/CONTRIBUTING.md)

View File

@@ -1,55 +0,0 @@
---
id: windows
title: 'Installing As a Windows Service'
---
Loosely based upon the instructions found [here](http://asysadmin.tumblr.com/post/32941224574/running-nginx-on-windows-as-a-service). I crafted the following and it provided me with a fully working verdaccio service installation:
1. Create a directory for verdaccio
- mkdir `c:\verdaccio`
- cd `c:\verdaccio`
2. Install verdaccio locally (I ran into npm issues with global installs)
- npm install verdaccio
3. Create your `config.yaml` file in this location `(c:\verdaccio\config.yaml)`
4. Windows Service Setup
## Using NSSM {#using-nssm}
ALTERNATIVE METHOD: (WinSW package was missing when I tried to download it)
- Download [NSSM](https://www.nssm.cc/download/) and extract
- Add the path that contains nssm.exe to the PATH
- Open an administrative command
- Run nssm install verdaccio At a minimum you must fill in the Application tab Path,
Startup directory and Arguments fields. Assuming an install with node in the system path and a
location of c:\verdaccio the below values will work:
_ Path: `node`
_ Startup directory: `c:\verdaccio` \* Arguments: `c:\verdaccio\node_modules\verdaccio\build\lib\cli.js -c c:\verdaccio\config.yaml`
You can adjust other service settings under other tabs as desired. When you are done, click Install service button
- Start the service sc start verdaccio
## Using WinSW {#using-winsw}
- As of 2015-10-27, WinSW is no longer available at the below location. Please follow the Using NSSM instructions above.
- Download [WinSW](http://repo.jenkins-ci.org/releases/com/sun/winsw/winsw/)
- Place the executable (e.g. `winsw-1.9-bin.exe`) into this folder (`c:\verdaccio`) and rename it to `verdaccio-winsw.exe`
- Create a configuration file in `c:\verdaccio`, named `verdaccio-winsw.xml`
with the following configuration `xml verdaccio verdaccio verdaccio node c:\verdaccio\node_modules\verdaccio\src\lib\cli.js -c c:\verdaccio\config.yaml roll c:\verdaccio\ `.
- Install your service
- `cd c:\verdaccio`
- `verdaccio-winsw.exe install`
- Start your service
- `verdaccio-winsw.exe start`
Some of the above config is more verbose than I had expected, it appears as though 'workingdirectory'
is ignored, but other than that, this works for me and allows my verdaccio instance to
persist between restarts of the server, and also restart itself should there be any crashes of the verdaccio process.
## Repositories {#repositories}
- [verdaccio-deamon-windows](https://github.com/davidenke/verdaccio-deamon-windows)

View File

@@ -1 +0,0 @@
label: '@verdaccio/config'

View File

@@ -1,323 +0,0 @@
---
id: 'Config'
title: 'Class: Config'
sidebar_label: 'Config'
sidebar_position: 0
custom_edit_url: null
---
Coordinates the application configuration
## Implements
- `Config`
## Constructors
### constructor
**new Config**(`config`, `configOptions?`)
#### Parameters
| Name | Type | Default value |
| :------------------------------------------- | :----------------------------------------- | :------------ |
| `config` | `ConfigYaml` & { `config_path`: `string` } | `undefined` |
| `configOptions` | `Object` | `undefined` |
| `configOptions.forceEnhancedLegacySignature` | `boolean` | `true` |
#### Defined in
[config.ts:64](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L64)
## Properties
### auth
**auth**: `any`
#### Implementation of
AppConfig.auth
#### Defined in
[config.ts:47](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L47)
---
### configOptions
`Private` **configOptions**: `Object`
#### Type declaration
| Name | Type |
| :----------------------------- | :-------- |
| `forceEnhancedLegacySignature` | `boolean` |
#### Defined in
[config.ts:63](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L63)
---
### configPath
**configPath**: `string`
#### Implementation of
AppConfig.configPath
#### Defined in
[config.ts:49](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L49)
---
### flags
**flags**: `FlagsConfig`
#### Implementation of
AppConfig.flags
#### Defined in
[config.ts:61](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L61)
---
### packages
**packages**: `PackageList`
#### Implementation of
AppConfig.packages
#### Defined in
[config.ts:45](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L45)
---
### plugins
**plugins**: `null` \| `string` \| `void`
#### Implementation of
AppConfig.plugins
#### Defined in
[config.ts:56](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L56)
---
### secret
**secret**: `string`
#### Implementation of
AppConfig.secret
#### Defined in
[config.ts:60](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L60)
---
### security
**security**: `Security`
#### Implementation of
AppConfig.security
#### Defined in
[config.ts:57](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L57)
---
### self_path
**self_path**: `string`
**`Deprecated`**
use configPath or config.getConfigPath();
#### Implementation of
AppConfig.self_path
#### Defined in
[config.ts:53](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L53)
---
### serverSettings
**serverSettings**: `ServerSettingsConf`
#### Defined in
[config.ts:58](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L58)
---
### server_id
**server_id**: `string`
#### Implementation of
AppConfig.server_id
#### Defined in
[config.ts:48](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L48)
---
### storage
**storage**: `string` \| `void`
#### Implementation of
AppConfig.storage
#### Defined in
[config.ts:54](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L54)
---
### uplinks
**uplinks**: `any`
#### Implementation of
AppConfig.uplinks
#### Defined in
[config.ts:44](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L44)
---
### userRateLimit
**userRateLimit**: `RateLimit`
#### Implementation of
AppConfig.userRateLimit
#### Defined in
[config.ts:62](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L62)
---
### user_agent
**user_agent**: `undefined` \| `string`
#### Implementation of
AppConfig.user_agent
#### Defined in
[config.ts:43](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L43)
---
### users
**users**: `any`
#### Defined in
[config.ts:46](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L46)
## Methods
### checkSecretKey
**checkSecretKey**(`secret?`): `string`
Store or create whether receive a secret key
**`Secret`**
external secret key
#### Parameters
| Name | Type |
| :-------- | :------- |
| `secret?` | `string` |
#### Returns
`string`
#### Implementation of
AppConfig.checkSecretKey
#### Defined in
[config.ts:150](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L150)
---
### getConfigPath
**getConfigPath**(): `string`
#### Returns
`string`
#### Defined in
[config.ts:134](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L134)
---
### getMatchedPackagesSpec
**getMatchedPackagesSpec**(`pkgName`): `void` \| `PackageAccess`
Check for package spec
#### Parameters
| Name | Type |
| :-------- | :------- |
| `pkgName` | `string` |
#### Returns
`void` \| `PackageAccess`
#### Implementation of
AppConfig.getMatchedPackagesSpec
#### Defined in
[config.ts:141](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L141)

View File

@@ -1,206 +0,0 @@
---
id: 'ConfigBuilder'
title: 'Class: ConfigBuilder'
sidebar_label: 'ConfigBuilder'
sidebar_position: 0
custom_edit_url: null
---
Helper configuration builder constructor, used to build the configuration for testing or
programatically creating a configuration.
## Constructors
### constructor
**new ConfigBuilder**(`config?`)
#### Parameters
| Name | Type |
| :-------- | :----------------------- |
| `config?` | `Partial`<`ConfigYaml`\> |
#### Defined in
[builder.ts:21](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/builder.ts#L21)
## Properties
### config
`Private` **config**: `ConfigYaml`
#### Defined in
[builder.ts:19](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/builder.ts#L19)
## Methods
### addAuth
**addAuth**(`auth`): [`ConfigBuilder`](ConfigBuilder.md)
#### Parameters
| Name | Type |
| :----- | :---------------- |
| `auth` | `Partial`<`any`\> |
#### Returns
[`ConfigBuilder`](ConfigBuilder.md)
#### Defined in
[builder.ts:46](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/builder.ts#L46)
---
### addLogger
**addLogger**(`log`): [`ConfigBuilder`](ConfigBuilder.md)
#### Parameters
| Name | Type |
| :---- | :--------------- |
| `log` | `LoggerConfItem` |
#### Returns
[`ConfigBuilder`](ConfigBuilder.md)
#### Defined in
[builder.ts:51](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/builder.ts#L51)
---
### addPackageAccess
**addPackageAccess**(`pattern`, `pkgAccess`): [`ConfigBuilder`](ConfigBuilder.md)
#### Parameters
| Name | Type |
| :---------- | :------------------ |
| `pattern` | `string` |
| `pkgAccess` | `PackageAccessYaml` |
#### Returns
[`ConfigBuilder`](ConfigBuilder.md)
#### Defined in
[builder.ts:30](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/builder.ts#L30)
---
### addSecurity
**addSecurity**(`security`): [`ConfigBuilder`](ConfigBuilder.md)
#### Parameters
| Name | Type |
| :--------- | :--------------------- |
| `security` | `Partial`<`Security`\> |
#### Returns
[`ConfigBuilder`](ConfigBuilder.md)
#### Defined in
[builder.ts:41](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/builder.ts#L41)
---
### addStorage
**addStorage**(`storage`): [`ConfigBuilder`](ConfigBuilder.md)
#### Parameters
| Name | Type |
| :-------- | :------------------- |
| `storage` | `string` \| `object` |
#### Returns
[`ConfigBuilder`](ConfigBuilder.md)
#### Defined in
[builder.ts:56](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/builder.ts#L56)
---
### addUplink
**addUplink**(`id`, `uplink`): [`ConfigBuilder`](ConfigBuilder.md)
#### Parameters
| Name | Type |
| :------- | :----------- |
| `id` | `string` |
| `uplink` | `UpLinkConf` |
#### Returns
[`ConfigBuilder`](ConfigBuilder.md)
#### Defined in
[builder.ts:36](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/builder.ts#L36)
---
### getAsYaml
**getAsYaml**(): `string`
#### Returns
`string`
#### Defined in
[builder.ts:69](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/builder.ts#L69)
---
### getConfig
**getConfig**(): `ConfigYaml`
#### Returns
`ConfigYaml`
#### Defined in
[builder.ts:65](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/builder.ts#L65)
---
### build
`Static` **build**(`config?`): [`ConfigBuilder`](ConfigBuilder.md)
#### Parameters
| Name | Type |
| :-------- | :----------------------- |
| `config?` | `Partial`<`ConfigYaml`\> |
#### Returns
[`ConfigBuilder`](ConfigBuilder.md)
#### Defined in
[builder.ts:26](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/builder.ts#L26)

View File

@@ -1,2 +0,0 @@
label: 'Classes'
position: 3

View File

@@ -1,16 +0,0 @@
---
id: 'index'
title: '@verdaccio/config'
sidebar_label: 'Readme'
sidebar_position: 0
custom_edit_url: null
---
# @verdaccio/config
### License
Verdaccio is [MIT licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)
The Verdaccio documentation and logos (excluding /thanks, e.g., .md, .png, .sketch) files within the /assets folder) is
[Creative Commons licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE-docs).

View File

@@ -1,11 +0,0 @@
---
id: 'LegacyPackageList'
title: 'Interface: LegacyPackageList'
sidebar_label: 'LegacyPackageList'
sidebar_position: 0
custom_edit_url: null
---
## Indexable
▪ [key: `string`]: `PackageAccess`

View File

@@ -1,2 +0,0 @@
label: 'Interfaces'
position: 4

View File

@@ -1,476 +0,0 @@
---
id: 'modules'
title: '@verdaccio/config'
sidebar_label: 'Exports'
sidebar_position: 0.5
custom_edit_url: null
---
## Classes
- [Config](classes/Config.md)
- [ConfigBuilder](classes/ConfigBuilder.md)
## Interfaces
- [LegacyPackageList](interfaces/LegacyPackageList.md)
## Type Aliases
### SetupDirectory
Ƭ **SetupDirectory**: `Object`
#### Type declaration
| Name | Type |
| :----- | :------- |
| `path` | `string` |
| `type` | `string` |
#### Defined in
[config-path.ts:19](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config-path.ts#L19)
## Variables
### DEFAULT_REGISTRY
`Const` **DEFAULT_REGISTRY**: `"https://registry.npmjs.org"`
#### Defined in
[uplinks.ts:7](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/uplinks.ts#L7)
---
### DEFAULT_UPLINK
`Const` **DEFAULT_UPLINK**: `"npmjs"`
#### Defined in
[uplinks.ts:8](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/uplinks.ts#L8)
---
### PACKAGE_ACCESS
`Const` **PACKAGE_ACCESS**: `Object`
#### Type declaration
| Name | Type |
| :------ | :------- |
| `ALL` | `string` |
| `SCOPE` | `string` |
#### Defined in
[package-access.ts:23](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/package-access.ts#L23)
---
### ROLES
`Const` **ROLES**: `Object`
#### Type declaration
| Name | Type |
| :--------------------- | :------- |
| `$ALL` | `string` |
| `$ANONYMOUS` | `string` |
| `$AUTH` | `string` |
| `ALL` | `string` |
| `DEPRECATED_ALL` | `string` |
| `DEPRECATED_ANONYMOUS` | `string` |
| `DEPRECATED_AUTH` | `string` |
#### Defined in
[package-access.ts:12](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/package-access.ts#L12)
---
### TIME_EXPIRATION_1H
`Const` **TIME_EXPIRATION_1H**: `"1h"`
#### Defined in
[security.ts:4](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/security.ts#L4)
---
### TOKEN_VALID_LENGTH
`Const` **TOKEN_VALID_LENGTH**: `32`
#### Defined in
[token.ts:3](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/token.ts#L3)
---
### WEB_TITLE
`Const` **WEB_TITLE**: `"Verdaccio"`
#### Defined in
[config.ts:31](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L31)
---
### defaultLoggedUserRoles
`Const` **defaultLoggedUserRoles**: `string`[]
All logged users will have by default the group $all and $authenticate
#### Defined in
[user.ts:8](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/user.ts#L8)
---
### defaultNonLoggedUserRoles
`Const` **defaultNonLoggedUserRoles**: `string`[]
#### Defined in
[user.ts:18](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/user.ts#L18)
---
### defaultSecurity
`Const` **defaultSecurity**: `Security`
#### Defined in
[security.ts:18](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/security.ts#L18)
---
### defaultUserRateLimiting
`Const` **defaultUserRateLimiting**: `Object`
#### Type declaration
| Name | Type |
| :--------- | :------- |
| `max` | `number` |
| `windowMs` | `number` |
#### Defined in
[config.ts:34](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config.ts#L34)
## Functions
### createAnonymousRemoteUser
**createAnonymousRemoteUser**(): `RemoteUser`
Builds an anonymous remote user in case none is logged in.
#### Returns
`RemoteUser`
{ name: xx, groups: [], real_groups: [] }
#### Defined in
[user.ts:47](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/user.ts#L47)
---
### createRemoteUser
**createRemoteUser**(`name`, `pluginGroups`): `RemoteUser`
Create a RemoteUser object
#### Parameters
| Name | Type |
| :------------- | :--------- |
| `name` | `string` |
| `pluginGroups` | `string`[] |
#### Returns
`RemoteUser`
{ name: xx, pluginGroups: [], real_groups: [] }
#### Defined in
[user.ts:30](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/user.ts#L30)
---
### findConfigFile
**findConfigFile**(`configPath?`): `string`
Find and get the first config file that match.
#### Parameters
| Name | Type |
| :------------ | :------- |
| `configPath?` | `string` |
#### Returns
`string`
the config file path
#### Defined in
[config-path.ts:30](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config-path.ts#L30)
---
### fromJStoYAML
**fromJStoYAML**(`config`): `string` \| `null`
#### Parameters
| Name | Type |
| :------- | :----------------------- |
| `config` | `Partial`<`ConfigYaml`\> |
#### Returns
`string` \| `null`
#### Defined in
[parse.ts:56](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/parse.ts#L56)
---
### generateRandomSecretKey
**generateRandomSecretKey**(): `string`
Secret key must have 32 characters.
#### Returns
`string`
#### Defined in
[token.ts:8](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/token.ts#L8)
---
### getDefaultConfig
**getDefaultConfig**(`fileName?`): `ConfigYaml` & { `configPath`: `string` ; `config_path`: `string` }
#### Parameters
| Name | Type | Default value |
| :--------- | :------- | :--------------- |
| `fileName` | `string` | `'default.yaml'` |
#### Returns
`ConfigYaml` & { `configPath`: `string` ; `config_path`: `string` }
#### Defined in
[conf/index.ts:5](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/conf/index.ts#L5)
---
### getUserAgent
**getUserAgent**(`customUserAgent?`, `version?`, `name?`): `string`
#### Parameters
| Name | Type |
| :----------------- | :-------------------- |
| `customUserAgent?` | `string` \| `boolean` |
| `version?` | `string` |
| `name?` | `string` |
#### Returns
`string`
#### Defined in
[agent.ts:3](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/agent.ts#L3)
---
### hasProxyTo
**hasProxyTo**(`pkg`, `upLink`, `packages`): `boolean`
#### Parameters
| Name | Type |
| :--------- | :------------ |
| `pkg` | `string` |
| `upLink` | `string` |
| `packages` | `PackageList` |
#### Returns
`boolean`
#### Defined in
[uplinks.ts:51](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/uplinks.ts#L51)
---
### normalisePackageAccess
**normalisePackageAccess**(`packages`): [`LegacyPackageList`](interfaces/LegacyPackageList.md)
#### Parameters
| Name | Type |
| :--------- | :----------------------------------------------------- |
| `packages` | [`LegacyPackageList`](interfaces/LegacyPackageList.md) |
#### Returns
[`LegacyPackageList`](interfaces/LegacyPackageList.md)
#### Defined in
[package-access.ts:50](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/package-access.ts#L50)
---
### normalizeUserList
**normalizeUserList**(`groupsList`): `any`
#### Parameters
| Name | Type |
| :----------- | :---- |
| `groupsList` | `any` |
#### Returns
`any`
#### Defined in
[package-access.ts:28](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/package-access.ts#L28)
---
### parseConfigFile
**parseConfigFile**(`configPath`): `ConfigYaml` & { `configPath`: `string` ; `config_path`: `string` }
Parse a config file from yaml to JSON.
#### Parameters
| Name | Type | Description |
| :----------- | :------- | :------------------------------------------ |
| `configPath` | `string` | the absolute path of the configuration file |
#### Returns
`ConfigYaml` & { `configPath`: `string` ; `config_path`: `string` }
#### Defined in
[parse.ts:17](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/parse.ts#L17)
---
### readDefaultConfig
**readDefaultConfig**(): `Buffer`
#### Returns
`Buffer`
#### Defined in
[config-path.ts:66](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/config-path.ts#L66)
---
### sanityCheckNames
**sanityCheckNames**(`item`, `users`): `any`
#### Parameters
| Name | Type |
| :------ | :------- |
| `item` | `string` |
| `users` | `any` |
#### Returns
`any`
#### Defined in
[uplinks.ts:61](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/uplinks.ts#L61)
---
### sanityCheckUplinksProps
**sanityCheckUplinksProps**(`configUpLinks`): `UpLinksConfList`
#### Parameters
| Name | Type |
| :-------------- | :---------------- |
| `configUpLinks` | `UpLinksConfList` |
#### Returns
`UpLinksConfList`
#### Defined in
[uplinks.ts:37](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/uplinks.ts#L37)
---
### uplinkSanityCheck
**uplinkSanityCheck**(`uplinks`, `users?`): `UpLinksConfList`
#### Parameters
| Name | Type | Default value |
| :-------- | :---------------- | :------------ |
| `uplinks` | `UpLinksConfList` | `undefined` |
| `users` | `any` | `BLACKLIST` |
#### Returns
`UpLinksConfList`
#### Defined in
[uplinks.ts:18](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/config/src/uplinks.ts#L18)

View File

@@ -1 +0,0 @@
label: '@verdaccio/core'

View File

@@ -1,2 +0,0 @@
label: 'Classes'
position: 3

View File

@@ -1,106 +0,0 @@
---
id: 'pluginUtils.Plugin'
title: 'Class: Plugin<PluginConfig>'
sidebar_label: 'pluginUtils.Plugin'
custom_edit_url: null
---
[pluginUtils](../namespaces/pluginUtils.md).Plugin
The base plugin class, set of utilities for developing
plugins.
## Type parameters
| Name |
| :------------- |
| `PluginConfig` |
## Hierarchy
- **`Plugin`**
↳ [`Storage`](../interfaces/pluginUtils.Storage.md)
↳ [`ExpressMiddleware`](../interfaces/pluginUtils.ExpressMiddleware.md)
↳ [`Auth`](../interfaces/pluginUtils.Auth.md)
↳ [`ManifestFilter`](../interfaces/pluginUtils.ManifestFilter.md)
## Constructors
### constructor
**new Plugin**<`PluginConfig`\>(`config`, `options`)
#### Type parameters
| Name |
| :------------- |
| `PluginConfig` |
#### Parameters
| Name | Type |
| :-------- | :------------------------------------------------------------ |
| `config` | `PluginConfig` |
| `options` | [`PluginOptions`](../interfaces/pluginUtils.PluginOptions.md) |
#### Defined in
[plugin-utils.ts:38](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L38)
## Properties
### config
`Readonly` **config**: `unknown`
#### Defined in
[plugin-utils.ts:36](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L36)
---
### options
`Readonly` **options**: [`PluginOptions`](../interfaces/pluginUtils.PluginOptions.md)
#### Defined in
[plugin-utils.ts:37](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L37)
---
### version
`Readonly` **version**: `number`
#### Defined in
[plugin-utils.ts:35](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L35)
---
### version
`Static` **version**: `number` = `1`
#### Defined in
[plugin-utils.ts:34](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L34)
## Methods
### getVersion
**getVersion**(): `number`
#### Returns
`number`
#### Defined in
[plugin-utils.ts:44](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L44)

View File

@@ -1,47 +0,0 @@
---
id: 'HtpasswdHashAlgorithm'
title: 'Enumeration: HtpasswdHashAlgorithm'
sidebar_label: 'HtpasswdHashAlgorithm'
sidebar_position: 0
custom_edit_url: null
---
## Enumeration Members
### bcrypt
**bcrypt** = `"bcrypt"`
#### Defined in
[constants.ts:119](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/constants.ts#L119)
---
### crypt
**crypt** = `"crypt"`
#### Defined in
[constants.ts:118](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/constants.ts#L118)
---
### md5
**md5** = `"md5"`
#### Defined in
[constants.ts:116](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/constants.ts#L116)
---
### sha1
**sha1** = `"sha1"`
#### Defined in
[constants.ts:117](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/constants.ts#L117)

View File

@@ -1,2 +0,0 @@
label: 'Enumerations'
position: 2

View File

@@ -1,68 +0,0 @@
---
id: 'warningUtils.Codes'
title: 'Enumeration: Codes'
sidebar_label: 'warningUtils.Codes'
custom_edit_url: null
---
[warningUtils](../namespaces/warningUtils.md).Codes
## Enumeration Members
### VERDEP003
**VERDEP003** = `"VERDEP003"`
#### Defined in
[warning-utils.ts:14](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/warning-utils.ts#L14)
---
### VERWAR001
**VERWAR001** = `"VERWAR001"`
#### Defined in
[warning-utils.ts:8](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/warning-utils.ts#L8)
---
### VERWAR002
**VERWAR002** = `"VERWAR002"`
#### Defined in
[warning-utils.ts:9](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/warning-utils.ts#L9)
---
### VERWAR003
**VERWAR003** = `"VERWAR003"`
#### Defined in
[warning-utils.ts:10](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/warning-utils.ts#L10)
---
### VERWAR004
**VERWAR004** = `"VERWAR004"`
#### Defined in
[warning-utils.ts:11](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/warning-utils.ts#L11)
---
### VERWAR005
**VERWAR005** = `"VERWAR005"`
#### Defined in
[warning-utils.ts:12](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/warning-utils.ts#L12)

View File

@@ -1,27 +0,0 @@
---
id: 'index'
title: '@verdaccio/core'
sidebar_label: 'Readme'
sidebar_position: 0
custom_edit_url: null
---
# Core
[![CircleCI](https://circleci.com/gh/verdaccio/streams.svg?style=svg)](https://circleci.com/gh/ayusharma/@verdaccio/streams)
[![codecov](https://codecov.io/gh/verdaccio/streams/branch/master/graph/badge.svg)](https://codecov.io/gh/verdaccio/streams)
[![verdaccio (latest)](https://img.shields.io/npm/v/@verdaccio/streams/latest.svg)](https://www.npmjs.com/package/@verdaccio/streams)
[![backers](https://opencollective.com/verdaccio/tiers/backer/badge.svg?label=Backer&color=brightgreen)](https://opencollective.com/verdaccio)
[![discord](https://img.shields.io/discord/388674437219745793.svg)](http://chat.verdaccio.org/)
![MIT](https://img.shields.io/github/license/mashape/apistatus.svg)
[![node](https://img.shields.io/node/v/@verdaccio/streams/latest.svg)](https://www.npmjs.com/package/@verdaccio/streams)
This project provides an extension of `PassThrough` stream.
## Detail
It provides 2 additional methods `abort()` and `done()`. Those implementations are widely use in the verdaccio core for handle `tarballs`.
## License
MIT (http://www.opensource.org/licenses/mit-license.php)

View File

@@ -1,2 +0,0 @@
label: 'Interfaces'
position: 4

View File

@@ -1,316 +0,0 @@
---
id: 'pluginUtils.Auth'
title: 'Interface: Auth<T>'
sidebar_label: 'pluginUtils.Auth'
custom_edit_url: null
---
[pluginUtils](../namespaces/pluginUtils.md).Auth
The base plugin class, set of utilities for developing
plugins.
## Type parameters
| Name |
| :--- |
| `T` |
## Hierarchy
- [`Plugin`](../classes/pluginUtils.Plugin.md)<`T`\>
**`Auth`**
## Properties
### config
`Readonly` **config**: `unknown`
#### Inherited from
[Plugin](../classes/pluginUtils.Plugin.md).[config](../classes/pluginUtils.Plugin.md#config)
#### Defined in
[plugin-utils.ts:36](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L36)
---
### options
`Readonly` **options**: [`PluginOptions`](pluginUtils.PluginOptions.md)
#### Inherited from
[Plugin](../classes/pluginUtils.Plugin.md).[options](../classes/pluginUtils.Plugin.md#options)
#### Defined in
[plugin-utils.ts:37](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L37)
---
### version
`Readonly` **version**: `number`
#### Inherited from
[Plugin](../classes/pluginUtils.Plugin.md).[version](../classes/pluginUtils.Plugin.md#version)
#### Defined in
[plugin-utils.ts:35](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L35)
## Methods
### adduser
`Optional` **adduser**(`user`, `password`, `cb`): `void`
Handles the authenticated method.
```ts
class Auth {
public adduser(user: string, password: string, done: AuthCallback): void {
if (!password) {
return done(errorUtils.getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD));
}
// return boolean
return done(null, true);
}
```
#### Parameters
| Name | Type |
| :--------- | :------------------------------------------------------------------ |
| `user` | `string` |
| `password` | `string` |
| `cb` | [`AuthUserCallback`](../namespaces/pluginUtils.md#authusercallback) |
#### Returns
`void`
#### Defined in
[plugin-utils.ts:144](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L144)
---
### allow_access
`Optional` **allow_access**(`user`, `pkg`, `cb`): `void`
#### Parameters
| Name | Type |
| :----- | :-------------------------------------------------------------- |
| `user` | `RemoteUser` |
| `pkg` | `T` & `PackageAccess` |
| `cb` | [`AccessCallback`](../namespaces/pluginUtils.md#accesscallback) |
#### Returns
`void`
#### Defined in
[plugin-utils.ts:153](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L153)
`Optional` **allow_access**(`user`, `pkg`, `cb`): `void`
#### Parameters
| Name | Type |
| :----- | :-------------------------------------------------------------- |
| `user` | `RemoteUser` |
| `pkg` | `AllowAccess` & `PackageAccess` |
| `cb` | [`AccessCallback`](../namespaces/pluginUtils.md#accesscallback) |
#### Returns
`void`
#### Defined in
[plugin-utils.ts:154](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L154)
---
### allow_publish
`Optional` **allow_publish**(`user`, `pkg`, `cb`): `void`
#### Parameters
| Name | Type |
| :----- | :---------------------------------------------------------------------- |
| `user` | `RemoteUser` |
| `pkg` | `T` & `PackageAccess` |
| `cb` | [`AuthAccessCallback`](../namespaces/pluginUtils.md#authaccesscallback) |
#### Returns
`void`
#### Defined in
[plugin-utils.ts:151](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L151)
`Optional` **allow_publish**(`user`, `pkg`, `cb`): `void`
#### Parameters
| Name | Type |
| :----- | :---------------------------------------------------------------------- |
| `user` | `RemoteUser` |
| `pkg` | `AllowAccess` & `PackageAccess` |
| `cb` | [`AuthAccessCallback`](../namespaces/pluginUtils.md#authaccesscallback) |
#### Returns
`void`
#### Defined in
[plugin-utils.ts:152](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L152)
---
### allow_unpublish
`Optional` **allow_unpublish**(`user`, `pkg`, `cb`): `void`
#### Parameters
| Name | Type |
| :----- | :---------------------------------------------------------------------- |
| `user` | `RemoteUser` |
| `pkg` | `T` & `PackageAccess` |
| `cb` | [`AuthAccessCallback`](../namespaces/pluginUtils.md#authaccesscallback) |
#### Returns
`void`
#### Defined in
[plugin-utils.ts:155](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L155)
`Optional` **allow_unpublish**(`user`, `pkg`, `cb`): `void`
#### Parameters
| Name | Type |
| :----- | :---------------------------------------------------------------------- |
| `user` | `RemoteUser` |
| `pkg` | `AllowAccess` & `PackageAccess` |
| `cb` | [`AuthAccessCallback`](../namespaces/pluginUtils.md#authaccesscallback) |
#### Returns
`void`
#### Defined in
[plugin-utils.ts:156](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L156)
---
### apiJWTmiddleware
`Optional` **apiJWTmiddleware**(`helpers`): `RequestHandler`<`ParamsDictionary`, `any`, `any`, `ParsedQs`, `Record`<`string`, `any`\>\>
#### Parameters
| Name | Type |
| :-------- | :---- |
| `helpers` | `any` |
#### Returns
`RequestHandler`<`ParamsDictionary`, `any`, `any`, `ParsedQs`, `Record`<`string`, `any`\>\>
#### Defined in
[plugin-utils.ts:161](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L161)
---
### authenticate
**authenticate**(`user`, `password`, `cb`): `void`
Handles the authenticated method.
```ts
class Auth {
public authenticate(user: string, password: string, done: AuthCallback): void {
if (!password) {
return done(errorUtils.getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD));
}
// always return an array of users
return done(null, [user]);
}
```
#### Parameters
| Name | Type |
| :--------- | :---------------------------------------------------------- |
| `user` | `string` |
| `password` | `string` |
| `cb` | [`AuthCallback`](../namespaces/pluginUtils.md#authcallback) |
#### Returns
`void`
#### Defined in
[plugin-utils.ts:130](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L130)
---
### changePassword
`Optional` **changePassword**(`user`, `password`, `newPassword`, `cb`): `void`
#### Parameters
| Name | Type |
| :------------ | :-------------------------------------------------------------------------------------- |
| `user` | `string` |
| `password` | `string` |
| `newPassword` | `string` |
| `cb` | [`AuthChangePasswordCallback`](../namespaces/pluginUtils.md#authchangepasswordcallback) |
#### Returns
`void`
#### Defined in
[plugin-utils.ts:145](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L145)
---
### getVersion
**getVersion**(): `number`
#### Returns
`number`
#### Inherited from
[Plugin](../classes/pluginUtils.Plugin.md).[getVersion](../classes/pluginUtils.Plugin.md#getversion)
#### Defined in
[plugin-utils.ts:44](https://github.com/verdaccio/verdaccio/blob/10057a4ff/packages/core/core/src/plugin-utils.ts#L44)

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