1
0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-12-20 17:05:52 +01:00

chore(website): add api section (#3424)

* chore: add api section

* chore: fix build

* Update website.yml

* chore: improve types plugin

clean up others stuff

* Update crowdin.yaml

* clean up
This commit is contained in:
Juan Picado 2022-10-10 08:00:09 +02:00 committed by GitHub
parent bf36b9477c
commit 64cfedb805
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
85 changed files with 661 additions and 970 deletions

@ -3,7 +3,6 @@
'@verdaccio/auth': major
'@verdaccio/cli': major
'@verdaccio/config': major
'@verdaccio/commons-api': major
'@verdaccio/core': major
'@verdaccio/local-storage': major
'@verdaccio/server-fastify': major

@ -3,7 +3,6 @@
'@verdaccio/auth': major
'@verdaccio/cli': major
'@verdaccio/config': major
'@verdaccio/commons-api': major
'@verdaccio/file-locking': major
'verdaccio-htpasswd': major
'@verdaccio/local-storage': major

@ -3,7 +3,6 @@
'@verdaccio/auth': major
'@verdaccio/cli': major
'@verdaccio/config': major
'@verdaccio/commons-api': major
'@verdaccio/file-locking': major
'verdaccio-htpasswd': major
'@verdaccio/local-storage': major

@ -6,7 +6,6 @@
'@verdaccio/auth': patch
'@verdaccio/cli': patch
'@verdaccio/config': patch
'@verdaccio/commons-api': patch
'@verdaccio/file-locking': patch
'verdaccio-htpasswd': patch
'@verdaccio/readme': patch

@ -3,7 +3,6 @@
'@verdaccio/auth': minor
'@verdaccio/cli': minor
'@verdaccio/config': minor
'@verdaccio/commons-api': minor
'@verdaccio/file-locking': minor
'verdaccio-htpasswd': minor
'@verdaccio/local-storage': minor

@ -3,7 +3,6 @@
'@verdaccio/auth': minor
'@verdaccio/cli': minor
'@verdaccio/config': minor
'@verdaccio/commons-api': minor
'@verdaccio/file-locking': minor
'verdaccio-htpasswd': minor
'@verdaccio/local-storage': minor

@ -3,7 +3,6 @@
'@verdaccio/auth': patch
'@verdaccio/cli': patch
'@verdaccio/config': patch
'@verdaccio/commons-api': patch
'@verdaccio/file-locking': patch
'verdaccio-htpasswd': patch
'@verdaccio/local-storage': patch

@ -3,7 +3,6 @@
'@verdaccio/auth': patch
'@verdaccio/cli': patch
'@verdaccio/config': patch
'@verdaccio/commons-api': patch
'@verdaccio/file-locking': patch
'verdaccio-htpasswd': patch
'@verdaccio/local-storage': patch

@ -37,8 +37,8 @@ jobs:
run_install: |
- recursive: true
args: [--frozen-lockfile]
- name: Build Plugins
run: pnpm build --filter "docusaurus-plugin-contributors"
- name: Build
run: pnpm build
- name: Build Translations percentage
run: pnpm build --filter "@verdaccio/crowdin-translations"
- name: Cache Docusaurus Build

6
.gitignore vendored

@ -49,5 +49,7 @@ api-results*.json
.clinic/
#docs
./api
**/docs/**
website/docs/api/**/*.md
website/docs/api/**/*.yml
!website/docs/api/index.md
packages/core/types/docs

@ -8,13 +8,12 @@ preserve_hierarchy: true
files:
- source: /packages/plugins/ui-theme/src/i18n/crowdin/*.json
translation: '/packages/plugins/ui-theme/src/i18n/download_translations/%locale%/%original_file_name%'
# languages_mapping: *languages_mapping
- source: /website/i18n/en/**/*
translation: '/website/i18n/%locale%/**/%original_file_name%'
- source: /website/docs/**/*
translation: '/website/i18n/%locale%/docusaurus-plugin-content-docs/current/**/%original_file_name%'
# languages_mapping: *languages_mapping
ignore: [/website/docs/api/**/*]
- source: /website/versioned_docs/**/*
translation: /website/i18n/%locale%/docusaurus-plugin-content-docs/**/%original_file_name%
# languages_mapping: *languages_mapping
ignore: [/website/versioned_docs/version-5.x/api/**/*]

3
docs/plugins.md Normal file

@ -0,0 +1,3 @@
## Developing plugins
TBA

@ -10,7 +10,7 @@ module.exports = {
coveragePathIgnorePatterns: ['node_modules', 'fixtures'],
coverageThreshold: {
global: {
lines: 90,
lines: 85,
},
},
};

@ -111,7 +111,7 @@
"scripts": {
"prepare": "husky install",
"husky:pre-commit": "lint-staged",
"clean": "pnpm run clean",
"clean": "pnpm run clean --filter=./packages",
"build": "pnpm run build --filter=./packages && pnpm run build --filter=./e2e",
"docker": "docker build -t verdaccio/verdaccio:local . --no-cache",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md}\"",
@ -151,6 +151,12 @@
"local:publish": "cross-env npm_config_registry=http://localhost:4873 pnpm ci:publish",
"local:publish:release": "concurrently \"pnpm local:registry\" \"pnpm local:publish\""
},
"pnpm": {
"overrides": {
"got": "11.8.5",
"p-cancelable": "2.1.1"
}
},
"engines": {
"node": ">=16.5",
"pnpm": ">=6.32.3 <7.0.0"

@ -11,18 +11,16 @@ import {
TOKEN_BEARER,
VerdaccioError,
errorUtils,
pluginUtils,
} from '@verdaccio/core';
import { asyncLoadPlugin } from '@verdaccio/loaders';
import {
AllowAccess,
AuthPluginPackage,
Callback,
Config,
IPluginAuth,
JWTSignOptions,
Logger,
PackageAccess,
PluginOptions,
RemoteUser,
Security,
} from '@verdaccio/types';
@ -46,15 +44,6 @@ const LoggerApi = require('@verdaccio/logger');
const debug = buildDebug('verdaccio:auth');
export interface IBasicAuth<T> {
config: T & Config;
authenticate(user: string, password: string, cb: Callback): void;
invalidateToken?(token: string): Promise<void>;
changePassword(user: string, password: string, newPassword: string, cb: Callback): void;
allow_access(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void;
add_user(user: string, password: string, cb: Callback): any;
}
export interface TokenEncryption {
jwtEncrypt(user: RemoteUser, signOptions: JWTSignOptions): Promise<string>;
aesEncrypt(buf: string): string | void;
@ -74,13 +63,13 @@ export interface IAuthMiddleware {
webUIJWTmiddleware(): $NextFunctionVer;
}
export interface IAuth extends IBasicAuth<Config>, IAuthMiddleware, TokenEncryption {
export interface IAuth extends IAuthMiddleware, TokenEncryption, pluginUtils.IBasicAuth {
config: Config;
logger: Logger;
secret: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
plugins: any[];
allow_unpublish(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void;
allow_unpublish(pkg: pluginUtils.AuthPluginPackage, user: RemoteUser, callback: Callback): void;
invalidateToken(token: string): Promise<void>;
init(): Promise<void>;
}
@ -89,7 +78,7 @@ class Auth implements IAuth {
public config: Config;
public logger: Logger;
public secret: string;
public plugins: IPluginAuth<Config>[];
public plugins: pluginUtils.IPluginAuth<Config>[];
public constructor(config: Config) {
this.config = config;
@ -114,13 +103,16 @@ class Auth implements IAuth {
private loadDefaultPlugin() {
debug('load default auth plugin');
const pluginOptions: PluginOptions = {
const pluginOptions: pluginUtils.PluginOptions = {
config: this.config,
logger: this.logger,
};
let authPlugin;
try {
authPlugin = new HTPasswd({ file: './htpasswd' }, pluginOptions as any as PluginOptions);
authPlugin = new HTPasswd(
{ file: './htpasswd' },
pluginOptions as any as pluginUtils.PluginOptions
);
} catch (error: any) {
debug('error on loading auth htpasswd plugin stack: %o', error);
return [];
@ -129,14 +121,14 @@ class Auth implements IAuth {
return [authPlugin];
}
private async loadPlugin(): Promise<IPluginAuth<Config>[]> {
return asyncLoadPlugin<IPluginAuth<Config>>(
private async loadPlugin(): Promise<pluginUtils.IPluginAuth<Config>[]> {
return asyncLoadPlugin<pluginUtils.IPluginAuth<any>>(
this.config.auth,
{
config: this.config,
logger: this.logger,
},
(plugin: IPluginAuth<Config>): boolean => {
(plugin: pluginUtils.IPluginAuth<Config>): boolean => {
const { authenticate, allow_access, allow_publish } = plugin;
// @ts-ignore
@ -195,7 +187,7 @@ class Auth implements IAuth {
public authenticate(username: string, password: string, cb: Callback): void {
const plugins = this.plugins.slice(0);
(function next(): void {
const plugin = plugins.shift() as IPluginAuth<Config>;
const plugin = plugins.shift() as pluginUtils.IPluginAuth<Config>;
if (isFunction(plugin.authenticate) === false) {
return next();
@ -239,7 +231,7 @@ class Auth implements IAuth {
debug('add user %o', user);
(function next(): void {
const plugin = plugins.shift() as IPluginAuth<Config>;
const plugin = plugins.shift() as pluginUtils.IPluginAuth<Config>;
let method = 'adduser';
if (isFunction(plugin[method]) === false) {
method = 'add_user';
@ -272,7 +264,7 @@ class Auth implements IAuth {
* Allow user to access a package.
*/
public allow_access(
{ packageName, packageVersion }: AuthPluginPackage,
{ packageName, packageVersion }: pluginUtils.AuthPluginPackage,
user: RemoteUser,
callback: Callback
): void {
@ -286,7 +278,8 @@ class Auth implements IAuth {
debug('allow access for %o', packageName);
(function next(): void {
const plugin: IPluginAuth<Config> = plugins.shift() as IPluginAuth<Config>;
const plugin: pluginUtils.IPluginAuth<Config> =
plugins.shift() as pluginUtils.IPluginAuth<Config>;
if (_.isNil(plugin) || isFunction(plugin.allow_access) === false) {
return next();
@ -309,7 +302,7 @@ class Auth implements IAuth {
}
public allow_unpublish(
{ packageName, packageVersion }: AuthPluginPackage,
{ packageName, packageVersion }: pluginUtils.AuthPluginPackage,
user: RemoteUser,
callback: Callback
): void {
@ -354,7 +347,7 @@ class Auth implements IAuth {
* Allow user to publish a package.
*/
public allow_publish(
{ packageName, packageVersion }: AuthPluginPackage,
{ packageName, packageVersion }: pluginUtils.AuthPluginPackage,
user: RemoteUser,
callback: Callback
): void {

@ -1,4 +1,4 @@
export { Auth, IAuth, TokenEncryption, IBasicAuth } from './auth';
export { Auth, IAuth, TokenEncryption } from './auth';
export * from './utils';
export * from './legacy-token';
export * from './jwt-token';

@ -9,15 +9,9 @@ import {
TOKEN_BEARER,
VerdaccioError,
errorUtils,
pluginUtils,
} from '@verdaccio/core';
import {
AuthPackageAllow,
Callback,
Config,
IPluginAuth,
RemoteUser,
Security,
} from '@verdaccio/types';
import { AuthPackageAllow, Callback, Config, RemoteUser, Security } from '@verdaccio/types';
import { AESPayload, TokenEncryption } from './auth';
import { verifyPayload } from './jwt-token';
@ -161,7 +155,7 @@ export function isAuthHeaderValid(authorization: string): boolean {
return authorization.split(' ').length === 2;
}
export function getDefaultPlugins(logger: any): IPluginAuth<Config> {
export function getDefaultPlugins(logger: any): pluginUtils.IPluginAuth<Config> {
return {
authenticate(user: string, password: string, cb: Callback): void {
cb(errorUtils.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));

@ -11,7 +11,7 @@
"path": "../config"
},
{
"path": "../core/htpasswd"
"path": "../plugins/htpasswd"
},
{
"path": "../loaders"
@ -19,9 +19,6 @@
{
"path": "../logger"
},
{
"path": "../mock"
},
{
"path": "../utils"
}

@ -10,9 +10,6 @@
{
"path": "../config"
},
{
"path": "../core/cli-ui"
},
{
"path": "../core/core"
},

@ -1,72 +1,5 @@
# @verdaccio/config
[![backers](https://opencollective.com/verdaccio/tiers/backer/badge.svg?label=Backer&color=brightgreen)](https://opencollective.com/verdaccio)
[![stackshare](https://img.shields.io/badge/Follow%20on-StackShare-blue.svg?logo=stackshare&style=flat)](https://stackshare.io/verdaccio)
[![MIT](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/verdaccio/localized.svg)](https://crowdin.com/project/verdaccio)
[![TODOs](https://badgen.net/https/api.tickgit.com/badgen/github.com/verdaccio/verdaccio)](https://www.tickgit.com/browse?repo=github.com/verdaccio/verdaccio)
[![Twitter followers](https://img.shields.io/twitter/follow/verdaccio_npm.svg?style=social&label=Follow)](https://twitter.com/verdaccio_npm)
[![Github](https://img.shields.io/github/stars/verdaccio/verdaccio.svg?style=social&label=Stars)](https://github.com/verdaccio/verdaccio/stargazers)
## Donations
Verdaccio is run by **volunteers**; nobody is working full-time on it. If you find this project to be useful and would like to support its development, consider making a donation - **your logo might end up in this readme.** 😉
**[Donate](https://opencollective.com/verdaccio)** 💵👍🏻 starting from _\$1/month_ or just one single contribution.
## Report a vulnerability
If you want to report a security vulnerability, please follow the steps which we have defined for you in our [security policy](https://github.com/verdaccio/verdaccio/security/policy).
## Open Collective Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/verdaccio#sponsor)]
[![sponsor](https://opencollective.com/verdaccio/sponsor/0/avatar.svg)](https://opencollective.com/verdaccio/sponsor/0/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/1/avatar.svg)](https://opencollective.com/verdaccio/sponsor/1/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/2/avatar.svg)](https://opencollective.com/verdaccio/sponsor/2/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/3/avatar.svg)](https://opencollective.com/verdaccio/sponsor/3/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/4/avatar.svg)](https://opencollective.com/verdaccio/sponsor/4/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/5/avatar.svg)](https://opencollective.com/verdaccio/sponsor/5/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/6/avatar.svg)](https://opencollective.com/verdaccio/sponsor/6/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/7/avatar.svg)](https://opencollective.com/verdaccio/sponsor/7/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/8/avatar.svg)](https://opencollective.com/verdaccio/sponsor/8/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/9/avatar.svg)](https://opencollective.com/verdaccio/sponsor/9/website)
## Open Collective Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/verdaccio#backer)]
[![backers](https://opencollective.com/verdaccio/backers.svg?width=890)](https://opencollective.com/verdaccio#backers)
## Special Thanks
Thanks to the following companies to help us to achieve our goals providing free open source licenses.
[![jetbrain](assets/thanks/jetbrains/logo.png)](https://www.jetbrains.com/)
[![crowdin](assets/thanks/crowdin/logo.png)](https://crowdin.com/)
[![balsamiq](assets/thanks/balsamiq/logo.jpg)](https://balsamiq.com/)
## Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
[![contributors](https://opencollective.com/verdaccio/contributors.svg?width=890&button=true)](../../graphs/contributors)
### FAQ / Contact / Troubleshoot
If you have any issue you can try the following options, do no desist to ask or check our issues database, perhaps someone has asked already what you are looking for.
- [Blog](https://verdaccio.org/blog/)
- [Donations](https://opencollective.com/verdaccio)
- [Reporting an issue](https://github.com/verdaccio/verdaccio/blob/master/CONTRIBUTING.md#reporting-a-bug)
- [Running discussions](https://github.com/verdaccio/verdaccio/issues?q=is%3Aissue+is%3Aopen+label%3Adiscuss)
- [Chat](http://chat.verdaccio.org/)
- [Logos](https://verdaccio.org/docs/en/logo)
- [Docker Examples](https://github.com/verdaccio/docker-examples)
- [FAQ](https://github.com/verdaccio/verdaccio/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Aquestion%20)
### License
Verdaccio is [MIT licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)

@ -1,15 +1,75 @@
import { Config, IPackageStorage, Token, TokenFilter } from '@verdaccio/types';
import { Readable, Writable } from 'stream';
import {
AllowAccess,
Callback,
Config,
HttpError,
Logger,
Manifest,
PackageAccess,
RemoteUser,
Token,
TokenFilter,
} from '@verdaccio/types';
import { searchUtils } from '.';
interface IPlugin {
version?: string;
// In case a plugin needs to be cleaned up/removed
close?(): void;
export type AuthError = HttpError & { code: number };
export type AuthAccessCallback = (error: AuthError | null, access: boolean) => void;
export type AuthCallback = (error: AuthError | null, groups: string[] | false) => void;
export interface AuthPluginPackage {
packageName: string;
packageVersion?: string;
tag?: string;
}
export interface PluginOptions {
config: Config;
logger: Logger;
}
export interface IPluginStorage<T> extends IPlugin {
config: T & Config;
/**
* The base plugin class, set of utilities for developing
* plugins.
* @alpha
* */
export class Plugin<T> {
static version = 1;
public version: number;
public config: T;
public options: PluginOptions;
public constructor(config: T, options: PluginOptions) {
this.version = Plugin.version;
this.config = config;
this.options = options;
}
public getVersion() {
return this.version;
}
}
export interface IPackageStorage {
logger: Logger;
deletePackage(fileName: string): Promise<void>;
removePackage(): Promise<void>;
// next packages migration (this list is meant to replace the callback parent functions)
updatePackage(
packageName: string,
handleUpdate: (manifest: Manifest) => Promise<Manifest>
): Promise<Manifest>;
readPackage(name: string): Promise<Manifest>;
savePackage(pkgName: string, value: Manifest): Promise<void>;
readTarball(pkgName: string, { signal }): Promise<Readable>;
createPackage(name: string, manifest: Manifest): Promise<void>;
writeTarball(tarballName: string, { signal }): Promise<Writable>;
// verify if tarball exist in the storage
hasTarball(fileName: string): Promise<boolean>;
// verify if package exist in the storage
hasPackage(): Promise<boolean>;
}
export interface IPluginStorage<T> extends Plugin<T> {
add(name: string): Promise<void>;
remove(name: string): Promise<void>;
get(): Promise<any>;
@ -22,3 +82,39 @@ export interface IPluginStorage<T> extends IPlugin {
deleteToken(user: string, tokenKey: string): Promise<any>;
readTokens(filter: TokenFilter): Promise<Token[]>;
}
export interface IBasicAuth {
authenticate(user: string, password: string, cb: Callback): void;
invalidateToken?(token: string): Promise<void>;
changePassword(user: string, password: string, newPassword: string, cb: Callback): void;
allow_access(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void;
add_user(user: string, password: string, cb: Callback): any;
}
export interface IPluginMiddleware<T, K, L> extends Plugin<T> {
register_middlewares(app: any, auth: L, storage: K): void;
}
export interface IPluginAuth<T> extends Plugin<T> {
/**
* @param props user from Application component
*/
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: T & PackageAccess, cb: AuthAccessCallback): void;
allow_publish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
allow_access?(user: RemoteUser, pkg: T & PackageAccess, cb: AuthAccessCallback): void;
allow_access?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
allow_unpublish?(user: RemoteUser, pkg: T & PackageAccess, cb: AuthAccessCallback): void;
allow_unpublish?(
user: RemoteUser,
pkg: AllowAccess & PackageAccess,
cb: AuthAccessCallback
): void;
apiJWTmiddleware?(helpers: any): Function;
}
export interface IPluginStorageFilter<T> extends Plugin<T> {
filterMetadata(packageInfo: Manifest): Promise<Manifest>;
}

@ -1,90 +1,9 @@
import { PassThrough, Transform, TransformOptions } from 'stream';
export interface IReadTarball {
abort?: () => void;
}
export interface IUploadTarball {
done?: () => void;
abort?: () => void;
}
/**
* This stream is used to read tarballs from repository.
* @param {*} options
* @return {Stream}
*/
class ReadTarball extends PassThrough implements IReadTarball {
/**
*
* @param {Object} options
*/
public constructor(options: TransformOptions) {
super(options);
// called when data is not needed anymore
addAbstractMethods(this, 'abort');
}
public abort(): void {}
}
/**
* This stream is used to upload tarballs to a repository.
* @param {*} options
* @return {Stream}
*/
class UploadTarball extends PassThrough implements IUploadTarball {
/**
*
* @param {Object} options
*/
public constructor(options: any) {
super(options);
// called when user closes connection before upload finishes
addAbstractMethods(this, 'abort');
// called when upload finishes successfully
addAbstractMethods(this, 'done');
}
public abort(): void {}
public done(): void {}
}
/**
* This function intercepts abstract calls and replays them allowing.
* us to attach those functions after we are ready to do so
* @param {*} self
* @param {*} name
*/
// Perhaps someone knows a better way to write this
function addAbstractMethods(self: any, name: any): void {
self._called_methods = self._called_methods || {};
self.__defineGetter__(name, function () {
return function (): void {
self._called_methods[name] = true;
};
});
self.__defineSetter__(name, function (fn: any) {
delete self[name];
self[name] = fn;
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
if (self._called_methods && self._called_methods[name]) {
delete self._called_methods[name];
self[name]();
}
});
}
import { Readable, Transform } from 'stream';
/**
* Converts a buffer stream to a string.
*/
const readableToString = async (stream) => {
const readableToString = async (stream: Readable) => {
const chunks: Buffer[] = [];
for await (let chunk of stream) {
chunks.push(Buffer.from(chunk));
@ -106,4 +25,4 @@ const transformObjectToString = () => {
});
};
export { ReadTarball, UploadTarball, readableToString, transformObjectToString };
export { readableToString, transformObjectToString };

@ -1,34 +1,8 @@
import { Stream } from 'stream';
import { ReadTarball, UploadTarball, readableToString } from '../src/stream-utils';
import { readableToString } from '../src/stream-utils';
describe('mystreams', () => {
test('should delay events on ReadTarball abort', (cb) => {
const readTballStream = new ReadTarball({});
readTballStream.abort();
setTimeout(function () {
readTballStream.abort = function (): void {
cb();
};
readTballStream.abort = function (): never {
throw Error('fail');
};
}, 10);
});
test('should delay events on UploadTarball abort', (cb) => {
const uploadTballStream = new UploadTarball({});
uploadTballStream.abort();
setTimeout(function () {
uploadTballStream.abort = function (): void {
cb();
};
uploadTballStream.abort = function (): never {
throw Error('fail');
};
}, 10);
});
test('readableToString single string', async () => {
expect(await readableToString(Stream.Readable.from('foo'))).toEqual('foo');
});

@ -1,26 +1,3 @@
# @verdaccio/types
TypeScript definitions for Verdaccio plugins and internal code.
### Usage
```ts
import type {ILocalData, LocalStorage, Logger, Config} from '@verdaccio/types';
class LocalData implements ILocalData {
path: string;
logger: Logger;
data: LocalStorage;
config: Config;
locked: boolean;
...
}
```
### Run docs
Generate the package types documentation at `./docs` folder.
```bash
pnpm build:docs
```

@ -36,14 +36,13 @@
"scripts": {
"clean": "rimraf ./build",
"test": "pnpm type-check",
"build:docs": "typedoc --options ./typedoc.json --excludeExternals --tsconfig tsconfig.build.json",
"build:docs": "typedoc --options ./typedoc.json --tsconfig tsconfig.build.json",
"type-check": "tsc --noEmit -p tsconfig.build.json",
"build": "tsc --emitDeclarationOnly -p tsconfig.build.json"
},
"devDependencies": {
"@types/node": "16.11.62",
"typedoc": "beta",
"typedoc-plugin-missing-exports": "1.0.0"
"typedoc": "0.23.15"
},
"typedoc": {
"entryPoint": "./src/types.ts",

@ -1,22 +0,0 @@
import { Callback, HttpError, RemoteUser } from '../commons';
import { Config } from '../configuration';
export interface AuthPluginPackage {
packageName: string;
packageVersion?: string;
tag?: string;
}
export type AuthError = HttpError & { code: number };
export type AuthAccessCallback = (error: AuthError | null, access: boolean) => void;
export type AuthCallback = (error: AuthError | null, groups: string[] | false) => void;
// @deprecated use IBasicAuth from @verdaccio/auth
export interface IBasicAuth<T> {
config: T & Config;
aesEncrypt(buf: Buffer): Buffer;
authenticate(user: string, password: string, cb: Callback): void;
changePassword(user: string, password: string, newPassword: string, cb: Callback): void;
allow_access(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void;
add_user(user: string, password: string, cb: Callback): any;
}

@ -1,15 +0,0 @@
import { Config, Logger } from '../configuration';
export class Plugin<T> {
public constructor(config: T, options: PluginOptions) {}
}
export interface IPlugin<T> {
// TODO: not used on core yet
version?: string;
}
export interface PluginOptions {
config: Config;
logger: Logger;
}

@ -1,6 +0,0 @@
import { Manifest } from '../manifest';
import { IPlugin } from './commons';
export interface IPluginStorageFilter<T> extends IPlugin<T> {
filterMetadata(packageInfo: Manifest): Promise<Manifest>;
}

@ -1,31 +1 @@
import { RemoteUser } from '../commons';
import { AllowAccess } from '../configuration';
import { PackageAccess } from '../manifest';
import { AuthAccessCallback, AuthCallback } from './auth';
import { IPlugin } from './commons';
export interface IPluginAuth<T> extends IPlugin<T> {
/**
* @param props user from Application component
*/
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: T & PackageAccess, cb: AuthAccessCallback): void;
allow_access?(user: RemoteUser, pkg: T & PackageAccess, cb: AuthAccessCallback): void;
allow_unpublish?(user: RemoteUser, pkg: T & PackageAccess, cb: AuthAccessCallback): 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;
}
export * from './auth';
export * from './storage';
export * from './middleware';
export * from './commons';
export * from './filter';

@ -1,8 +0,0 @@
import { Config } from '../configuration';
import { IBasicAuth } from './auth';
import { IPlugin } from './commons';
// TODO: convert to generic storage should come from implementation
export interface IPluginMiddleware<T, K> extends IPlugin<T> {
register_middlewares(app: any, auth: IBasicAuth<T>, storage: K): void;
}

@ -1,17 +1,8 @@
import { PassThrough, PipelinePromise, Readable, Stream, Writable } from 'stream';
import { Callback, CallbackAction, StringValue } from '../commons';
import { Config, Logger } from '../configuration';
import { Manifest, MergeTags, Token, Version } from '../manifest';
import { IPlugin } from './commons';
import { Callback, CallbackAction } from '../commons';
import { Manifest, Token } from '../manifest';
export type StorageList = string[];
export interface LocalStorage {
list: any;
secret: string;
}
export interface ILocalStorage {
add(name: string): void;
remove(name: string): void;
@ -53,43 +44,3 @@ export type StorageUpdateCallback = (data: Manifest, cb: CallbackAction) => void
export type StorageWriteCallback = (name: string, json: Manifest, callback: Callback) => void;
export type PackageTransformer = (pkg: Manifest) => Manifest;
export type ReadPackageCallback = (err: any | null, data?: Manifest) => void;
export interface ILocalPackageManager {
logger: Logger;
deletePackage(fileName: string): Promise<void>;
removePackage(): Promise<void>;
// next packages migration (this list is meant to replace the callback parent functions)
updatePackage(
packageName: string,
handleUpdate: (manifest: Manifest) => Promise<Manifest>
): Promise<Manifest>;
readPackage(name: string): Promise<Manifest>;
savePackage(pkgName: string, value: Manifest): Promise<void>;
readTarball(pkgName: string, { signal }): Promise<Readable>;
createPackage(name: string, manifest: Manifest): Promise<void>;
writeTarball(tarballName: string, { signal }): Promise<Writable>;
// verify if tarball exist in the storage
hasTarball(fileName: string): Promise<boolean>;
// verify if package exist in the storage
hasPackage(): Promise<boolean>;
}
export type IPackageStorage = ILocalPackageManager | void;
export type IPluginStorage<T> = ILocalData<T>;
export type IPackageStorageManager = ILocalPackageManager;
/**
* @deprecated use @verdaccio/core pluginUtils instead
*/
interface ILocalData<T> extends IPlugin<T>, ITokenActions {
logger: Logger;
config: T;
add(name: string): Promise<void>;
remove(name: string): Promise<void>;
get(): Promise<any>;
init(): Promise<void>;
getSecret(): Promise<string>;
setSecret(secret: string): Promise<any>;
getPackageStorage(packageInfo: string): IPackageStorage;
}

@ -2,8 +2,9 @@ import buildDebug from 'debug';
import { lstat } from 'fs/promises';
import { dirname, isAbsolute, join, resolve } from 'path';
import { pluginUtils } from '@verdaccio/core';
import { logger } from '@verdaccio/logger';
import { Config, IPlugin, Logger } from '@verdaccio/types';
import { Config, Logger } from '@verdaccio/types';
import { isES6, isValid, tryLoad } from './utils';
@ -38,7 +39,7 @@ export type Params = { config: Config; logger: Logger };
* @param {*} prefix by default is verdaccio but can be override with config.server.pluginPrefix
* @return {Array} list of plugins
*/
export async function asyncLoadPlugin<T extends IPlugin<T>>(
export async function asyncLoadPlugin<T extends pluginUtils.Plugin<T>>(
pluginConfigs: any = {},
params: Params,
sanityCheck: any,

@ -15,9 +15,6 @@
},
{
"path": "../logger"
},
{
"path": "../mock"
}
]
}

@ -1,72 +1,5 @@
# @verdaccio/node-api
[![backers](https://opencollective.com/verdaccio/tiers/backer/badge.svg?label=Backer&color=brightgreen)](https://opencollective.com/verdaccio)
[![stackshare](https://img.shields.io/badge/Follow%20on-StackShare-blue.svg?logo=stackshare&style=flat)](https://stackshare.io/verdaccio)
[![MIT](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/verdaccio/localized.svg)](https://crowdin.com/project/verdaccio)
[![TODOs](https://badgen.net/https/api.tickgit.com/badgen/github.com/verdaccio/verdaccio)](https://www.tickgit.com/browse?repo=github.com/verdaccio/verdaccio)
[![Twitter followers](https://img.shields.io/twitter/follow/verdaccio_npm.svg?style=social&label=Follow)](https://twitter.com/verdaccio_npm)
[![Github](https://img.shields.io/github/stars/verdaccio/verdaccio.svg?style=social&label=Stars)](https://github.com/verdaccio/verdaccio/stargazers)
## Donations
Verdaccio is run by **volunteers**; nobody is working full-time on it. If you find this project to be useful and would like to support its development, consider making a donation - **your logo might end up in this readme.** 😉
**[Donate](https://opencollective.com/verdaccio)** 💵👍🏻 starting from _\$1/month_ or just one single contribution.
## Report a vulnerability
If you want to report a security vulnerability, please follow the steps which we have defined for you in our [security policy](https://github.com/verdaccio/verdaccio/security/policy).
## Open Collective Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/verdaccio#sponsor)]
[![sponsor](https://opencollective.com/verdaccio/sponsor/0/avatar.svg)](https://opencollective.com/verdaccio/sponsor/0/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/1/avatar.svg)](https://opencollective.com/verdaccio/sponsor/1/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/2/avatar.svg)](https://opencollective.com/verdaccio/sponsor/2/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/3/avatar.svg)](https://opencollective.com/verdaccio/sponsor/3/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/4/avatar.svg)](https://opencollective.com/verdaccio/sponsor/4/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/5/avatar.svg)](https://opencollective.com/verdaccio/sponsor/5/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/6/avatar.svg)](https://opencollective.com/verdaccio/sponsor/6/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/7/avatar.svg)](https://opencollective.com/verdaccio/sponsor/7/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/8/avatar.svg)](https://opencollective.com/verdaccio/sponsor/8/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/9/avatar.svg)](https://opencollective.com/verdaccio/sponsor/9/website)
## Open Collective Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/verdaccio#backer)]
[![backers](https://opencollective.com/verdaccio/backers.svg?width=890)](https://opencollective.com/verdaccio#backers)
## Special Thanks
Thanks to the following companies to help us to achieve our goals providing free open source licenses.
[![jetbrain](assets/thanks/jetbrains/logo.png)](https://www.jetbrains.com/)
[![crowdin](assets/thanks/crowdin/logo.png)](https://crowdin.com/)
[![balsamiq](assets/thanks/balsamiq/logo.jpg)](https://balsamiq.com/)
## Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
[![contributors](https://opencollective.com/verdaccio/contributors.svg?width=890&button=true)](../../graphs/contributors)
### FAQ / Contact / Troubleshoot
If you have any issue you can try the following options, do no desist to ask or check our issues database, perhaps someone has asked already what you are looking for.
- [Blog](https://verdaccio.org/blog/)
- [Donations](https://opencollective.com/verdaccio)
- [Reporting an issue](https://github.com/verdaccio/verdaccio/blob/master/CONTRIBUTING.md#reporting-a-bug)
- [Running discussions](https://github.com/verdaccio/verdaccio/issues?q=is%3Aissue+is%3Aopen+label%3Adiscuss)
- [Chat](http://chat.verdaccio.org/)
- [Logos](https://verdaccio.org/docs/en/logo)
- [Docker Examples](https://github.com/verdaccio/docker-examples)
- [FAQ](https://github.com/verdaccio/verdaccio/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Aquestion%20)
### License
Verdaccio is [MIT licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)

@ -173,12 +173,14 @@ export async function initServer(
/**
* Exposes a server factory to be instantiated programmatically.
*
```ts
const app = await runServer(); // default configuration
const app = await runServer('./config/config.yaml');
const app = await runServer({ configuration });
app.listen(4000, (event) => {
// do something
});
```
* @param config
*/
export async function runServer(config?: string | ConfigYaml): Promise<any> {

@ -15,7 +15,7 @@ describe('startServer via API', () => {
});
test('should fail on start with null as entry', async () => {
// @ts-expected-error
// @ts-expect-error
await expect(runServer(null)).rejects.toThrow();
});
});

@ -4,6 +4,5 @@
"rootDir": "./src",
"outDir": "./build"
},
"include": ["src/**/*.ts"],
"exclude": ["src/**/*.test.ts"]
"include": ["src/**/*.ts", "types/*.d.ts"]
}

@ -4,21 +4,15 @@
"rootDir": "./src",
"outDir": "./build"
},
"include": ["src/**/*"],
"include": ["src/**/*.ts", "types/*.d.ts"],
"exclude": ["src/**/*.test.ts"],
"references": [
{
"path": "../config"
},
{
"path": "../core/cli-ui"
},
{
"path": "../logger"
},
{
"path": "../mock"
},
{
"path": "../server/express"
},

@ -31,6 +31,9 @@
"npm": ">=6"
},
"dependencies": {
"@verdaccio/core": "workspace:6.0.0-6-next.48",
"@verdaccio/config": "workspace:6.0.0-6-next.48",
"@verdaccio/logger": "workspace:6.0.0-6-next.16",
"express": "4.18.1",
"body-parser": "1.20.0",
"https-proxy-agent": "5.0.1",
@ -38,8 +41,7 @@
},
"devDependencies": {
"@verdaccio/types": "workspace:11.0.0-6-next.17",
"@verdaccio/config": "workspace:6.0.0-6-next.48",
"@verdaccio/logger": "workspace:6.0.0-6-next.16",
"@verdaccio/auth": "workspace:6.0.0-6-next.27",
"nock": "13.2.9",
"supertest": "6.2.4"
},

@ -4,25 +4,31 @@ import https from 'https';
import createHttpsProxyAgent from 'https-proxy-agent';
import fetch from 'node-fetch';
import { IBasicAuth, IPluginMiddleware, Logger, PluginOptions } from '@verdaccio/types';
import type { Auth } from '@verdaccio/auth';
import { pluginUtils } from '@verdaccio/core';
import { Logger } from '@verdaccio/types';
import { ConfigAudit } from './types';
// FUTURE: we should be able to overwrite this
export const REGISTRY_DOMAIN = 'https://registry.npmjs.org';
export default class ProxyAudit implements IPluginMiddleware<{}, {}> {
export default class ProxyAudit
extends pluginUtils.Plugin<ConfigAudit>
implements pluginUtils.IPluginMiddleware<ConfigAudit, {}, Auth>
{
public enabled: boolean;
public logger: Logger;
public strict_ssl: boolean;
public constructor(config: ConfigAudit, options: PluginOptions) {
public constructor(config: ConfigAudit, options: pluginUtils.PluginOptions) {
super(config, options);
this.enabled = config.enabled || false;
this.strict_ssl = config.strict_ssl !== undefined ? config.strict_ssl : true;
this.logger = options.logger;
}
public register_middlewares(app: any, auth: IBasicAuth<ConfigAudit>): void {
public register_middlewares(app: any, auth: Auth): void {
const fetchAudit = async (
req: Request,
res: Response & { report_error?: Function }

@ -8,10 +8,16 @@
"exclude": ["src/**/*.test.ts"],
"references": [
{
"path": "../config"
"path": "../../config"
},
{
"path": "../logger"
"path": "../../auth"
},
{
"path": "../../logger"
},
{
"path": "../../core/core"
}
]
}

@ -1,27 +1,23 @@
import buildDebug from 'debug';
import { API_ERROR, errorUtils } from '@verdaccio/core';
import {
Callback,
Config,
IPluginAuth,
Logger,
PackageAccess,
PluginOptions,
RemoteUser,
} from '@verdaccio/types';
import { API_ERROR, errorUtils, pluginUtils } from '@verdaccio/core';
import { Callback, Config, Logger, PackageAccess, RemoteUser } from '@verdaccio/types';
import { UserMemory, Users, VerdaccioMemoryConfig } from './types';
const debug = buildDebug('verdaccio:plugin:auth:memory:user');
export default class Memory implements IPluginAuth<VerdaccioMemoryConfig> {
export default class Memory
extends pluginUtils.Plugin<VerdaccioMemoryConfig>
implements pluginUtils.IPluginAuth<VerdaccioMemoryConfig>
{
public _logger: Logger;
public _users: Users;
public _config: {};
public _app_config: Config;
public constructor(config: VerdaccioMemoryConfig, appOptions: PluginOptions) {
public constructor(config: VerdaccioMemoryConfig, appOptions: pluginUtils.PluginOptions) {
super(config, appOptions);
this._users = config.users || {};
this._config = config;
this._logger = appOptions.logger;

@ -5,10 +5,5 @@
"outDir": "./build"
},
"include": ["src/**/*", "types/*.d.ts"],
"exclude": ["src/**/*.test.ts"],
"references": [
{
"path": "../../core/streams"
}
]
"exclude": ["src/**/*.test.ts"]
}

@ -5,10 +5,5 @@
"outDir": "./build"
},
"include": ["src/**/*", "types/*.d.ts"],
"exclude": ["src/**/*.test.ts"],
"references": [
{
"path": "../../core/streams"
}
]
"exclude": ["src/**/*.test.ts"]
}

@ -2,8 +2,9 @@ import buildDebug from 'debug';
import fs from 'fs';
import { dirname, join, resolve } from 'path';
import { pluginUtils } from '@verdaccio/core';
import { unlockFile } from '@verdaccio/file-locking';
import { Callback, IPluginAuth, Logger, PluginOptions } from '@verdaccio/types';
import { Callback, Logger } from '@verdaccio/types';
import {
HtpasswdHashAlgorithm,
@ -32,7 +33,10 @@ export const DEFAULT_SLOW_VERIFY_MS = 200;
/**
* HTPasswd - Verdaccio auth class
*/
export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
export default class HTPasswd
extends pluginUtils.Plugin<HTPasswdConfig>
implements pluginUtils.IPluginAuth<HTPasswdConfig>
{
/**
*
* @param {*} config htpasswd file
@ -46,7 +50,8 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
private logger: Logger;
private lastTime: any;
// constructor
public constructor(config: HTPasswdConfig, options: PluginOptions) {
public constructor(config: HTPasswdConfig, options: pluginUtils.PluginOptions) {
super(config, options);
this.users = {};
// verdaccio logger

@ -1,8 +1,8 @@
import { PluginOptions } from '@verdaccio/types';
import type { pluginUtils } from '@verdaccio/core';
import HTPasswd, { HTPasswdConfig } from './htpasswd';
export default function (config: HTPasswdConfig, params: PluginOptions): HTPasswd {
export default function (config: HTPasswdConfig, params: pluginUtils.PluginOptions): HTPasswd {
return new HTPasswd(config, params);
}

@ -1,19 +1,22 @@
// import LRU from 'lru-cache';
import buildDebug from 'debug';
import _ from 'lodash';
import low from 'lowdb';
import FileAsync from 'lowdb/adapters/FileAsync';
import FileMemory from 'lowdb/adapters/Memory';
import path from 'path';
import { errorUtils, fileUtils, pluginUtils, searchUtils } from '@verdaccio/core';
import { Config, IPackageStorage, LocalStorage, Logger } from '@verdaccio/types';
import { Config, Logger, Token, TokenFilter } from '@verdaccio/types';
import { getMatchedPackagesSpec } from '@verdaccio/utils';
import { searchOnStorage } from './dir-utils';
import { mkdirPromise, writeFilePromise } from './fs';
import LocalDriver, { noSuchFile } from './local-fs';
import { loadPrivatePackages } from './pkg-utils';
import TokenActions from './token';
import { LocalStorage, loadPrivatePackages } from './pkg-utils';
import { _dbGenPath } from './utils';
const TOKEN_DB_NAME = '.token-db.json';
const DB_NAME = process.env.VERDACCIO_STORAGE_NAME ?? fileUtils.Files.DatabaseName;
const debug = buildDebug('verdaccio:plugin:local-storage');
@ -23,16 +26,19 @@ export const ERROR_DB_LOCKED =
type IPluginStorage = pluginUtils.IPluginStorage<{}>;
class LocalDatabase extends TokenActions implements IPluginStorage {
class LocalDatabase extends pluginUtils.Plugin<{}> implements IPluginStorage {
private readonly path: string;
private readonly logger: Logger;
public readonly config: Config;
public readonly storages: Map<string, string>;
public data: LocalStorage | undefined;
public locked: boolean;
public tokenDb: low.LowdbAsync<any> | null;
public constructor(config: Config, logger: Logger) {
super(config);
// TODO: fix double config
super(config, { config, logger });
this.tokenDb = null;
this.config = config;
this.logger = logger;
this.locked = false;
@ -183,7 +189,7 @@ class LocalDatabase extends TokenActions implements IPluginStorage {
return Promise.resolve(list);
}
public getPackageStorage(packageName: string): IPackageStorage {
public getPackageStorage(packageName: string): pluginUtils.IPackageStorage {
const packageAccess = getMatchedPackagesSpec(packageName, this.config.packages);
const packagePath: string = this._getLocalStoragePath(
@ -192,7 +198,7 @@ class LocalDatabase extends TokenActions implements IPluginStorage {
debug('storage path selected: ', packagePath);
if (_.isString(packagePath) === false) {
debug('the package %o has no storage defined ', packageName);
return;
throw errorUtils.getInternalError('storage not found or implemented');
}
const packageStoragePath: string = path.join(
@ -292,6 +298,65 @@ class LocalDatabase extends TokenActions implements IPluginStorage {
return { list: [], secret: '' };
}
}
private async getTokenDb(): Promise<low.LowdbAsync<any>> {
if (!this.tokenDb) {
debug('token database is not defined');
let adapter;
if (process.env.NODE_ENV === 'test') {
debug('token memory adapter');
adapter = new FileMemory('');
} else {
debug('token async adapter');
const pathDb = _dbGenPath(TOKEN_DB_NAME, this.config);
adapter = new FileAsync(pathDb);
}
debug('token bd generated');
this.tokenDb = await low(adapter);
}
return this.tokenDb;
}
public async saveToken(token: Token): Promise<void> {
debug('token key %o', token.key);
const db = await this.getTokenDb();
const userData = await db.get(token.user).value();
debug('user data %o', userData);
if (_.isNil(userData)) {
await db.set(token.user, [token]).write();
debug('token user %o new database', token.user);
} else {
// types does not match with valid implementation
// @ts-ignore
await db.get(token.user).push(token).write();
}
debug('data %o', await db.getState());
debug('token saved %o', token.user);
}
public async deleteToken(user: string, tokenKey: string): Promise<void> {
const db = await this.getTokenDb();
const userTokens = await db.get(user).value();
if (_.isNil(userTokens)) {
throw new Error('user not found');
}
debug('tokens %o - %o', userTokens, userTokens.length);
const remainingTokens = userTokens.filter(({ key }) => {
debug('key %o', key);
return key !== tokenKey;
});
await db.set(user, remainingTokens).write();
debug('removed tokens key %o', tokenKey);
}
public async readTokens(filter: TokenFilter): Promise<Token[]> {
const { user } = filter;
debug('read tokens with %o', user);
const db = await this.getTokenDb();
const tokens = await db.get(user).value();
return tokens || [];
}
}
export default LocalDatabase;

@ -5,9 +5,9 @@ import path from 'path';
import sanitzers from 'sanitize-filename';
import { Readable, Writable, addAbortSignal } from 'stream';
import { VerdaccioError, errorUtils } from '@verdaccio/core';
import { VerdaccioError, errorUtils, pluginUtils } from '@verdaccio/core';
import { readFileNext, unlockFileNext } from '@verdaccio/file-locking';
import { ILocalPackageManager, Logger, Manifest } from '@verdaccio/types';
import { Logger, Manifest } from '@verdaccio/types';
import {
accessPromise,
@ -27,7 +27,7 @@ export const noSuchFile = 'ENOENT';
export const resourceNotAvailable = 'EAGAIN';
export const packageJSONFileName = 'package.json';
export type ILocalFSPackageManager = ILocalPackageManager & { path: string };
export type ILocalFSPackageManager = pluginUtils.IPackageStorage & { path: string };
const debug = buildDebug('verdaccio:plugin:local-storage:local-fs');

@ -1,9 +1,14 @@
import _ from 'lodash';
import { LocalStorage, Logger, StorageList } from '@verdaccio/types';
import { Logger, StorageList } from '@verdaccio/types';
import { readFilePromise } from './fs';
export type LocalStorage = {
list: any;
secret: string;
};
export async function loadPrivatePackages(path: string, logger: Logger): Promise<LocalStorage> {
const list: StorageList = [];
const emptyDatabase = { list, secret: '' };

@ -1,82 +0,0 @@
import buildDebug from 'debug';
import _ from 'lodash';
import low from 'lowdb';
import FileAsync from 'lowdb/adapters/FileAsync';
import FileMemory from 'lowdb/adapters/Memory';
import { Config, ITokenActions, Token, TokenFilter } from '@verdaccio/types';
import { _dbGenPath } from './utils';
const debug = buildDebug('verdaccio:plugin:local-storage:token');
const TOKEN_DB_NAME = '.token-db.json';
export default class TokenActions implements ITokenActions {
public config: Config;
public tokenDb: low.LowdbAsync<any> | null;
public constructor(config: Config) {
this.config = config;
this.tokenDb = null;
}
private async getTokenDb(): Promise<low.LowdbAsync<any>> {
if (!this.tokenDb) {
debug('token database is not defined');
let adapter;
if (process.env.NODE_ENV === 'test') {
debug('token memory adapter');
adapter = new FileMemory('');
} else {
debug('token async adapter');
const pathDb = _dbGenPath(TOKEN_DB_NAME, this.config);
adapter = new FileAsync(pathDb);
}
debug('token bd generated');
this.tokenDb = await low(adapter);
}
return this.tokenDb;
}
public async saveToken(token: Token): Promise<void> {
debug('token key %o', token.key);
const db = await this.getTokenDb();
const userData = await db.get(token.user).value();
debug('user data %o', userData);
if (_.isNil(userData)) {
await db.set(token.user, [token]).write();
debug('token user %o new database', token.user);
} else {
// types does not match with valid implementation
// @ts-ignore
await db.get(token.user).push(token).write();
}
debug('data %o', await db.getState());
debug('token saved %o', token.user);
}
public async deleteToken(user: string, tokenKey: string): Promise<void> {
const db = await this.getTokenDb();
const userTokens = await db.get(user).value();
if (_.isNil(userTokens)) {
throw new Error('user not found');
}
debug('tokens %o - %o', userTokens, userTokens.length);
const remainingTokens = userTokens.filter(({ key }) => {
debug('key %o', key);
return key !== tokenKey;
});
await db.set(user, remainingTokens).write();
debug('removed tokens key %o', tokenKey);
}
public async readTokens(filter: TokenFilter): Promise<Token[]> {
const { user } = filter;
debug('read tokens with %o', user);
const db = await this.getTokenDb();
const tokens = await db.get(user).value();
return tokens || [];
}
}

@ -4,23 +4,19 @@
"rootDir": "./src",
"outDir": "./build"
},
"include": ["src/**/*"],
"exclude": ["src/**/*.test.ts"],
"include": ["src/**/*.ts"],
"references": [
{
"path": "../file-locking"
"path": "../../core/file-locking"
},
{
"path": "../streams"
"path": "../../config"
},
{
"path": "../config"
"path": "../../logger"
},
{
"path": "../logger"
},
{
"path": "../core"
"path": "../../core/core"
}
]
}

@ -1,7 +1,7 @@
import buildDebug from 'debug';
import { errorUtils } from '@verdaccio/core';
import { Callback, IPluginStorage, Logger, PluginOptions, Token } from '@verdaccio/types';
import { errorUtils, pluginUtils, searchUtils } from '@verdaccio/core';
import { Logger, Token } from '@verdaccio/types';
import MemoryHandler, { DataHandler } from './memory-handler';
@ -15,14 +15,19 @@ export interface MemoryLocalStorage {
const debug = buildDebug('verdaccio:plugin:storage:local-memory');
const DEFAULT_LIMIT = 1000;
class LocalMemory implements IPluginStorage<ConfigMemory> {
class LocalMemory
extends pluginUtils.Plugin<ConfigMemory>
implements pluginUtils.IPluginStorage<ConfigMemory>
{
private path: string;
private limit: number;
public logger: Logger;
private data: MemoryLocalStorage;
// @ts-ignore
public config: ConfigMemory;
public constructor(config: ConfigMemory, options: PluginOptions) {
public constructor(config: ConfigMemory, options: pluginUtils.PluginOptions) {
super(config, options);
this.config = config;
this.limit = config.limit || DEFAULT_LIMIT;
this.logger = options.logger;
@ -66,9 +71,9 @@ class LocalMemory implements IPluginStorage<ConfigMemory> {
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public search(onPackage: Callback, onEnd: Callback): void {
public async search(query: searchUtils.SearchQuery): Promise<searchUtils.SearchItem[]> {
this.logger.warn('[verdaccio/memory]: search method not implemented, PR is welcome');
onEnd();
return Promise.reject('not implemented');
}
async remove(name: string): Promise<void> {

@ -6,8 +6,8 @@ import path from 'path';
import { PassThrough, Writable, addAbortSignal } from 'stream';
import { pipeline } from 'stream/promises';
import { errorUtils } from '@verdaccio/core';
import { IPackageStorageManager, Logger, Manifest } from '@verdaccio/types';
import { errorUtils, pluginUtils } from '@verdaccio/core';
import { Logger, Manifest } from '@verdaccio/types';
import { parsePackage, stringifyPackage } from './utils';
@ -39,7 +39,7 @@ export type DataHandler = {
[key: string]: string;
};
class MemoryHandler implements IPackageStorageManager {
class MemoryHandler implements pluginUtils.IPackageStorage {
private data: DataHandler;
private name: string;
private path: string;

@ -8,7 +8,7 @@
"exclude": ["src/**/*.test.ts"],
"references": [
{
"path": "../../core/streams"
"path": "../../core/core"
}
]
}

@ -53,6 +53,7 @@
},
"devDependencies": {
"@types/node": "16.11.62",
"p-cancelable": "2.1.1",
"@verdaccio/types": "workspace:11.0.0-6-next.17",
"get-stream": "^6.0.1",
"nock": "13.2.9",

@ -2,17 +2,14 @@
"extends": "../../tsconfig.reference.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./build"
"outDir": "./build",
"noImplicitAny": false
},
"include": ["src/**/*", "types/*.d.ts"],
"exclude": ["src/**/*.test.ts"],
"include": ["src/**/*.ts", "types/*.d.ts"],
"references": [
{
"path": "../config"
},
{
"path": "../core/streams"
},
{
"path": "../core/core"
},

10
packages/proxy/types/patch.d.ts vendored Normal file

@ -0,0 +1,10 @@
declare module 'jest-matcher-utils';
declare module 'pretty-format' {
export type Plugin = any;
export type CompareKeys = any;
}
declare module '@jest/schemas' {
export type SnapshotFormat = any;
}
declare module '@szmarczak/http-timer';

@ -8,25 +8,21 @@ import _ from 'lodash';
import AuditMiddleware from 'verdaccio-audit';
import apiEndpoint from '@verdaccio/api';
import { Auth, IBasicAuth } from '@verdaccio/auth';
import { Auth } from '@verdaccio/auth';
import { Config as AppConfig } from '@verdaccio/config';
import { API_ERROR, HTTP_STATUS, errorUtils } from '@verdaccio/core';
import { API_ERROR, HTTP_STATUS, errorUtils, pluginUtils } from '@verdaccio/core';
import { asyncLoadPlugin } from '@verdaccio/loaders';
import { logger } from '@verdaccio/logger';
import { errorReportingMiddleware, final, log } from '@verdaccio/middleware';
import { Storage } from '@verdaccio/store';
import { ConfigYaml } from '@verdaccio/types';
import { Config as IConfig, IPlugin } from '@verdaccio/types';
import { Config as IConfig } from '@verdaccio/types';
import webMiddleware from '@verdaccio/web';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types/custom';
import hookDebug from './debug';
import { getUserAgent } from './utils';
export interface IPluginMiddleware<T> extends IPlugin<T> {
register_middlewares(app: any, auth: IBasicAuth<T>, storage: Storage): void;
}
const debug = buildDebug('verdaccio:server');
const defineAPI = async function (config: IConfig, storage: Storage): Promise<any> {
@ -63,25 +59,24 @@ const defineAPI = async function (config: IConfig, storage: Storage): Promise<an
hookDebug(app, config.configPath);
}
const plugins: IPluginMiddleware<IConfig>[] = await asyncLoadPlugin(
const plugins: pluginUtils.IPluginMiddleware<IConfig, {}, Auth>[] = await asyncLoadPlugin(
config.middlewares,
{
config,
logger,
},
function (plugin: IPluginMiddleware<IConfig>) {
function (plugin: pluginUtils.IPluginMiddleware<IConfig, {}, Auth>) {
return plugin.register_middlewares;
}
);
if (plugins.length === 0) {
logger.info('none middleware plugins has been defined, adding audit middleware by default');
plugins.push(
new AuditMiddleware({ ...config, enabled: true, strict_ssl: true }, { config, logger })
);
// @ts-ignore
plugins.push(new AuditMiddleware({ enabled: true, strict_ssl: true }, { config, logger }));
}
plugins.forEach((plugin: IPluginMiddleware<IConfig>) => {
plugins.forEach((plugin: pluginUtils.IPluginMiddleware<IConfig, {}, Auth>) => {
plugin.register_middlewares(app, auth, storage);
});

@ -16,9 +16,6 @@
{
"path": "../../config"
},
{
"path": "../../core/commons-api"
},
{
"path": "../../loaders"
},

@ -1,13 +1,13 @@
import { FastifyInstance } from 'fastify';
import fp from 'fastify-plugin';
import { Auth, IAuth } from '@verdaccio/auth';
import { Auth } from '@verdaccio/auth';
import { Config as IConfig } from '@verdaccio/types';
export default fp(
async function (fastify: FastifyInstance, opts: { config: IConfig; filters?: unknown }) {
const { config } = opts;
const auth: IAuth = new Auth(config);
const auth = new Auth(config);
await auth.init();
fastify.decorate('auth', auth);
},
@ -18,6 +18,6 @@ export default fp(
declare module 'fastify' {
interface FastifyInstance {
auth: IAuth;
auth: Auth;
}
}

@ -66,7 +66,7 @@ class LocalStorage {
}
private async loadStorePlugin(): Promise<IPluginStorage | undefined> {
const plugins: IPluginStorage[] = await asyncLoadPlugin<IPluginStorage>(
const plugins: IPluginStorage[] = await asyncLoadPlugin<pluginUtils.IPluginStorage<any>>(
this.config.store,
{
config: this.config,

@ -17,6 +17,7 @@ import {
USERS,
errorUtils,
pkgUtils,
pluginUtils,
searchUtils,
validatioUtils,
} from '@verdaccio/core';
@ -34,8 +35,6 @@ import {
Config,
DistFile,
GenericBody,
IPackageStorage,
IPluginStorageFilter,
Logger,
Manifest,
MergeTags,
@ -174,7 +173,7 @@ class Storage {
public async removeTarball(name: string, filename: string, _revision: string): Promise<Manifest> {
debug('remove tarball %s for %s', filename, name);
assert(validatioUtils.validateName(filename));
const storage: IPackageStorage = this.getPrivatePackageStorage(name);
const storage: pluginUtils.IPackageStorage = this.getPrivatePackageStorage(name);
if (!storage) {
debug(`method not implemented for storage`);
this.logger.error('method for remove tarball not implemented');
@ -200,7 +199,7 @@ class Storage {
});
try {
const storage: IPackageStorage = this.getPrivatePackageStorage(name);
const storage: pluginUtils.IPackageStorage = this.getPrivatePackageStorage(name);
if (!storage) {
debug(`method not implemented for storage`);
this.logger.error('method for remove tarball not implemented');
@ -664,7 +663,7 @@ class Storage {
debug('storage has been already initialized');
}
if (!this.filters) {
this.filters = await asyncLoadPlugin<IPluginStorageFilter<any>>(
this.filters = await asyncLoadPlugin<pluginUtils.IPluginStorageFilter<any>>(
this.config.filters,
{
config: this.config,
@ -707,7 +706,7 @@ class Storage {
* @param {Object} pkgName package name.
* @return {Object}
*/
private getPrivatePackageStorage(pkgName: string): IPackageStorage {
private getPrivatePackageStorage(pkgName: string): pluginUtils.IPackageStorage {
debug('get local storage for %o', pkgName);
return this.localStorage.getStoragePlugin().getPackageStorage(pkgName);
}
@ -725,7 +724,7 @@ class Storage {
{ signal }: { signal: AbortSignal }
): Promise<Readable> {
assert(validatioUtils.validateName(filename));
const storage: IPackageStorage = this.getPrivatePackageStorage(pkgName);
const storage: pluginUtils.IPackageStorage = this.getPrivatePackageStorage(pkgName);
if (typeof storage === 'undefined') {
return this.createFailureStreamResponseNext();
}
@ -776,7 +775,7 @@ class Storage {
}
private async removePackageByRevision(pkgName: string, revision: string): Promise<void> {
const storage: IPackageStorage = this.getPrivatePackageStorage(pkgName);
const storage: pluginUtils.IPackageStorage = this.getPrivatePackageStorage(pkgName);
debug('get package metadata for %o', pkgName);
if (typeof storage === 'undefined') {
throw errorUtils.getServiceUnavailable('storage not initialized');
@ -831,7 +830,7 @@ class Storage {
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public async getPackageLocalMetadata(name: string, _revision?: string): Promise<Manifest> {
const storage: IPackageStorage = this.getPrivatePackageStorage(name);
const storage: pluginUtils.IPackageStorage = this.getPrivatePackageStorage(name);
debug('get package metadata for %o', name);
if (typeof storage === 'undefined') {
throw errorUtils.getServiceUnavailable('storage not initialized');
@ -1052,7 +1051,7 @@ class Storage {
* @returns boolean
*/
private async hasPackage(pkgName: string): Promise<boolean> {
const storage: IPackageStorage = this.getPrivatePackageStorage(pkgName);
const storage: pluginUtils.IPackageStorage = this.getPrivatePackageStorage(pkgName);
if (typeof storage === 'undefined') {
throw errorUtils.getNotFound();
}
@ -1410,7 +1409,7 @@ class Storage {
* @returns
*/
private async createNewLocalCachePackage(name: string, latestVersion: string): Promise<void> {
const storage: IPackageStorage = this.getPrivatePackageStorage(name);
const storage: pluginUtils.IPackageStorage = this.getPrivatePackageStorage(name);
if (!storage) {
debug(`storage is missing for %o package cannot be added`, name);
@ -1518,7 +1517,7 @@ class Storage {
name: string,
updateHandler: (manifest: Manifest) => Promise<Manifest>
): Promise<Manifest> {
const storage: IPackageStorage = this.getPrivatePackageStorage(name);
const storage: pluginUtils.IPackageStorage = this.getPrivatePackageStorage(name);
if (!storage) {
throw errorUtils.getNotFound();

@ -1,5 +1,6 @@
import { pluginUtils } from '@verdaccio/core';
import { FetchOptions } from '@verdaccio/proxy';
import { Config, IPluginStorageFilter, Manifest, RemoteUser } from '@verdaccio/types';
import { Config, Manifest, RemoteUser } from '@verdaccio/types';
import { RequestOptions } from '@verdaccio/url';
// @deprecated use IGetPackageOptionsNext
@ -57,7 +58,7 @@ export type UpdateManifestOptions = {
signal: AbortSignal;
};
export type IPluginFilters = IPluginStorageFilter<Config>[];
export type IPluginFilters = pluginUtils.IPluginStorageFilter<Config>[];
/**
* When the command `npm star` is executed, the body only contains the following

@ -13,9 +13,6 @@
{
"path": "../plugins/local-storage"
},
{
"path": "../core/streams"
},
{
"path": "../core/url"
},
@ -31,9 +28,6 @@
{
"path": "../logger"
},
{
"path": "../mock"
},
{
"path": "../proxy"
},

12
packages/store/types/patch.d.ts vendored Normal file

@ -0,0 +1,12 @@
declare module 'jest-matcher-utils';
declare module 'pretty-format' {
export type Plugin = any;
export type CompareKeys = any;
}
declare module '@jest/schemas' {
export type SnapshotFormat = any;
}
declare module '@szmarczak/http-timer';
declare module 'cacheable-lookup';
// declare module 'p-cancelable';

@ -9,10 +9,5 @@
"declarationMap": true
},
"include": ["src/**/*.ts"],
"exclude": ["src/**/*.test.ts"],
"references": [
{
"path": "../core/commons-api"
}
]
"exclude": ["src/**/*.test.ts"]
}

@ -4,73 +4,6 @@
npm install --global verdaccio
```
[![backers](https://opencollective.com/verdaccio/tiers/backer/badge.svg?label=Backer&color=brightgreen)](https://opencollective.com/verdaccio)
[![stackshare](https://img.shields.io/badge/Follow%20on-StackShare-blue.svg?logo=stackshare&style=flat)](https://stackshare.io/verdaccio)
[![MIT](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/verdaccio/localized.svg)](https://crowdin.com/project/verdaccio)
[![TODOs](https://badgen.net/https/api.tickgit.com/badgen/github.com/verdaccio/verdaccio)](https://www.tickgit.com/browse?repo=github.com/verdaccio/verdaccio)
[![Twitter followers](https://img.shields.io/twitter/follow/verdaccio_npm.svg?style=social&label=Follow)](https://twitter.com/verdaccio_npm)
[![Github](https://img.shields.io/github/stars/verdaccio/verdaccio.svg?style=social&label=Stars)](https://github.com/verdaccio/verdaccio/stargazers)
## Donations
Verdaccio is run by **volunteers**; nobody is working full-time on it. If you find this project to be useful and would like to support its development, consider making a donation - **your logo might end up in this readme.** 😉
**[Donate](https://opencollective.com/verdaccio)** 💵👍🏻 starting from _\$1/month_ or just one single contribution.
## Report a vulnerability
If you want to report a security vulnerability, please follow the steps which we have defined for you in our [security policy](https://github.com/verdaccio/verdaccio/security/policy).
## Open Collective Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/verdaccio#sponsor)]
[![sponsor](https://opencollective.com/verdaccio/sponsor/0/avatar.svg)](https://opencollective.com/verdaccio/sponsor/0/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/1/avatar.svg)](https://opencollective.com/verdaccio/sponsor/1/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/2/avatar.svg)](https://opencollective.com/verdaccio/sponsor/2/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/3/avatar.svg)](https://opencollective.com/verdaccio/sponsor/3/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/4/avatar.svg)](https://opencollective.com/verdaccio/sponsor/4/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/5/avatar.svg)](https://opencollective.com/verdaccio/sponsor/5/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/6/avatar.svg)](https://opencollective.com/verdaccio/sponsor/6/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/7/avatar.svg)](https://opencollective.com/verdaccio/sponsor/7/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/8/avatar.svg)](https://opencollective.com/verdaccio/sponsor/8/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/9/avatar.svg)](https://opencollective.com/verdaccio/sponsor/9/website)
## Open Collective Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/verdaccio#backer)]
[![backers](https://opencollective.com/verdaccio/backers.svg?width=890)](https://opencollective.com/verdaccio#backers)
## Special Thanks
Thanks to the following companies to help us to achieve our goals providing free open source licenses.
[![jetbrain](assets/thanks/jetbrains/logo.png)](https://www.jetbrains.com/)
[![crowdin](assets/thanks/crowdin/logo.png)](https://crowdin.com/)
[![balsamiq](assets/thanks/balsamiq/logo.jpg)](https://balsamiq.com/)
## Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
[![contributors](https://opencollective.com/verdaccio/contributors.svg?width=890&button=true)](../../graphs/contributors)
### FAQ / Contact / Troubleshoot
If you have any issue you can try the following options, do no desist to ask or check our issues database, perhaps someone has asked already what you are looking for.
- [Blog](https://verdaccio.org/blog/)
- [Donations](https://opencollective.com/verdaccio)
- [Reporting an issue](https://github.com/verdaccio/verdaccio/blob/master/CONTRIBUTING.md#reporting-a-bug)
- [Running discussions](https://github.com/verdaccio/verdaccio/issues?q=is%3Aissue+is%3Aopen+label%3Adiscuss)
- [Chat](http://chat.verdaccio.org/)
- [Logos](https://verdaccio.org/docs/en/logo)
- [Docker Examples](https://github.com/verdaccio/docker-examples)
- [FAQ](https://github.com/verdaccio/verdaccio/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Aquestion%20)
### License
Verdaccio is [MIT licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)

@ -19,6 +19,7 @@
"clean": "rimraf ./build",
"lint": "eslint . --ext .js,.ts",
"test": "jest --detectOpenHandles",
"ge:docs": "typedoc src/index.ts --tsconfig tsconfig.build.json --plugin typedoc-plugin-markdown",
"test:debug": "node --inspect-brk ../../node_modules/jest/bin/jest.js --config ./test/jest.config.functional.js --testPathPattern ./test/unit/* --passWithNoTests",
"type-check": "tsc --noEmit -p tsconfig.build.json",
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
@ -58,7 +59,9 @@
"lodash": "4.17.21",
"node-mocks-http": "1.11.0",
"get-port": "5.1.1",
"nock": "13.2.9"
"nock": "13.2.9",
"typedoc-plugin-missing-exports": "1.0.0",
"typedoc-plugin-markdown": "3.13.6"
},
"keywords": [
"private",

@ -4,5 +4,5 @@
"rootDir": "./src",
"outDir": "./build"
},
"include": ["src/**/*.ts"]
"include": ["src/**/*.ts", "types/*.d.ts"]
}

@ -17,7 +17,7 @@
"path": "../config"
},
{
"path": "../core/htpasswd"
"path": "../plugins/htpasswd"
},
{
"path": "../tools/helper"

8
packages/verdaccio/types/patch.d.ts vendored Normal file

@ -0,0 +1,8 @@
declare module 'jest-matcher-utils';
declare module 'pretty-format' {
export type Plugin = any;
export type CompareKeys = any;
}
declare module '@jest/schemas' {
export type SnapshotFormat = any;
}

265
pnpm-lock.yaml generated

@ -1,5 +1,9 @@
lockfileVersion: 5.3
overrides:
got: 11.8.5
p-cancelable: 2.1.1
importers:
.:
@ -258,7 +262,7 @@ importers:
pnpm: next-7
dependencies:
'@verdaccio/test-cli-commons': link:../cli-commons
pnpm: 7.12.2
pnpm: 7.13.3
e2e/cli/e2e-yarn1:
specifiers:
@ -499,12 +503,10 @@ importers:
packages/core/types:
specifiers:
'@types/node': 16.11.62
typedoc: beta
typedoc-plugin-missing-exports: 1.0.0
typedoc: 0.23.15
devDependencies:
'@types/node': 16.11.62
typedoc: 0.23.0-beta.7_typescript@4.8.4
typedoc-plugin-missing-exports: 1.0.0_typedoc@0.23.0-beta.7
typedoc: 0.23.15_typescript@4.8.4
packages/core/url:
specifiers:
@ -656,7 +658,9 @@ importers:
packages/plugins/audit:
specifiers:
'@verdaccio/auth': workspace:6.0.0-6-next.27
'@verdaccio/config': workspace:6.0.0-6-next.48
'@verdaccio/core': workspace:6.0.0-6-next.48
'@verdaccio/logger': workspace:6.0.0-6-next.16
'@verdaccio/types': workspace:11.0.0-6-next.17
body-parser: 1.20.0
@ -666,13 +670,15 @@ importers:
node-fetch: cjs
supertest: 6.2.4
dependencies:
'@verdaccio/config': link:../../config
'@verdaccio/core': link:../../core/core
'@verdaccio/logger': link:../../logger
body-parser: 1.20.0
express: 4.18.1
https-proxy-agent: 5.0.1
node-fetch: 2.6.7
devDependencies:
'@verdaccio/config': link:../../config
'@verdaccio/logger': link:../../logger
'@verdaccio/auth': link:../../auth
'@verdaccio/types': link:../../core/types
nock: 13.2.9
supertest: 6.2.4
@ -956,6 +962,7 @@ importers:
lodash: 4.17.21
nock: 13.2.9
node-mocks-http: 1.11.0
p-cancelable: 2.1.1
semver: 7.3.7
undici: 4.16.0
dependencies:
@ -976,6 +983,7 @@ importers:
get-stream: 6.0.1
nock: 13.2.9
node-mocks-http: 1.11.0
p-cancelable: 2.1.1
semver: 7.3.7
packages/server/express:
@ -1273,6 +1281,8 @@ importers:
lodash: 4.17.21
nock: 13.2.9
node-mocks-http: 1.11.0
typedoc-plugin-markdown: 3.13.6
typedoc-plugin-missing-exports: 1.0.0
verdaccio-audit: workspace:11.0.0-6-next.11
verdaccio-htpasswd: workspace:11.0.0-6-next.18
yaml: 2.1.1
@ -1297,6 +1307,8 @@ importers:
lodash: 4.17.21
nock: 13.2.9
node-mocks-http: 1.11.0
typedoc-plugin-markdown: 3.13.6
typedoc-plugin-missing-exports: 1.0.0
yaml: 2.1.1
packages/web:
@ -1380,8 +1392,10 @@ importers:
docusaurus-plugin-contributors: workspace:1.0.1-6-next.0
docusaurus-plugin-sass: ^0.2.1
docusaurus-plugin-sentry: 1.0.0
docusaurus-plugin-typedoc: latest
esbuild: 0.14.10
esbuild-loader: 2.16.0
p-cancelable: 2.1.1
prism-react-renderer: ^1.2.1
react: 17.0.2
react-dom: 17.0.2
@ -1389,6 +1403,9 @@ importers:
react-twitter-widgets: ^1.10.0
sass: 1.55.0
sass-loader: ^12.1.0
typedoc: 0.23.15
typedoc-github-wiki-theme: ^1.0.1
typedoc-plugin-markdown: 3.13.6
url-loader: 4.1.1
use-is-in-viewport: ^1.0.9
usehooks-ts: 2.7.1
@ -1409,10 +1426,14 @@ importers:
copy-text-to-clipboard: 3.0.1
docusaurus-plugin-contributors: link:../packages/tools/docusaurus-plugin-contributors
docusaurus-plugin-sentry: 1.0.0_6cc73cc048a6f0dd8d2f9ff95b1ea0d9
docusaurus-plugin-typedoc: 0.17.5_fe401e7e42cf7649fa36d66d5c1ce51f
p-cancelable: 2.1.1
react: 17.0.2
react-dom: 17.0.2_react@17.0.2
react-player: 2.11.0_react@17.0.2
react-twitter-widgets: 1.10.0_react@17.0.2
typedoc: 0.23.15_typescript@4.8.4
typedoc-plugin-markdown: 3.13.6_typedoc@0.23.15
use-is-in-viewport: 1.0.9_react@17.0.2
usehooks-ts: 2.7.1_react-dom@17.0.2+react@17.0.2
devDependencies:
@ -1425,6 +1446,7 @@ importers:
prism-react-renderer: 1.2.1_react@17.0.2
sass: 1.55.0
sass-loader: 12.1.0_sass@1.55.0
typedoc-github-wiki-theme: 1.0.1_fe401e7e42cf7649fa36d66d5c1ce51f
url-loader: 4.1.1
packages:
@ -5953,7 +5975,7 @@ packages:
wait-on: 6.0.1_debug@4.3.4
webpack: 5.74.0_esbuild@0.14.10
webpack-bundle-analyzer: 4.6.1
webpack-dev-server: 4.9.3_webpack@5.74.0
webpack-dev-server: 4.9.3_debug@4.3.4+webpack@5.74.0
webpack-merge: 5.8.0
webpackbar: 5.0.2_webpack@5.74.0
transitivePeerDependencies:
@ -6050,7 +6072,7 @@ packages:
wait-on: 6.0.1_debug@4.3.4
webpack: 5.74.0_esbuild@0.14.10
webpack-bundle-analyzer: 4.6.1
webpack-dev-server: 4.9.3_webpack@5.74.0
webpack-dev-server: 4.9.3_debug@4.3.4+webpack@5.74.0
webpack-merge: 5.8.0
webpackbar: 5.0.2_webpack@5.74.0
transitivePeerDependencies:
@ -8352,10 +8374,6 @@ packages:
/@sinclair/typebox/0.24.34:
resolution: {integrity: sha512-x3ejWKw7rpy30Bvm6U0AQMOHdjqe2E3YJrBHlTxH0KFsp77bBa+MH324nJxtXZFpnTy/JW2h5HPYVm0vG2WPnw==}
/@sindresorhus/is/0.14.0:
resolution: {integrity: sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==}
engines: {node: '>=6'}
/@sindresorhus/is/4.6.0:
resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
engines: {node: '>=10'}
@ -8624,12 +8642,6 @@ packages:
transitivePeerDependencies:
- supports-color
/@szmarczak/http-timer/1.1.2:
resolution: {integrity: sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==}
engines: {node: '>=6'}
dependencies:
defer-to-connect: 1.1.3
/@szmarczak/http-timer/4.0.6:
resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
engines: {node: '>=10'}
@ -9162,7 +9174,7 @@ packages:
dependencies:
'@types/prop-types': 15.7.5
'@types/scheduler': 0.16.2
csstype: 3.1.0
csstype: 3.1.1
/@types/redux/3.6.0:
resolution: {integrity: sha1-8evh5UEVGAcuT9/KXHbhbnTBOZo=}
@ -10294,7 +10306,7 @@ packages:
/axios/0.21.1_debug@4.3.4:
resolution: {integrity: sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==}
dependencies:
follow-redirects: 1.14.9_debug@4.3.4
follow-redirects: 1.14.9_debug@4.3.3
transitivePeerDependencies:
- debug
dev: false
@ -10302,7 +10314,7 @@ packages:
/axios/0.21.3_debug@4.3.4:
resolution: {integrity: sha512-JtoZ3Ndke/+Iwt5n+BgSli/3idTvpt5OjKyoCmz4LX5+lPiY5l7C1colYezhlxThjNa/NhngCUWZSZFypIFuaA==}
dependencies:
follow-redirects: 1.14.9_debug@4.3.4
follow-redirects: 1.14.9_debug@4.3.3
transitivePeerDependencies:
- debug
dev: false
@ -10310,7 +10322,7 @@ packages:
/axios/0.25.0_debug@4.3.4:
resolution: {integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==}
dependencies:
follow-redirects: 1.14.9_debug@4.3.4
follow-redirects: 1.14.9_debug@4.3.3
transitivePeerDependencies:
- debug
@ -10794,7 +10806,6 @@ packages:
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
dependencies:
balanced-match: 1.0.2
dev: true
/braces/2.3.2:
resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==}
@ -10952,18 +10963,6 @@ packages:
resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==}
engines: {node: '>=10.6.0'}
/cacheable-request/6.1.0:
resolution: {integrity: sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==}
engines: {node: '>=8'}
dependencies:
clone-response: 1.0.2
get-stream: 5.2.0
http-cache-semantics: 4.1.0
keyv: 3.1.0
lowercase-keys: 2.0.0
normalize-url: 4.5.1
responselike: 1.0.2
/cacheable-request/7.0.2:
resolution: {integrity: sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==}
engines: {node: '>=8'}
@ -12460,12 +12459,6 @@ packages:
resolution: {integrity: sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=}
engines: {node: '>=0.10'}
/decompress-response/3.3.0:
resolution: {integrity: sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=}
engines: {node: '>=4'}
dependencies:
mimic-response: 1.0.1
/decompress-response/6.0.0:
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
engines: {node: '>=10'}
@ -12515,9 +12508,6 @@ packages:
clone: 1.0.4
dev: true
/defer-to-connect/1.1.3:
resolution: {integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==}
/defer-to-connect/2.0.1:
resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==}
engines: {node: '>=10'}
@ -12767,6 +12757,16 @@ packages:
- webpack-cli
dev: false
/docusaurus-plugin-typedoc/0.17.5_fe401e7e42cf7649fa36d66d5c1ce51f:
resolution: {integrity: sha512-mMTk4lRy2+wQ7fmMOv6RLfKkoGnHkBLE8qUoPfWFoqUYDDDInwVQKxz12FNnQx86eJSLgBiZmuY/zB/bYsZQlQ==}
peerDependencies:
typedoc: '>=0.22.0'
typedoc-plugin-markdown: '>=3.11.10'
dependencies:
typedoc: 0.23.15_typescript@4.8.4
typedoc-plugin-markdown: 3.13.6_typedoc@0.23.15
dev: false
/dom-accessibility-api/0.5.9:
resolution: {integrity: sha512-+KPF4o71fl6NrdnqIrJc6m44NA+Rhf1h7In2MRznejSQasWkjqmHOBUlk+pXJ77cVOSYyZeNHFwn/sjotB6+Sw==}
dev: true
@ -12888,9 +12888,6 @@ packages:
/duplexer/0.1.2:
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
/duplexer3/0.1.4:
resolution: {integrity: sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=}
/eastasianwidth/0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
@ -14337,9 +14334,16 @@ packages:
transitivePeerDependencies:
- encoding
/follow-redirects/1.14.9:
/follow-redirects/1.14.9_debug@4.3.3:
resolution: {integrity: sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
dependencies:
debug: 4.3.3_supports-color@6.1.0
/follow-redirects/1.14.9_debug@4.3.4:
resolution: {integrity: sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==}
@ -14783,24 +14787,6 @@ packages:
p-cancelable: 2.1.1
responselike: 2.0.0
/got/9.6.0:
resolution: {integrity: sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==}
engines: {node: '>=8.6'}
dependencies:
'@sindresorhus/is': 0.14.0
'@szmarczak/http-timer': 1.1.2
'@types/keyv': 3.1.4
'@types/responselike': 1.0.0
cacheable-request: 6.1.0
decompress-response: 3.3.0
duplexer3: 0.1.4
get-stream: 4.1.0
lowercase-keys: 1.0.1
mimic-response: 1.0.1
p-cancelable: 1.1.0
to-readable-stream: 1.0.0
url-parse-lax: 3.0.0
/graceful-fs/4.2.6:
resolution: {integrity: sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==}
dev: true
@ -14853,7 +14839,6 @@ packages:
wordwrap: 1.0.0
optionalDependencies:
uglify-js: 3.12.4
dev: false
/hard-rejection/2.1.0:
resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==}
@ -15264,18 +15249,19 @@ packages:
- supports-color
dev: true
/http-proxy-middleware/0.19.1_supports-color@6.1.0:
/http-proxy-middleware/0.19.1_debug@4.3.3+supports-color@6.1.0:
resolution: {integrity: sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==}
engines: {node: '>=4.0.0'}
dependencies:
http-proxy: 1.18.1
http-proxy: 1.18.1_debug@4.3.3
is-glob: 4.0.3
lodash: 4.17.21
micromatch: 3.1.10_supports-color@6.1.0
transitivePeerDependencies:
- debug
- supports-color
/http-proxy-middleware/2.0.3_@types+express@4.17.13:
/http-proxy-middleware/2.0.3_adbe487640bba2b97136947cd1213f1b:
resolution: {integrity: sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA==}
engines: {node: '>=12.0.0'}
peerDependencies:
@ -15286,18 +15272,32 @@ packages:
dependencies:
'@types/express': 4.17.13
'@types/http-proxy': 1.17.8
http-proxy: 1.18.1
http-proxy: 1.18.1_debug@4.3.4
is-glob: 4.0.3
is-plain-obj: 3.0.0
micromatch: 4.0.5
transitivePeerDependencies:
- debug
/http-proxy/1.18.1:
/http-proxy/1.18.1_debug@4.3.3:
resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==}
engines: {node: '>=8.0.0'}
dependencies:
eventemitter3: 4.0.6
follow-redirects: 1.14.9
follow-redirects: 1.14.9_debug@4.3.3
requires-port: 1.0.0
transitivePeerDependencies:
- debug
/http-proxy/1.18.1_debug@4.3.4:
resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==}
engines: {node: '>=8.0.0'}
dependencies:
eventemitter3: 4.0.6
follow-redirects: 1.14.9_debug@4.3.4
requires-port: 1.0.0
transitivePeerDependencies:
- debug
/http-status-codes/2.2.0:
resolution: {integrity: sha512-feERVo9iWxvnejp3SEfm/+oNG517npqL2/PIA8ORjyOZjGC7TwCRQsZylciLS64i6pJ0wRYz3rkXLRwbtFa8Ng==}
@ -16661,9 +16661,6 @@ packages:
engines: {node: '>=4'}
hasBin: true
/json-buffer/3.0.0:
resolution: {integrity: sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=}
/json-buffer/3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
@ -16717,7 +16714,6 @@ packages:
/jsonc-parser/3.1.0:
resolution: {integrity: sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==}
dev: true
/jsonfile/4.0.0:
resolution: {integrity: sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=}
@ -16846,11 +16842,6 @@ packages:
tsscmp: 1.0.6
dev: false
/keyv/3.1.0:
resolution: {integrity: sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==}
dependencies:
json-buffer: 3.0.0
/keyv/4.1.1:
resolution: {integrity: sha512-tGv1yP6snQVDSM4X6yxrv2zzq/EvpW+oYiUz6aueW1u9CtS8RzUQYxxmFwgZlO2jSgCxQbchhxaqXXp2hnKGpQ==}
dependencies:
@ -17220,10 +17211,6 @@ packages:
dependencies:
tslib: 2.4.0
/lowercase-keys/1.0.1:
resolution: {integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==}
engines: {node: '>=0.10.0'}
/lowercase-keys/2.0.0:
resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==}
engines: {node: '>=8'}
@ -17326,11 +17313,10 @@ packages:
hasBin: true
dev: false
/marked/4.0.18:
resolution: {integrity: sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==}
/marked/4.1.1:
resolution: {integrity: sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==}
engines: {node: '>= 12'}
hasBin: true
dev: true
/mathml-tag-names/2.1.3:
resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==}
@ -18003,7 +17989,6 @@ packages:
engines: {node: '>=10'}
dependencies:
brace-expansion: 2.0.1
dev: true
/minimist-options/4.1.0:
resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
@ -18364,10 +18349,6 @@ packages:
resolution: {integrity: sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=}
engines: {node: '>=0.10.0'}
/normalize-url/4.5.1:
resolution: {integrity: sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==}
engines: {node: '>=8'}
/normalize-url/6.1.0:
resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==}
engines: {node: '>=10'}
@ -19019,10 +19000,6 @@ packages:
resolution: {integrity: sha512-yeWM9k6UPfG/nzxdaPlJkB2p08hCg4xP6Lx99F+vP8YF7xyZVfTmJjrrNalkmzudD4WFvNLVudQikqUmF8zhVQ==}
dev: true
/p-cancelable/1.1.0:
resolution: {integrity: sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==}
engines: {node: '>=6'}
/p-cancelable/2.1.1:
resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==}
engines: {node: '>=8'}
@ -19118,7 +19095,7 @@ packages:
resolution: {integrity: sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==}
engines: {node: '>=8'}
dependencies:
got: 9.6.0
got: 11.8.5
registry-auth-token: 4.2.1
registry-url: 5.1.0
semver: 6.3.0
@ -19382,8 +19359,8 @@ packages:
hasBin: true
dev: false
/pnpm/7.12.2:
resolution: {integrity: sha512-8QvnKANKN+YZXDmVYGI7zRJysdKldZI+w3AYnxu9IwtnLv1x6WuzrJr0nxMcTeuUAT908RjDqK+/6KJB9wNqxA==}
/pnpm/7.13.3:
resolution: {integrity: sha512-6avqSfzfAr/9w1ZleaMI276ZuZUu88eOIe6v2mTCuwtSjUEqheboH1G4m7jgF+4arMUfnBrz371UAU+DCeCiSA==}
engines: {node: '>=14.6'}
hasBin: true
dev: false
@ -20194,10 +20171,6 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
/prepend-http/2.0.0:
resolution: {integrity: sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=}
engines: {node: '>=4'}
/prettier-linter-helpers/1.0.0:
resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==}
engines: {node: '>=6.0.0'}
@ -21340,11 +21313,6 @@ packages:
path-parse: 1.0.7
dev: false
/responselike/1.0.2:
resolution: {integrity: sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=}
dependencies:
lowercase-keys: 1.0.1
/responselike/2.0.0:
resolution: {integrity: sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==}
dependencies:
@ -21830,13 +21798,12 @@ packages:
interpret: 1.4.0
rechoir: 0.6.2
/shiki/0.10.1:
resolution: {integrity: sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==}
/shiki/0.11.1:
resolution: {integrity: sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==}
dependencies:
jsonc-parser: 3.1.0
vscode-oniguruma: 1.6.2
vscode-textmate: 5.2.0
dev: true
vscode-textmate: 6.0.0
/side-channel/1.0.4:
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
@ -22937,10 +22904,6 @@ packages:
dependencies:
kind-of: 3.2.2
/to-readable-stream/1.0.0:
resolution: {integrity: sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==}
engines: {node: '>=6'}
/to-regex-range/2.1.1:
resolution: {integrity: sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=}
engines: {node: '>=0.10.0'}
@ -23195,27 +23158,50 @@ packages:
dependencies:
is-typedarray: 1.0.0
/typedoc-plugin-missing-exports/1.0.0_typedoc@0.23.0-beta.7:
/typedoc-github-wiki-theme/1.0.1_fe401e7e42cf7649fa36d66d5c1ce51f:
resolution: {integrity: sha512-FaO7fENGK6IJLpkddbNXxJfNbooF9KBC7xfk7Lj4uqG5SCC7YQFPTLDyNmbpJKO93QEenRYgqBwI5E5d/bKrHw==}
peerDependencies:
typedoc: '>=0.22.9'
typedoc-plugin-markdown: '>=3.11.10'
dependencies:
typedoc: 0.23.15_typescript@4.8.4
typedoc-plugin-markdown: 3.13.6_typedoc@0.23.15
dev: true
/typedoc-plugin-markdown/3.13.6:
resolution: {integrity: sha512-ISSc9v3BK7HkokxSBuJPttXox4tJ6hP0N9wfSIk0fmLN67+eqtAxbk97gs2nDiuha+RTO5eW9gdeAb+RPP0mgg==}
peerDependencies:
typedoc: '>=0.23.0'
dependencies:
handlebars: 4.7.7
dev: true
/typedoc-plugin-markdown/3.13.6_typedoc@0.23.15:
resolution: {integrity: sha512-ISSc9v3BK7HkokxSBuJPttXox4tJ6hP0N9wfSIk0fmLN67+eqtAxbk97gs2nDiuha+RTO5eW9gdeAb+RPP0mgg==}
peerDependencies:
typedoc: '>=0.23.0'
dependencies:
handlebars: 4.7.7
typedoc: 0.23.15_typescript@4.8.4
/typedoc-plugin-missing-exports/1.0.0:
resolution: {integrity: sha512-7s6znXnuAj1eD9KYPyzVzR1lBF5nwAY8IKccP5sdoO9crG4lpd16RoFpLsh2PccJM+I2NASpr0+/NMka6ThwVA==}
peerDependencies:
typedoc: 0.22.x || 0.23.x
dependencies:
typedoc: 0.23.0-beta.7_typescript@4.8.4
dev: true
/typedoc/0.23.0-beta.7_typescript@4.8.4:
resolution: {integrity: sha512-k8GKXXY4z3HIs7HdSu92jcze1nl71cLiHR329ZflhiO4Ta1rJc4F5uEtwUjCSChXFQaVZUI2l3VaF9nWm1/p7A==}
/typedoc/0.23.15_typescript@4.8.4:
resolution: {integrity: sha512-x9Zu+tTnwxb9YdVr+zvX7LYzyBl1nieOr6lrSHbHsA22/RJK2m4Y525WIg5Mj4jWCmfL47v6f4hUzY7EIuwS5w==}
engines: {node: '>= 14.14'}
hasBin: true
peerDependencies:
typescript: 4.6.x || 4.7.x
typescript: 4.6.x || 4.7.x || 4.8.x
dependencies:
lunr: 2.3.9
marked: 4.0.18
marked: 4.1.1
minimatch: 5.1.0
shiki: 0.10.1
shiki: 0.11.1
typescript: 4.8.4
dev: true
/typescript/4.8.4:
resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==}
@ -23230,7 +23216,6 @@ packages:
engines: {node: '>=0.8.0'}
hasBin: true
requiresBuild: true
dev: false
optional: true
/unbox-primitive/1.0.2:
@ -23620,12 +23605,6 @@ packages:
webpack: 5.74.0_webpack-cli@4.7.2
dev: true
/url-parse-lax/3.0.0:
resolution: {integrity: sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=}
engines: {node: '>=4'}
dependencies:
prepend-http: 2.0.0
/url-parse/1.5.1:
resolution: {integrity: sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==}
dependencies:
@ -23867,11 +23846,9 @@ packages:
/vscode-oniguruma/1.6.2:
resolution: {integrity: sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==}
dev: true
/vscode-textmate/5.2.0:
resolution: {integrity: sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==}
dev: true
/vscode-textmate/6.0.0:
resolution: {integrity: sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==}
/w3c-hr-time/1.0.2:
resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==}
@ -24144,7 +24121,7 @@ packages:
del: 4.1.1
express: 4.17.1_supports-color@6.1.0
html-entities: 1.3.1
http-proxy-middleware: 0.19.1_supports-color@6.1.0
http-proxy-middleware: 0.19.1_debug@4.3.3+supports-color@6.1.0
import-local: 2.0.0
internal-ip: 4.3.0
ip: 1.1.5
@ -24194,7 +24171,7 @@ packages:
del: 4.1.1
express: 4.17.1_supports-color@6.1.0
html-entities: 1.3.1
http-proxy-middleware: 0.19.1_supports-color@6.1.0
http-proxy-middleware: 0.19.1_debug@4.3.3+supports-color@6.1.0
import-local: 2.0.0
internal-ip: 4.3.0
ip: 1.1.5
@ -24224,7 +24201,7 @@ packages:
- utf-8-validate
dev: false
/webpack-dev-server/4.9.3_webpack@5.74.0:
/webpack-dev-server/4.9.3_debug@4.3.4+webpack@5.74.0:
resolution: {integrity: sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw==}
engines: {node: '>= 12.13.0'}
hasBin: true
@ -24252,7 +24229,7 @@ packages:
express: 4.18.1
graceful-fs: 4.2.9
html-entities: 2.3.2
http-proxy-middleware: 2.0.3_@types+express@4.17.13
http-proxy-middleware: 2.0.3_adbe487640bba2b97136947cd1213f1b
ipaddr.js: 2.0.1
open: 8.4.0
p-retry: 4.6.1
@ -24267,6 +24244,7 @@ packages:
ws: 8.8.0
transitivePeerDependencies:
- bufferutil
- debug
- supports-color
- utf-8-validate
@ -24655,7 +24633,6 @@ packages:
/wordwrap/1.0.0:
resolution: {integrity: sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=}
dev: false
/worker-rpc/0.1.1:
resolution: {integrity: sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==}

@ -14,6 +14,7 @@
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
},
"include": ["src/**/*.ts", "types/*.d.ts"],
"exclude": [
"**/build",
"node_modules",

@ -4,6 +4,7 @@
"preserveSymlinks": true,
"composite": true,
"incremental": true,
"declarationMap": true
"declarationMap": true,
"removeComments": false
}
}

12
types/patch.d.ts vendored Normal file

@ -0,0 +1,12 @@
declare module 'jest-matcher-utils';
declare module 'pretty-format' {
export type Plugin = any;
export type CompareKeys = any;
}
declare module '@jest/schemas' {
export type SnapshotFormat = any;
}
// declare module '@szmarczak/http-timer';
// declare module 'cacheable-lookup';
// // declare module 'p-cancelable';

@ -0,0 +1,3 @@
# Verdaccio API
TBA

@ -7,9 +7,9 @@ Verdaccio is a Node.js private and proxy registry. To install it, you need a few
## Prerequisites {#prerequisites}
1. **Node.js** `v12` or higher.
1. **Node.js** `v16` or higher.
2. Your favorite Node Package Manager `npm`, `pnpm` or `yarn` (classic and berry).
2. Your favorite Node Package Manager `npm`, `pnpm` or `yarn` (classic and modern).
> 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.
@ -17,8 +17,6 @@ Verdaccio is a Node.js private and proxy registry. To install it, you need a few
> 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.
@ -34,10 +32,10 @@ Learn the basics before getting started, how to install, where is the location o
Using `npm`
```bash
npm install --location=global verdaccio
npm install --location=global verdaccio@6-next
```
or using `yarn`
or using `yarn@1.x` _classic_,
```bash
yarn global add verdaccio
@ -51,30 +49,17 @@ 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 --location=global verdaccio@6-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
info -=- local storage path /Users/user/.local/share/verdaccio/storage/.verdaccio-db.json
info --- using htpasswd file: /Users/user/.config/verdaccio/htpasswd
info --- http address http://localhost:4873/
info --- version: 6.0.0-6-next.48
info --- server started
```
For more information about the CLI, please [read the cli section](cli.md).
@ -118,7 +103,7 @@ If you'd like a broader explanation, don't miss the tutorial created by [thedevl
## Docker Image {#docker-image}
```bash
docker run -it --rm --name verdaccio -p 4873:4873 verdaccio/verdaccio
docker run -it --rm --name verdaccio -p 4873:4873 verdaccio/verdaccio:nightly-master
```
`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.
@ -128,17 +113,5 @@ docker run -it --rm --name verdaccio -p 4873:4873 verdaccio/verdaccio
```bash
$ helm repo add verdaccio https://charts.verdaccio.org
$ helm repo update
$ helm install verdaccio/verdaccio
$ helm install registry --set image.tag=nightly-master 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)

@ -0,0 +1,16 @@
---
id: third-party
title: "Third-party Integrations"
---
## 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)

@ -62,8 +62,68 @@ module.exports = {
plugins: [
'docusaurus-plugin-sass',
"docusaurus-plugin-contributors",
isProductionDeployment && typeof process.env.SENTRY_KEY === 'string' && ['docusaurus-plugin-sentry', { DSN: process.env.SENTRY_KEY }]
].filter(Boolean),
isProductionDeployment && typeof process.env.SENTRY_KEY === 'string' && ['docusaurus-plugin-sentry', { DSN: process.env.SENTRY_KEY }],
[
'docusaurus-plugin-typedoc',
{
entryPoints: ['../packages/node-api/src/index.ts'],
tsconfig: '../packages/node-api/tsconfig.build.json',
id: 'api/node-api',
out: 'api/node-api',
// theme: 'default',
excludePrivate: false,
excludeProtected: true,
categorizeByGroup: false,
excludeInternal: true,
sidebar: {
categoryLabel: '@verdaccio/node-api',
// position: 1,
fullNames: true
},
},
],
[
'docusaurus-plugin-typedoc',
{
entryPoints: ['../packages/config/src/index.ts'],
tsconfig: '../packages/config/tsconfig.build.json',
id: 'api/config',
out: 'api/config',
sidebar: {
categoryLabel: '@verdaccio/config',
fullNames: true
},
},
],
[
'docusaurus-plugin-typedoc',
{
entryPoints: ['../packages/core/core/src/index.ts'],
tsconfig: '../packages/core/core/tsconfig.build.json',
id: 'api/core',
out: 'api/core',
sidebar: {
categoryLabel: '@verdaccio/core',
fullNames: true
},
},
],
[
'docusaurus-plugin-typedoc',
{
entryPoints: ['../packages/core/types/src/types.ts'],
tsconfig: '../packages/core/types/tsconfig.build.json',
id: 'api/types',
out: 'api/types',
categorizeByGroup: false,
includeVersion: true,
sidebar: {
categoryLabel: '@verdaccio/types',
fullNames: true
},
},
],
],
webpack: {
jsLoader: (isServer) => ({
loader: require.resolve('esbuild-loader'),
@ -111,6 +171,12 @@ module.exports = {
position: 'left',
label: 'Docs',
},
{
type: 'doc',
docId: 'api/node-api/index',
position: 'left',
label: 'API'
},
{ to: '/blog', label: 'Blog', position: 'left' },
{ to: '/help', label: 'Help', position: 'left' },
{
@ -265,7 +331,7 @@ module.exports = {
},
blog: {
blogTitle: 'Verdaccio Official Blog',
blogDescription: 'The official Verdaccio NPM proxy registry blog',
blogDescription: 'The official Verdaccio Node.js proxy registry blog',
showReadingTime: true,
postsPerPage: 3,
feedOptions: {

@ -4,7 +4,7 @@
"version": "5.15.4",
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"start": "docusaurus start --no-open",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
@ -22,27 +22,31 @@
},
"dependencies": {
"@docusaurus/core": "2.1.0",
"@docusaurus/plugin-content-docs": "2.1.0",
"@docusaurus/plugin-google-analytics": "2.1.0",
"@docusaurus/preset-classic": "2.1.0",
"@docusaurus/remark-plugin-npm2yarn": "2.1.0",
"@docusaurus/theme-search-algolia": "2.1.0",
"@docusaurus/plugin-content-docs": "2.1.0",
"@docusaurus/theme-common": "2.1.0",
"@mui/material": "5.10.7",
"@mui/icons-material": "5.10.6",
"@mui/styles": "5.10.7",
"@docusaurus/theme-search-algolia": "2.1.0",
"@mdx-js/react": "^1.6.22",
"clsx": "1.2.1",
"@mui/icons-material": "5.10.6",
"@mui/material": "5.10.7",
"@mui/styles": "5.10.7",
"classnames": "2.3.2",
"clsx": "1.2.1",
"copy-text-to-clipboard": "3.0.1",
"docusaurus-plugin-contributors": "workspace:1.0.1-6-next.0",
"docusaurus-plugin-sentry": "1.0.0",
"docusaurus-plugin-typedoc": "latest",
"react": "17.0.2",
"react-player": "2.11.0",
"p-cancelable": "2.1.1",
"react-dom": "17.0.2",
"usehooks-ts": "2.7.1",
"react-player": "2.11.0",
"react-twitter-widgets": "^1.10.0",
"use-is-in-viewport": "^1.0.9"
"typedoc": "0.23.15",
"typedoc-plugin-markdown": "3.13.6",
"use-is-in-viewport": "^1.0.9",
"usehooks-ts": "2.7.1"
},
"browserslist": {
"production": [
@ -66,6 +70,7 @@
"prism-react-renderer": "^1.2.1",
"sass": "1.55.0",
"sass-loader": "^12.1.0",
"typedoc-github-wiki-theme": "^1.0.1",
"url-loader": "4.1.1"
}
}

@ -1,15 +1,4 @@
// @ts-check
/**
* Creating a sidebar enables you to:
- create an ordered group of docs
- render a sidebar for each doc of that group
- provide next/previous navigation
The sidebars can be generated from the filesystem, or explicitly defined here.
Create as many sidebars as you want.
*/
module.exports = {
// By default, Docusaurus generates a sidebar from the docs folder structure
docs: [
@ -17,8 +6,8 @@ module.exports = {
type: "category",
label: "Introduction",
items: [
"what-is-verdaccio",
"installation",
"what-is-verdaccio",
"cli",
{
type: "category",
@ -33,10 +22,11 @@ module.exports = {
"verdaccio-programmatically",
"security-policy",
"logo",
"third-party",
{
type: "category",
label: "Uses Cases",
items: ["caching", "github-actions", "linking-remote-registry"]
items: ["caching", "linking-remote-registry"]
},
{
type: "category",
@ -106,5 +96,17 @@ module.exports = {
label: "Guides",
items: ["aws"]
}
],
api: [
{
type: 'category',
label: 'API Reference',
items: [
{
type: 'autogenerated',
dirName: 'api'
}
]
}
]
};

@ -1,8 +1,14 @@
{
"extends": "@tsconfig/docusaurus/tsconfig.json",
"extends": "../tsconfig.base.json",
"compilerOptions": {
"allowJs": true,
"esModuleInterop": true,
"jsx": "react",
"lib": ["DOM"],
"noEmit": true,
"noImplicitAny": false,
"types": ["node", "@docusaurus/module-type-aliases"],
"downlevelIteration": true,
"plugins": [{ "name": "typescript-plugin-css-modules" }]
},
"include": ["src/**/*"]
}
}

8
website/types/patch.d.ts vendored Normal file

@ -0,0 +1,8 @@
declare module 'jest-matcher-utils';
declare module 'pretty-format' {
export type Plugin = any;
export type CompareKeys = any;
}
declare module '@jest/schemas' {
export type SnapshotFormat = any;
}

@ -0,0 +1,5 @@
# 5.x API
Go to [Node-API](../../node-api.md).