mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-30 22:34:10 -05:00
feat: upgrade to pino 8 with async logging (#3308)
This commit is contained in:
parent
9bff9045f8
commit
a3a209b5e2
44 changed files with 1334 additions and 1103 deletions
12
.changeset/clever-pugs-warn.md
Normal file
12
.changeset/clever-pugs-warn.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
'@verdaccio/cli': major
|
||||
'@verdaccio/core': major
|
||||
'@verdaccio/types': major
|
||||
'@verdaccio/logger': major
|
||||
'@verdaccio/logger-prettify': major
|
||||
'verdaccio-audit': major
|
||||
'@verdaccio/eslint-config': major
|
||||
'@verdaccio/mock': major
|
||||
---
|
||||
|
||||
feat: migrate to pino.js 8
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -46,7 +46,8 @@ api-results.json
|
|||
hyper-results.json
|
||||
hyper-results*.json
|
||||
api-results*.json
|
||||
.clinic/
|
||||
|
||||
#docs
|
||||
./api
|
||||
packages/core/core/docs
|
||||
**/docs/**
|
||||
|
|
|
@ -2,9 +2,8 @@ import { Command, Option } from 'clipanion';
|
|||
|
||||
import { findConfigFile, parseConfigFile } from '@verdaccio/config';
|
||||
import { logger, setup } from '@verdaccio/logger';
|
||||
import { LoggerConfigItem } from '@verdaccio/logger';
|
||||
import { initServer } from '@verdaccio/node-api';
|
||||
import { ConfigYaml } from '@verdaccio/types';
|
||||
import { ConfigYaml, LoggerConfigItem } from '@verdaccio/types';
|
||||
|
||||
export const DEFAULT_PROCESS_NAME: string = 'verdaccio';
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ const verdaccioDeprecation = 'VerdaccioDeprecation';
|
|||
|
||||
export enum Codes {
|
||||
VERWAR001 = 'VERWAR001',
|
||||
VERWAR002 = 'VERWAR002',
|
||||
VERWAR003 = 'VERWAR003',
|
||||
VERWAR004 = 'VERWAR004',
|
||||
// deprecation warnings
|
||||
|
@ -19,8 +18,6 @@ warningInstance.create(
|
|||
`Verdaccio doesn't need superuser privileges. don't run it under root`
|
||||
);
|
||||
|
||||
warningInstance.create(verdaccioWarning, Codes.VERWAR002, 'logger is not defined');
|
||||
|
||||
warningInstance.create(
|
||||
verdaccioWarning,
|
||||
Codes.VERWAR003,
|
||||
|
|
|
@ -1,30 +1,8 @@
|
|||
# TypeScript types for Verdaccio
|
||||
# @verdaccio/types
|
||||
|
||||
TypeScript definitions for Verdaccio plugins and internal code.
|
||||
|
||||
# TypeScript
|
||||
|
||||
For usage with the library, the `tsconfig.json` should looks like this.
|
||||
|
||||
```json5
|
||||
// tsconfig.json
|
||||
{
|
||||
compilerOptions: {
|
||||
target: 'esnext',
|
||||
module: 'commonjs',
|
||||
declaration: true,
|
||||
noImplicitAny: false,
|
||||
strict: true,
|
||||
outDir: 'lib',
|
||||
allowSyntheticDefaultImports: true,
|
||||
esModuleInterop: true,
|
||||
typeRoots: ['./node_modules/@verdaccio/types/lib/verdaccio', './node_modules/@types'],
|
||||
},
|
||||
include: ['src/*.ts', 'types/*.d.ts'],
|
||||
}
|
||||
```
|
||||
|
||||
### Imports
|
||||
### Usage
|
||||
|
||||
```ts
|
||||
import type {ILocalData, LocalStorage, Logger, Config} from '@verdaccio/types';
|
||||
|
@ -38,3 +16,11 @@ class LocalData implements ILocalData {
|
|||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Run docs
|
||||
|
||||
Generate the package types documentation at `./docs` folder.
|
||||
|
||||
```bash
|
||||
pnpm build:docs
|
||||
```
|
||||
|
|
694
packages/core/types/index.d.ts
vendored
694
packages/core/types/index.d.ts
vendored
|
@ -1,694 +0,0 @@
|
|||
/// <reference types="node" />
|
||||
import { PassThrough, PipelinePromise, Readable, Stream, Writable } from 'stream';
|
||||
|
||||
declare module '@verdaccio/types' {
|
||||
type StringValue = string | void | null;
|
||||
|
||||
type StorageList = string[];
|
||||
type Callback = Function;
|
||||
// FIXME: err should be something flexible enough for any implementation
|
||||
type CallbackAction = (err: any | null) => void;
|
||||
interface Author {
|
||||
username?: string;
|
||||
name: string;
|
||||
email?: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
type PackageManagers = 'pnpm' | 'yarn' | 'npm';
|
||||
|
||||
// FUTURE: WebConf and TemplateUIOptions should be merged .
|
||||
type CommonWebConf = {
|
||||
title?: string;
|
||||
logo?: string;
|
||||
favicon?: string;
|
||||
gravatar?: boolean;
|
||||
sort_packages?: string;
|
||||
darkMode?: boolean;
|
||||
url_prefix?: string;
|
||||
language?: string;
|
||||
login?: boolean;
|
||||
scope?: string;
|
||||
pkgManagers?: PackageManagers[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Options are passed to the index.html
|
||||
*/
|
||||
export type TemplateUIOptions = {
|
||||
uri?: string;
|
||||
darkMode?: boolean;
|
||||
protocol?: string;
|
||||
host?: string;
|
||||
// deprecated
|
||||
basename?: string;
|
||||
scope?: string;
|
||||
showInfo?: boolean;
|
||||
showSettings?: boolean;
|
||||
showSearch?: boolean;
|
||||
showFooter?: boolean;
|
||||
showThemeSwitch?: boolean;
|
||||
showDownloadTarball?: boolean;
|
||||
showRaw?: boolean;
|
||||
base: string;
|
||||
primaryColor?: string;
|
||||
version?: string;
|
||||
logoURI?: string;
|
||||
flags: FlagsConfig;
|
||||
} & CommonWebConf;
|
||||
|
||||
/**
|
||||
* Options on config.yaml for web
|
||||
*/
|
||||
type WebConf = {
|
||||
// FIXME: rename to primaryColor and move it to CommonWebConf
|
||||
primary_color?: string;
|
||||
enable?: boolean;
|
||||
scriptsHead?: string[];
|
||||
scriptsBodyAfter?: string[];
|
||||
metaScripts?: string[];
|
||||
bodyBefore?: string[];
|
||||
bodyAfter?: string[];
|
||||
} & CommonWebConf;
|
||||
|
||||
interface Signatures {
|
||||
keyid: string;
|
||||
sig: string;
|
||||
}
|
||||
|
||||
interface Dist {
|
||||
'npm-signature'?: string;
|
||||
signatures?: Signatures[];
|
||||
fileCount?: number;
|
||||
integrity?: string;
|
||||
shasum: string;
|
||||
unpackedSize?: number;
|
||||
tarball: string;
|
||||
}
|
||||
|
||||
interface RemoteUser {
|
||||
real_groups: string[];
|
||||
groups: string[];
|
||||
name: string | void;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
interface LocalStorage {
|
||||
list: any;
|
||||
secret: string;
|
||||
}
|
||||
|
||||
interface Version {
|
||||
name: string;
|
||||
version: string;
|
||||
devDependencies?: string;
|
||||
directories?: any;
|
||||
dist: Dist;
|
||||
author: string | Author;
|
||||
main: string;
|
||||
homemage?: string;
|
||||
license?: string;
|
||||
readme: string;
|
||||
readmeFileName?: string;
|
||||
readmeFilename?: string;
|
||||
description: string;
|
||||
bin?: string;
|
||||
bugs?: any;
|
||||
files?: string[];
|
||||
gitHead?: string;
|
||||
maintainers?: Author[];
|
||||
contributors?: Author[];
|
||||
repository?: string | any;
|
||||
scripts?: any;
|
||||
homepage?: string;
|
||||
etag?: string;
|
||||
dependencies: any;
|
||||
keywords?: string | string[];
|
||||
nodeVersion?: string;
|
||||
_id: string;
|
||||
_npmVersion?: string;
|
||||
_npmUser: Author;
|
||||
_hasShrinkwrap?: boolean;
|
||||
deprecated?: string;
|
||||
}
|
||||
|
||||
interface Logger {
|
||||
child: (conf: any) => any;
|
||||
debug: (conf: any, template?: string) => void;
|
||||
error: (conf: any, template?: string) => void;
|
||||
http: (conf: any, template?: string) => void;
|
||||
trace: (conf: any, template?: string) => void;
|
||||
warn: (conf: any, template?: string) => void;
|
||||
info: (conf: any, template?: string) => void;
|
||||
}
|
||||
|
||||
interface Versions {
|
||||
[key: string]: Version;
|
||||
}
|
||||
|
||||
interface DistFile {
|
||||
url: string;
|
||||
sha: string;
|
||||
registry?: string;
|
||||
}
|
||||
|
||||
interface MergeTags {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
interface DistFiles {
|
||||
[key: string]: DistFile;
|
||||
}
|
||||
|
||||
interface AttachMents {
|
||||
[key: string]: AttachMentsItem;
|
||||
}
|
||||
|
||||
interface AttachMentsItem {
|
||||
data?: string;
|
||||
content_type?: string;
|
||||
length?: number;
|
||||
shasum?: string;
|
||||
version?: string;
|
||||
}
|
||||
|
||||
interface GenericBody {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
interface UpLinkMetadata {
|
||||
etag: string;
|
||||
fetched: number;
|
||||
}
|
||||
|
||||
interface UpLinks {
|
||||
[key: string]: UpLinkMetadata;
|
||||
}
|
||||
|
||||
interface Tags {
|
||||
[key: string]: Version;
|
||||
}
|
||||
|
||||
interface Headers {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
interface PackageUsers {
|
||||
[key: string]: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use Manifest instead
|
||||
*/
|
||||
interface Package {
|
||||
_id?: string;
|
||||
name: string;
|
||||
versions: Versions;
|
||||
'dist-tags': GenericBody;
|
||||
time: GenericBody;
|
||||
readme?: string;
|
||||
users?: PackageUsers;
|
||||
_distfiles: DistFiles;
|
||||
_attachments: AttachMents;
|
||||
_uplinks: UpLinks;
|
||||
_rev: string;
|
||||
}
|
||||
|
||||
interface PublishManifest {
|
||||
/**
|
||||
* The `_attachments` object has different usages:
|
||||
*
|
||||
* - When a package is published, it contains the tarball as an string, this string is used to be
|
||||
* converted as a tarball, usually attached to the package but not stored in the database.
|
||||
* - If user runs `npm star` the _attachments will be at the manifest body but empty.
|
||||
*
|
||||
* It has also an internal usage:
|
||||
*
|
||||
* - Used as a cache for the tarball, quick access to the tarball shasum, etc. Instead
|
||||
* iterate versions and find the right one, just using the tarball as a key which is what
|
||||
* the package manager sends to the registry.
|
||||
*
|
||||
* - A `_attachments` object is added every time a private tarball is published, upstream cached tarballs are
|
||||
* not being part of this object, only for published private packages.
|
||||
*
|
||||
* Note: This field is removed when the package is accesed through the web user interface.
|
||||
* */
|
||||
_attachments: AttachMents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents upstream manifest from another registry
|
||||
*/
|
||||
interface FullRemoteManifest {
|
||||
_id?: string;
|
||||
_rev?: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
'dist-tags': GenericBody;
|
||||
time: GenericBody;
|
||||
versions: Versions;
|
||||
maintainers?: Author[];
|
||||
/** store the latest readme **/
|
||||
readme?: string;
|
||||
/** store star assigned to this packages by users */
|
||||
users?: PackageUsers;
|
||||
// TODO: not clear what access exactly means
|
||||
access?: any;
|
||||
bugs?: { url: string };
|
||||
license?: string;
|
||||
homepage?: string;
|
||||
repository?: string | { type?: string; url: string; directory?: string };
|
||||
keywords?: string[];
|
||||
}
|
||||
|
||||
interface Manifest extends FullRemoteManifest, PublishManifest {
|
||||
// private fields only used by verdaccio
|
||||
/**
|
||||
* store fast access to the dist url of an specific tarball, instead search version
|
||||
* by id, just the tarball id is faster.
|
||||
*
|
||||
* The _distfiles is created only when a package is being sync from an upstream.
|
||||
* also used to fetch tarballs from upstream, the private publish tarballs are not stored in
|
||||
* this object because they are not published in the upstream registry.
|
||||
*/
|
||||
_distfiles: DistFiles;
|
||||
/**
|
||||
* Store access cache metadata, to avoid to fetch the same metadata multiple times.
|
||||
*
|
||||
* The key represents the uplink id which is composed of a etag and a fetched timestamp.
|
||||
*
|
||||
* The fetched timestamp is the time when the metadata was fetched, used to avoid to fetch the
|
||||
* same metadata until the metadata is older than the last fetch.
|
||||
*/
|
||||
_uplinks: UpLinks;
|
||||
/**
|
||||
* store the revision of the manifest
|
||||
*/
|
||||
_rev: string;
|
||||
}
|
||||
|
||||
interface UpLinkTokenConf {
|
||||
type: 'Bearer' | 'Basic';
|
||||
token?: string;
|
||||
token_env?: boolean | string;
|
||||
}
|
||||
|
||||
interface UpLinkConf {
|
||||
url: string;
|
||||
ca?: string;
|
||||
cache?: boolean;
|
||||
timeout?: string | void;
|
||||
maxage?: string | void;
|
||||
max_fails?: number | void;
|
||||
fail_timeout?: string | void;
|
||||
headers?: Headers;
|
||||
auth?: UpLinkTokenConf;
|
||||
strict_ssl?: boolean | void;
|
||||
_autogenerated?: boolean;
|
||||
}
|
||||
|
||||
interface AuthPluginPackage {
|
||||
packageName: string;
|
||||
packageVersion?: string;
|
||||
tag?: string;
|
||||
}
|
||||
|
||||
interface PackageAccess {
|
||||
storage?: string;
|
||||
publish?: string[];
|
||||
proxy?: string[];
|
||||
access?: string[];
|
||||
unpublish: string[];
|
||||
}
|
||||
|
||||
interface PackageAccessYaml {
|
||||
storage?: string;
|
||||
publish?: string;
|
||||
proxy?: string;
|
||||
access?: string;
|
||||
unpublish?: string;
|
||||
}
|
||||
|
||||
// info passed to the auth plugin when a package is package is being published
|
||||
interface AllowAccess {
|
||||
name: string;
|
||||
version?: string;
|
||||
tag?: string;
|
||||
}
|
||||
|
||||
interface AuthPackageAllow extends PackageAccess, AllowAccess {}
|
||||
|
||||
interface PackageList {
|
||||
[key: string]: PackageAccess;
|
||||
}
|
||||
|
||||
interface PackageListYaml {
|
||||
[key: string]: PackageAccessYaml;
|
||||
}
|
||||
interface UpLinksConfList {
|
||||
[key: string]: UpLinkConf;
|
||||
}
|
||||
|
||||
type LoggerType = 'stdout' | 'stderr' | 'file';
|
||||
type LoggerFormat = 'pretty' | 'pretty-timestamped' | 'file' | 'json';
|
||||
type LoggerLevel = 'http' | 'fatal' | 'warn' | 'info' | 'debug' | 'trace';
|
||||
|
||||
interface LoggerConfItem {
|
||||
type: LoggerType;
|
||||
format: LoggerFormat;
|
||||
level: LoggerLevel;
|
||||
}
|
||||
|
||||
interface PublishOptions {
|
||||
allow_offline: boolean;
|
||||
}
|
||||
|
||||
type AuthConf = any | AuthHtpasswd;
|
||||
|
||||
interface AuthHtpasswd {
|
||||
file: string;
|
||||
max_users: number;
|
||||
}
|
||||
|
||||
// FUTURE: rename to Notification
|
||||
interface Notifications {
|
||||
method: string;
|
||||
packagePattern: RegExp;
|
||||
packagePatternFlags: string;
|
||||
endpoint: string;
|
||||
content: string;
|
||||
headers: Headers;
|
||||
}
|
||||
|
||||
type Notification = Notifications;
|
||||
|
||||
interface Token {
|
||||
user: string;
|
||||
token: string;
|
||||
key: string;
|
||||
cidr?: string[];
|
||||
readonly: boolean;
|
||||
created: number | string;
|
||||
updated?: number | string;
|
||||
}
|
||||
|
||||
interface TokenFilter {
|
||||
user: string;
|
||||
}
|
||||
|
||||
type IPackageStorage = ILocalPackageManager | undefined;
|
||||
type IPackageStorageManager = ILocalPackageManager;
|
||||
type IPluginStorage<T> = ILocalData<T>;
|
||||
|
||||
interface AuthHtpasswd {
|
||||
file: string;
|
||||
max_users: number;
|
||||
}
|
||||
|
||||
interface ILocalStorage {
|
||||
add(name: string): void;
|
||||
remove(name: string): void;
|
||||
get(): StorageList;
|
||||
sync(): void;
|
||||
}
|
||||
|
||||
interface ListenAddress {
|
||||
[key: string]: string;
|
||||
}
|
||||
interface HttpsConfKeyCert {
|
||||
key: string;
|
||||
cert: string;
|
||||
ca?: string;
|
||||
}
|
||||
|
||||
interface HttpsConfPfx {
|
||||
pfx: string;
|
||||
passphrase?: string;
|
||||
}
|
||||
|
||||
type HttpsConf = HttpsConfKeyCert | HttpsConfPfx;
|
||||
|
||||
interface JWTOptions {
|
||||
sign: JWTSignOptions;
|
||||
verify: JWTVerifyOptions;
|
||||
}
|
||||
|
||||
interface JWTVerifyOptions {
|
||||
algorithm?: string;
|
||||
expiresIn?: string;
|
||||
notBefore?: string | number;
|
||||
ignoreExpiration?: boolean;
|
||||
maxAge?: string | number;
|
||||
clockTimestamp?: number;
|
||||
}
|
||||
|
||||
interface JWTSignOptions {
|
||||
algorithm?: string;
|
||||
expiresIn?: string;
|
||||
notBefore?: string;
|
||||
ignoreExpiration?: boolean;
|
||||
maxAge?: string | number;
|
||||
clockTimestamp?: number;
|
||||
}
|
||||
|
||||
interface APITokenOptions {
|
||||
legacy: boolean;
|
||||
jwt?: JWTOptions;
|
||||
}
|
||||
|
||||
interface Security {
|
||||
web: JWTOptions;
|
||||
api: APITokenOptions;
|
||||
}
|
||||
|
||||
export type FlagsConfig = {
|
||||
searchRemote?: boolean;
|
||||
changePassword?: boolean;
|
||||
};
|
||||
|
||||
export type RateLimit = {
|
||||
windowMs: number;
|
||||
max: number;
|
||||
};
|
||||
|
||||
export type ServerSettingsConf = {
|
||||
// express-rate-limit settings
|
||||
rateLimit: RateLimit;
|
||||
keepAliveTimeout?: number;
|
||||
// force http2 if https is defined
|
||||
http2?: boolean;
|
||||
};
|
||||
|
||||
type URLPrefix = {
|
||||
// if is false, it would be relative by default
|
||||
absolute: boolean;
|
||||
// base path
|
||||
// eg: absolute: true, https://somedomain.com/xxx/
|
||||
// eg: absolute: false, /xxx/ (default) if url_prefix is an string instead an object
|
||||
basePath: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* YAML configuration file available options.
|
||||
*/
|
||||
interface ConfigYaml {
|
||||
_debug?: boolean;
|
||||
storage?: string | void;
|
||||
packages?: PackageListYaml;
|
||||
uplinks: UpLinksConfList;
|
||||
// FUTURE: log should be mandatory
|
||||
log?: LoggerConfItem;
|
||||
web?: WebConf;
|
||||
auth?: AuthConf;
|
||||
security?: Security;
|
||||
publish?: PublishOptions;
|
||||
store?: any;
|
||||
listen?: ListenAddress;
|
||||
https?: HttpsConf;
|
||||
http_proxy?: string;
|
||||
plugins?: string | void;
|
||||
https_proxy?: string;
|
||||
no_proxy?: string;
|
||||
max_body_size?: string;
|
||||
notifications?: Notifications;
|
||||
notify?: Notifications | Notifications[];
|
||||
middlewares?: any;
|
||||
filters?: any;
|
||||
url_prefix?: string;
|
||||
server?: ServerSettingsConf;
|
||||
flags?: FlagsConfig;
|
||||
// internal objects, added by internal yaml to JS config parser
|
||||
// @deprecated use configPath instead
|
||||
config_path?: string;
|
||||
// save the configuration file path
|
||||
configPath?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration object with additonal methods for configuration, includes yaml and internal medatada.
|
||||
* @interface Config
|
||||
* @extends {ConfigYaml}
|
||||
*/
|
||||
interface Config extends Omit<ConfigYaml, 'packages' | 'security' | 'configPath'> {
|
||||
user_agent: string;
|
||||
server_id: string;
|
||||
secret: string;
|
||||
// save the configuration file path, it's fails without thi configPath
|
||||
configPath: string;
|
||||
// packages from yaml file looks different from packages inside the config file
|
||||
packages: PackageList;
|
||||
// security object defaults is added by the config file but optional in the yaml file
|
||||
security: Security;
|
||||
// @deprecated (pending adding the replacement)
|
||||
checkSecretKey(token: string): string;
|
||||
getMatchedPackagesSpec(storage: string): PackageAccess | void;
|
||||
// TODO: verify how to handle this in the future
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
type PublisherMaintainer = {
|
||||
username: string;
|
||||
email: string;
|
||||
};
|
||||
|
||||
type SearchPackageBody = {
|
||||
name: string;
|
||||
scope: string;
|
||||
description: string;
|
||||
author: string | PublisherMaintainer;
|
||||
version: string;
|
||||
keywords: string | string[] | undefined;
|
||||
date: string;
|
||||
links?: {
|
||||
npm: string; // only include placeholder for URL eg: {url}/{packageName}
|
||||
homepage?: string;
|
||||
repository?: string;
|
||||
bugs?: string;
|
||||
};
|
||||
publisher?: any;
|
||||
maintainers?: PublisherMaintainer[];
|
||||
};
|
||||
|
||||
interface ConfigWithHttps extends Config {
|
||||
https: HttpsConf;
|
||||
}
|
||||
|
||||
export interface ITokenActions {
|
||||
saveToken(token: Token): Promise<any>;
|
||||
deleteToken(user: string, tokenKey: string): Promise<any>;
|
||||
readTokens(filter: TokenFilter): Promise<Token[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use @verdaccio/core pluginUtils instead
|
||||
*/
|
||||
interface ILocalData<T> extends IPlugin<T>, ITokenActions {
|
||||
logger: Logger;
|
||||
config: T & Config;
|
||||
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;
|
||||
}
|
||||
|
||||
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>;
|
||||
}
|
||||
|
||||
// @deprecated use IBasicAuth from @verdaccio/auth
|
||||
interface IBasicAuth<T> {
|
||||
config: T & Config;
|
||||
aesEncrypt(buf: string): string;
|
||||
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;
|
||||
}
|
||||
|
||||
export interface Plugin<T> {
|
||||
new (config: T, options: PluginOptions<T>): T;
|
||||
}
|
||||
|
||||
interface IPlugin<T> {
|
||||
version?: string;
|
||||
// In case a plugin needs to be cleaned up/removed
|
||||
close?(): void;
|
||||
}
|
||||
|
||||
interface PluginOptions<T> {
|
||||
config: T & Config;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
// FIXME: error should be export type `VerdaccioError = HttpError & { code: number };`
|
||||
// instead of AuthError
|
||||
// but this type is on @verdaccio/core and cannot be used here yet (I don't know why)
|
||||
interface HttpError extends Error {
|
||||
status: number;
|
||||
statusCode: number;
|
||||
expose: boolean;
|
||||
headers?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
type AuthError = HttpError & { code: number };
|
||||
type AuthAccessCallback = (error: AuthError | null, access: boolean) => void;
|
||||
type AuthCallback = (error: AuthError | null, groups: string[] | false) => void;
|
||||
|
||||
interface IPluginAuth<T> extends IPlugin<T> {
|
||||
authenticate(user: string, password: string, cb: AuthCallback): void;
|
||||
adduser?(user: string, password: string, cb: AuthCallback): void;
|
||||
changePassword?(user: string, password: string, newPassword: string, cb: AuthCallback): void;
|
||||
allow_publish?(user: RemoteUser, pkg: T & AuthPackageAllow, cb: AuthAccessCallback): void;
|
||||
allow_access?(user: RemoteUser, pkg: T & PackageAccess, cb: AuthAccessCallback): void;
|
||||
allow_unpublish?(user: RemoteUser, pkg: T & AuthPackageAllow, 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;
|
||||
}
|
||||
|
||||
// @deprecated use @verdaccio/server
|
||||
interface IPluginMiddleware<T> extends IPlugin<T> {
|
||||
register_middlewares(app: any, auth: IBasicAuth<T>, storage: any): void;
|
||||
}
|
||||
|
||||
interface IPluginStorageFilter<T> extends IPlugin<T> {
|
||||
filter_metadata(packageInfo: Manifest): Promise<Package>;
|
||||
}
|
||||
|
||||
export type SearchResultWeb = {
|
||||
name: string;
|
||||
version: string;
|
||||
description: string;
|
||||
};
|
||||
}
|
|
@ -31,15 +31,24 @@
|
|||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"main": "index.d.ts",
|
||||
"types": "index.d.ts",
|
||||
"main": "build/types.d.ts",
|
||||
"types": "build/types.d.ts",
|
||||
"scripts": {
|
||||
"test": "exit 0",
|
||||
"build": "exit 0"
|
||||
"clean": "rimraf ./build",
|
||||
"test": "pnpm type-check",
|
||||
"build:docs": "typedoc --options ./typedoc.json --excludeExternals --tsconfig tsconfig.build.json",
|
||||
"type-check": "tsc --noEmit -p tsconfig.build.json",
|
||||
"build": "tsc --emitDeclarationOnly -p tsconfig.build.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "16.11.47",
|
||||
"tsd": "0.22.0"
|
||||
"typedoc": "beta",
|
||||
"typedoc-plugin-missing-exports": "1.0.0"
|
||||
},
|
||||
"typedoc": {
|
||||
"entryPoint": "./src/types.ts",
|
||||
"readmeFile": "./README.md",
|
||||
"displayName": "@verdaccio/types"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
|
|
37
packages/core/types/src/commons.ts
Normal file
37
packages/core/types/src/commons.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
// @deprecated add proper type fot the callback
|
||||
export type Callback = Function;
|
||||
// FIXME: err should be something flexible enough for any implementation
|
||||
export type CallbackAction = (err: any | null) => void;
|
||||
// eslint-disable-next-line no-undef
|
||||
export type CallbackError = (err: NodeJS.ErrnoException) => void;
|
||||
|
||||
export interface RemoteUser {
|
||||
real_groups: string[];
|
||||
groups: string[];
|
||||
name: string | void;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export type StringValue = string | void | null;
|
||||
|
||||
// FIXME: error should be export type `VerdaccioError = HttpError & { code: number };`
|
||||
// instead of AuthError
|
||||
// but this type is on @verdaccio/core and cannot be used here yet (I don't know why)
|
||||
export interface HttpError extends Error {
|
||||
status: number;
|
||||
statusCode: number;
|
||||
expose: boolean;
|
||||
headers?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export type URLPrefix = {
|
||||
// if is false, it would be relative by default
|
||||
absolute: boolean;
|
||||
// base path
|
||||
// eg: absolute: true, https://somedomain.com/xxx/
|
||||
// eg: absolute: false, /xxx/ (default) if url_prefix is an string instead an object
|
||||
basePath: string;
|
||||
};
|
296
packages/core/types/src/configuration.ts
Normal file
296
packages/core/types/src/configuration.ts
Normal file
|
@ -0,0 +1,296 @@
|
|||
import { PackageAccess, PackageList } from './manifest';
|
||||
|
||||
export type TypeToken = 'Bearer' | 'Basic';
|
||||
|
||||
export interface Logger {
|
||||
child: (conf: any) => any;
|
||||
debug: (conf: any, template?: string) => void;
|
||||
error: (conf: any, template?: string) => void;
|
||||
http: (conf: any, template?: string) => void;
|
||||
trace: (conf: any, template?: string) => void;
|
||||
warn: (conf: any, template?: string) => void;
|
||||
info: (conf: any, template?: string) => void;
|
||||
}
|
||||
|
||||
export type LoggerType = 'stdout' | 'file';
|
||||
export type LoggerFormat = 'pretty' | 'pretty-timestamped' | 'json';
|
||||
export type LoggerLevel = 'http' | 'fatal' | 'warn' | 'info' | 'debug' | 'trace';
|
||||
|
||||
export type LoggerConfigItem = {
|
||||
type?: LoggerType;
|
||||
/**
|
||||
* The format
|
||||
*/
|
||||
format?: LoggerFormat;
|
||||
path?: string;
|
||||
level?: string;
|
||||
colors?: boolean;
|
||||
async?: boolean;
|
||||
};
|
||||
|
||||
export interface ConfigWithHttps extends Config {
|
||||
https: HttpsConf;
|
||||
}
|
||||
|
||||
export interface PackageAccessYaml {
|
||||
storage?: string;
|
||||
publish?: string;
|
||||
proxy?: string;
|
||||
access?: string;
|
||||
unpublish?: string;
|
||||
}
|
||||
|
||||
export interface LoggerConfItem {
|
||||
type: LoggerType;
|
||||
format: LoggerFormat;
|
||||
level: LoggerLevel;
|
||||
}
|
||||
|
||||
export interface Headers {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface UpLinkTokenConf {
|
||||
type: TypeToken;
|
||||
token?: string;
|
||||
token_env?: boolean | string;
|
||||
}
|
||||
|
||||
export interface UpLinkConf {
|
||||
url: string;
|
||||
ca?: string;
|
||||
cache?: boolean;
|
||||
timeout?: string | void;
|
||||
maxage?: string | void;
|
||||
max_fails?: number | void;
|
||||
fail_timeout?: string | void;
|
||||
headers?: Headers;
|
||||
auth?: UpLinkTokenConf;
|
||||
strict_ssl?: boolean | void;
|
||||
_autogenerated?: boolean;
|
||||
}
|
||||
|
||||
export type RateLimit = {
|
||||
windowMs?: number;
|
||||
max?: number;
|
||||
};
|
||||
|
||||
// export interface WebConf {
|
||||
// enable?: boolean;
|
||||
// title?: string;
|
||||
// logo?: string;
|
||||
// favicon?: string;
|
||||
// gravatar?: boolean;
|
||||
// sort_packages?: string;
|
||||
// rateLimit?: RateLimit;
|
||||
// }
|
||||
|
||||
export type FlagsConfig = {
|
||||
searchRemote?: boolean;
|
||||
changePassword?: boolean;
|
||||
};
|
||||
|
||||
export type PackageManagers = 'pnpm' | 'yarn' | 'npm';
|
||||
|
||||
// FUTURE: WebConf and TemplateUIOptions should be merged .
|
||||
export type CommonWebConf = {
|
||||
title?: string;
|
||||
logo?: string;
|
||||
favicon?: string;
|
||||
gravatar?: boolean;
|
||||
sort_packages?: string;
|
||||
darkMode?: boolean;
|
||||
url_prefix?: string;
|
||||
language?: string;
|
||||
login?: boolean;
|
||||
scope?: string;
|
||||
pkgManagers?: PackageManagers[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Options are passed to the index.html
|
||||
*/
|
||||
export type TemplateUIOptions = {
|
||||
uri?: string;
|
||||
darkMode?: boolean;
|
||||
protocol?: string;
|
||||
host?: string;
|
||||
// deprecated
|
||||
basename?: string;
|
||||
scope?: string;
|
||||
showInfo?: boolean;
|
||||
showSettings?: boolean;
|
||||
showSearch?: boolean;
|
||||
showFooter?: boolean;
|
||||
showThemeSwitch?: boolean;
|
||||
showDownloadTarball?: boolean;
|
||||
showRaw?: boolean;
|
||||
base: string;
|
||||
primaryColor?: string;
|
||||
version?: string;
|
||||
logoURI?: string;
|
||||
flags: FlagsConfig;
|
||||
} & CommonWebConf;
|
||||
|
||||
/**
|
||||
* Options on config.yaml for web
|
||||
*/
|
||||
export type WebConf = {
|
||||
// FIXME: rename to primaryColor and move it to CommonWebConf
|
||||
primary_color?: string;
|
||||
enable?: boolean;
|
||||
scriptsHead?: string[];
|
||||
scriptsBodyAfter?: string[];
|
||||
metaScripts?: string[];
|
||||
bodyBefore?: string[];
|
||||
bodyAfter?: string[];
|
||||
} & CommonWebConf;
|
||||
|
||||
export interface UpLinksConfList {
|
||||
[key: string]: UpLinkConf;
|
||||
}
|
||||
|
||||
export interface AuthHtpasswd {
|
||||
file: string;
|
||||
max_users: number;
|
||||
}
|
||||
|
||||
export type AuthConf = any | AuthHtpasswd;
|
||||
|
||||
export interface JWTOptions {
|
||||
sign: JWTSignOptions;
|
||||
verify: JWTVerifyOptions;
|
||||
}
|
||||
|
||||
export interface JWTSignOptions {
|
||||
algorithm?: string;
|
||||
expiresIn?: string;
|
||||
notBefore?: string;
|
||||
ignoreExpiration?: boolean;
|
||||
maxAge?: string | number;
|
||||
clockTimestamp?: number;
|
||||
}
|
||||
|
||||
export interface JWTVerifyOptions {
|
||||
algorithm?: string;
|
||||
expiresIn?: string;
|
||||
notBefore?: string | number;
|
||||
ignoreExpiration?: boolean;
|
||||
maxAge?: string | number;
|
||||
clockTimestamp?: number;
|
||||
}
|
||||
|
||||
export interface APITokenOptions {
|
||||
legacy: boolean;
|
||||
jwt?: JWTOptions;
|
||||
}
|
||||
|
||||
export interface Security {
|
||||
web: JWTOptions;
|
||||
api: APITokenOptions;
|
||||
}
|
||||
|
||||
export interface PublishOptions {
|
||||
allow_offline: boolean;
|
||||
}
|
||||
|
||||
export interface ListenAddress {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface HttpsConfKeyCert {
|
||||
key: string;
|
||||
cert: string;
|
||||
ca?: string;
|
||||
}
|
||||
|
||||
export interface HttpsConfPfx {
|
||||
pfx: string;
|
||||
passphrase?: string;
|
||||
}
|
||||
|
||||
export type HttpsConf = HttpsConfKeyCert | HttpsConfPfx;
|
||||
|
||||
export interface Notifications {
|
||||
method: string;
|
||||
packagePattern: RegExp;
|
||||
packagePatternFlags: string;
|
||||
endpoint: string;
|
||||
content: string;
|
||||
headers: Headers;
|
||||
}
|
||||
|
||||
export type Notification = Notifications;
|
||||
|
||||
export type ServerSettingsConf = {
|
||||
// express-rate-limit settings
|
||||
rateLimit: RateLimit;
|
||||
keepAliveTimeout?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* YAML configuration file available options.
|
||||
*/
|
||||
export interface ConfigYaml {
|
||||
_debug?: boolean;
|
||||
storage?: string | void;
|
||||
packages: PackageList;
|
||||
uplinks: UpLinksConfList;
|
||||
log?: LoggerConfItem;
|
||||
web?: WebConf;
|
||||
auth?: AuthConf;
|
||||
security: Security;
|
||||
publish?: PublishOptions;
|
||||
store?: any;
|
||||
listen?: ListenAddress;
|
||||
https?: HttpsConf;
|
||||
http_proxy?: string;
|
||||
plugins?: string | void;
|
||||
https_proxy?: string;
|
||||
no_proxy?: string;
|
||||
max_body_size?: string;
|
||||
notifications?: Notifications;
|
||||
notify?: Notifications | Notifications[];
|
||||
middlewares?: any;
|
||||
filters?: any;
|
||||
url_prefix?: string;
|
||||
server?: ServerSettingsConf;
|
||||
flags?: FlagsConfig;
|
||||
// internal objects, added by internal yaml to JS config parser
|
||||
// @deprecated use configPath instead
|
||||
config_path?: string;
|
||||
// save the configuration file path
|
||||
configPath?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration object with additonal methods for configuration, includes yaml and internal medatada.
|
||||
* @interface Config
|
||||
* @extends {ConfigYaml}
|
||||
*/
|
||||
export interface Config extends Omit<ConfigYaml, 'packages' | 'security' | 'configPath'> {
|
||||
user_agent: string;
|
||||
server_id: string;
|
||||
secret: string;
|
||||
// save the configuration file path, it's fails without thi configPath
|
||||
configPath: string;
|
||||
// packages from yaml file looks different from packages inside the config file
|
||||
packages: PackageList;
|
||||
// security object defaults is added by the config file but optional in the yaml file
|
||||
security: Security;
|
||||
// @deprecated (pending adding the replacement)
|
||||
checkSecretKey(token: string): string;
|
||||
getMatchedPackagesSpec(storage: string): PackageAccess | void;
|
||||
// TODO: verify how to handle this in the future
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface AllowAccess {
|
||||
name: string;
|
||||
version?: string;
|
||||
tag?: string;
|
||||
}
|
||||
|
||||
// info passed to the auth plugin when a package is package is being published
|
||||
|
||||
export interface AuthPackageAllow extends PackageAccess, AllowAccess {}
|
217
packages/core/types/src/manifest.ts
Normal file
217
packages/core/types/src/manifest.ts
Normal file
|
@ -0,0 +1,217 @@
|
|||
export interface PackageAccess {
|
||||
storage?: string;
|
||||
publish?: string[];
|
||||
proxy?: string[];
|
||||
access?: string[];
|
||||
unpublish: string[];
|
||||
}
|
||||
|
||||
export interface PackageList {
|
||||
[key: string]: PackageAccess;
|
||||
}
|
||||
|
||||
export interface MergeTags {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface DistFile {
|
||||
url: string;
|
||||
sha: string;
|
||||
registry?: string;
|
||||
}
|
||||
|
||||
export interface DistFiles {
|
||||
[key: string]: DistFile;
|
||||
}
|
||||
|
||||
export interface Token {
|
||||
user: string;
|
||||
token: string;
|
||||
key: string;
|
||||
cidr?: string[];
|
||||
readonly: boolean;
|
||||
created: number | string;
|
||||
updated?: number | string;
|
||||
}
|
||||
|
||||
export interface AttachMents {
|
||||
[key: string]: AttachMentsItem;
|
||||
}
|
||||
|
||||
export interface AttachMentsItem {
|
||||
content_type?: string;
|
||||
data?: string;
|
||||
length?: number;
|
||||
shasum?: string;
|
||||
version?: string;
|
||||
}
|
||||
|
||||
export interface GenericBody {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface UpLinkMetadata {
|
||||
etag: string;
|
||||
fetched: number;
|
||||
}
|
||||
|
||||
export interface UpLinks {
|
||||
[key: string]: UpLinkMetadata;
|
||||
}
|
||||
|
||||
export interface Signatures {
|
||||
keyid: string;
|
||||
sig: string;
|
||||
}
|
||||
|
||||
export interface Dist {
|
||||
'npm-signature'?: string;
|
||||
signatures?: Signatures[];
|
||||
fileCount?: number;
|
||||
integrity?: string;
|
||||
shasum: string;
|
||||
unpackedSize?: number;
|
||||
tarball: string;
|
||||
}
|
||||
|
||||
export interface Author {
|
||||
username?: string;
|
||||
name: string;
|
||||
email?: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export interface PackageUsers {
|
||||
[key: string]: boolean;
|
||||
}
|
||||
|
||||
export interface Tags {
|
||||
[key: string]: Version;
|
||||
}
|
||||
|
||||
export interface Version {
|
||||
name: string;
|
||||
version: string;
|
||||
devDependencies?: string;
|
||||
directories?: any;
|
||||
dist: Dist;
|
||||
author: string | Author;
|
||||
main: string;
|
||||
homemage?: string;
|
||||
license?: string;
|
||||
readme: string;
|
||||
readmeFileName?: string;
|
||||
readmeFilename?: string;
|
||||
description: string;
|
||||
bin?: string;
|
||||
bugs?: any;
|
||||
files?: string[];
|
||||
gitHead?: string;
|
||||
maintainers?: Author[];
|
||||
contributors?: Author[];
|
||||
repository?: string | any;
|
||||
scripts?: any;
|
||||
homepage?: string;
|
||||
etag?: string;
|
||||
dependencies: any;
|
||||
keywords?: string | string[];
|
||||
nodeVersion?: string;
|
||||
_id: string;
|
||||
_npmVersion?: string;
|
||||
_npmUser: Author;
|
||||
_hasShrinkwrap?: boolean;
|
||||
deprecated?: string;
|
||||
}
|
||||
|
||||
export interface Versions {
|
||||
[key: string]: Version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use Manifest instead
|
||||
*/
|
||||
export interface Package {
|
||||
_id?: string;
|
||||
name: string;
|
||||
versions: Versions;
|
||||
'dist-tags': GenericBody;
|
||||
time: GenericBody;
|
||||
readme?: string;
|
||||
users?: PackageUsers;
|
||||
_distfiles: DistFiles;
|
||||
_attachments: AttachMents;
|
||||
_uplinks: UpLinks;
|
||||
_rev: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents upstream manifest from another registry
|
||||
*/
|
||||
export interface FullRemoteManifest {
|
||||
_id?: string;
|
||||
_rev?: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
'dist-tags': GenericBody;
|
||||
time: GenericBody;
|
||||
versions: Versions;
|
||||
maintainers?: Author[];
|
||||
/** store the latest readme **/
|
||||
readme?: string;
|
||||
/** store star assigned to this packages by users */
|
||||
users?: PackageUsers;
|
||||
// TODO: not clear what access exactly means
|
||||
access?: any;
|
||||
bugs?: { url: string };
|
||||
license?: string;
|
||||
homepage?: string;
|
||||
repository?: string | { type?: string; url: string; directory?: string };
|
||||
keywords?: string[];
|
||||
}
|
||||
|
||||
export interface Manifest extends FullRemoteManifest, PublishManifest {
|
||||
// private fields only used by verdaccio
|
||||
/**
|
||||
* store fast access to the dist url of an specific tarball, instead search version
|
||||
* by id, just the tarball id is faster.
|
||||
*
|
||||
* The _distfiles is created only when a package is being sync from an upstream.
|
||||
* also used to fetch tarballs from upstream, the private publish tarballs are not stored in
|
||||
* this object because they are not published in the upstream registry.
|
||||
*/
|
||||
_distfiles: DistFiles;
|
||||
/**
|
||||
* Store access cache metadata, to avoid to fetch the same metadata multiple times.
|
||||
*
|
||||
* The key represents the uplink id which is composed of a etag and a fetched timestamp.
|
||||
*
|
||||
* The fetched timestamp is the time when the metadata was fetched, used to avoid to fetch the
|
||||
* same metadata until the metadata is older than the last fetch.
|
||||
*/
|
||||
_uplinks: UpLinks;
|
||||
/**
|
||||
* store the revision of the manifest
|
||||
*/
|
||||
_rev: string;
|
||||
}
|
||||
export interface PublishManifest {
|
||||
/**
|
||||
* The `_attachments` object has different usages:
|
||||
*
|
||||
* - When a package is published, it contains the tarball as an string, this string is used to be
|
||||
* converted as a tarball, usually attached to the package but not stored in the database.
|
||||
* - If user runs `npm star` the _attachments will be at the manifest body but empty.
|
||||
*
|
||||
* It has also an internal usage:
|
||||
*
|
||||
* - Used as a cache for the tarball, quick access to the tarball shasum, etc. Instead
|
||||
* iterate versions and find the right one, just using the tarball as a key which is what
|
||||
* the package manager sends to the registry.
|
||||
*
|
||||
* - A `_attachments` object is added every time a private tarball is published, upstream cached tarballs are
|
||||
* not being part of this object, only for published private packages.
|
||||
*
|
||||
* Note: This field is removed when the package is accesed through the web user interface.
|
||||
* */
|
||||
_attachments: AttachMents;
|
||||
}
|
22
packages/core/types/src/plugins/auth.ts
Normal file
22
packages/core/types/src/plugins/auth.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
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;
|
||||
}
|
15
packages/core/types/src/plugins/commons.ts
Normal file
15
packages/core/types/src/plugins/commons.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Config, Logger } from '../configuration';
|
||||
|
||||
export class Plugin<T> {
|
||||
public constructor(config: T, options: PluginOptions<T>) {}
|
||||
}
|
||||
|
||||
export interface IPlugin<T> {
|
||||
// TODO: not used on core yet
|
||||
version?: string;
|
||||
}
|
||||
|
||||
export interface PluginOptions<T> {
|
||||
config: T & Config;
|
||||
logger: Logger;
|
||||
}
|
6
packages/core/types/src/plugins/filter.ts
Normal file
6
packages/core/types/src/plugins/filter.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { Manifest } from '../manifest';
|
||||
import { IPlugin } from './commons';
|
||||
|
||||
export interface IPluginStorageFilter<T> extends IPlugin<T> {
|
||||
filter_metadata(packageInfo: Manifest): Promise<Manifest>;
|
||||
}
|
31
packages/core/types/src/plugins/index.ts
Normal file
31
packages/core/types/src/plugins/index.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
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';
|
8
packages/core/types/src/plugins/middleware.ts
Normal file
8
packages/core/types/src/plugins/middleware.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
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;
|
||||
}
|
95
packages/core/types/src/plugins/storage.ts
Normal file
95
packages/core/types/src/plugins/storage.ts
Normal file
|
@ -0,0 +1,95 @@
|
|||
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';
|
||||
|
||||
export type StorageList = string[];
|
||||
|
||||
export interface LocalStorage {
|
||||
list: any;
|
||||
secret: string;
|
||||
}
|
||||
|
||||
export interface ILocalStorage {
|
||||
add(name: string): void;
|
||||
remove(name: string): void;
|
||||
get(): StorageList;
|
||||
sync(): void;
|
||||
}
|
||||
|
||||
export interface TokenFilter {
|
||||
user: string;
|
||||
}
|
||||
|
||||
export interface ITokenActions {
|
||||
saveToken(token: Token): Promise<any>;
|
||||
deleteToken(user: string, tokenKey: string): Promise<any>;
|
||||
readTokens(filter: TokenFilter): Promise<Token[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method expect return a Package object
|
||||
* eg:
|
||||
* {
|
||||
* name: string;
|
||||
* time: number;
|
||||
* ... and other props
|
||||
* }
|
||||
*
|
||||
* The `cb` callback object will be executed if:
|
||||
* - it might return object (truly)
|
||||
* - it might reutrn null
|
||||
*/
|
||||
export type onSearchPackage = (item: Manifest, cb: CallbackAction) => void;
|
||||
// FIXME: error should be export type `VerdaccioError = HttpError & { code: number };`
|
||||
// but this type is on @verdaccio/commons-api and cannot be used here yet
|
||||
export type onEndSearchPackage = (error?: any) => void;
|
||||
export type onValidatePackage = (name: string) => boolean;
|
||||
|
||||
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 & Config;
|
||||
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;
|
||||
}
|
0
packages/core/types/src/plugins/theme.ts
Normal file
0
packages/core/types/src/plugins/theme.ts
Normal file
28
packages/core/types/src/search.ts
Normal file
28
packages/core/types/src/search.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
export type PublisherMaintainer = {
|
||||
username: string;
|
||||
email: string;
|
||||
};
|
||||
|
||||
export type SearchPackageBody = {
|
||||
name: string;
|
||||
scope: string;
|
||||
description: string;
|
||||
author: string | PublisherMaintainer;
|
||||
version: string;
|
||||
keywords: string | string[] | undefined;
|
||||
date: string;
|
||||
links?: {
|
||||
npm: string; // only include placeholder for URL eg: {url}/{packageName}
|
||||
homepage?: string;
|
||||
repository?: string;
|
||||
bugs?: string;
|
||||
};
|
||||
publisher?: any;
|
||||
maintainers?: PublisherMaintainer[];
|
||||
};
|
||||
|
||||
export type SearchResultWeb = {
|
||||
name: string;
|
||||
version: string;
|
||||
description: string;
|
||||
};
|
5
packages/core/types/src/types.ts
Normal file
5
packages/core/types/src/types.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
export * from './plugins';
|
||||
export * from './manifest';
|
||||
export * from './search';
|
||||
export * from './commons';
|
||||
export * from './configuration';
|
9
packages/core/types/tsconfig.build.json
Normal file
9
packages/core/types/tsconfig.build.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./build"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["src/**/*.test.ts"]
|
||||
}
|
9
packages/core/types/tsconfig.json
Normal file
9
packages/core/types/tsconfig.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.reference.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./build"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["src/**/*.test.ts"]
|
||||
}
|
5
packages/core/types/typedoc.json
Normal file
5
packages/core/types/typedoc.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"$schema": "https://typedoc.org/schema.json",
|
||||
"entryPoints": ["src/types.ts"],
|
||||
"sort": ["source-order"]
|
||||
}
|
|
@ -1,3 +1,10 @@
|
|||
const config = require('../../jest/config');
|
||||
|
||||
module.exports = Object.assign({}, config, {});
|
||||
module.exports = Object.assign({}, config, {
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
// FIXME: increase to 90
|
||||
lines: 60,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf ./build",
|
||||
"test": "jest",
|
||||
"test": "cross-env TZ=utc jest",
|
||||
"type-check": "tsc --noEmit -p tsconfig.build.json",
|
||||
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
|
||||
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
|
||||
|
@ -40,13 +40,13 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"dayjs": "1.11.4",
|
||||
"fast-safe-stringify": "2.1.1",
|
||||
"kleur": "3.0.3",
|
||||
"pino-abstract-transport": "1.0.0",
|
||||
"colorette": "2.0.7",
|
||||
"lodash": "4.17.21",
|
||||
"prettier-bytes": "1.0.4"
|
||||
"sonic-boom": "3.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"pino": "7.11.0"
|
||||
"pino": "8.4.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { green, red, white } from 'kleur';
|
||||
import { green, red, white } from 'colorette';
|
||||
import { inspect } from 'util';
|
||||
|
||||
import { LevelCode, calculateLevel, levelsColors, subSystemLevels } from './levels';
|
||||
|
@ -19,7 +19,11 @@ export interface ObjectTemplate {
|
|||
[key: string]: string | number | object | null | void;
|
||||
}
|
||||
|
||||
export function fillInMsgTemplate(msg, templateOptions: ObjectTemplate, colors): string {
|
||||
export function fillInMsgTemplate(
|
||||
msg: string,
|
||||
templateOptions: ObjectTemplate,
|
||||
colors: boolean
|
||||
): string {
|
||||
const templateRegex = /@{(!?[$A-Za-z_][$0-9A-Za-z\._]*)}/g;
|
||||
|
||||
return msg.replace(templateRegex, (_, name): string => {
|
||||
|
@ -53,10 +57,12 @@ export function fillInMsgTemplate(msg, templateOptions: ObjectTemplate, colors):
|
|||
});
|
||||
}
|
||||
|
||||
function getMessage(debugLevel, msg, sub, templateObjects, hasColors) {
|
||||
function getMessage(debugLevel, msg, sub, templateObjects, hasColors: boolean) {
|
||||
const finalMessage = fillInMsgTemplate(msg, templateObjects, hasColors);
|
||||
|
||||
const subSystemType = subSystemLevels.color[sub ?? 'default'];
|
||||
const subSystemType = hasColors
|
||||
? subSystemLevels.color[sub ?? 'default']
|
||||
: subSystemLevels.white[sub ?? 'default'];
|
||||
if (hasColors) {
|
||||
const logString = `${levelsColors[debugLevel](padRight(debugLevel, LEVEL_VALUE_MAX))}${white(
|
||||
`${subSystemType} ${finalMessage}`
|
||||
|
@ -71,8 +77,8 @@ function getMessage(debugLevel, msg, sub, templateObjects, hasColors) {
|
|||
|
||||
export function printMessage(
|
||||
templateObjects: ObjectTemplate,
|
||||
options: PrettyOptionsExtended,
|
||||
hasColors = true
|
||||
options: Pick<PrettyOptionsExtended, 'prettyStamp'>,
|
||||
hasColors: boolean
|
||||
): string {
|
||||
const { prettyStamp } = options;
|
||||
const { level, msg, sub } = templateObjects;
|
||||
|
|
|
@ -1,20 +1,2 @@
|
|||
import { fillInMsgTemplate, printMessage } from './formatter';
|
||||
import { PrettyOptionsExtended } from './types';
|
||||
|
||||
export { fillInMsgTemplate };
|
||||
|
||||
export type PrettyFactory = (param) => string;
|
||||
|
||||
/*
|
||||
options eg:
|
||||
{ messageKey: 'msg', levelFirst: true, prettyStamp: false }
|
||||
*/
|
||||
|
||||
export default function prettyFactory(options: PrettyOptionsExtended): PrettyFactory {
|
||||
// the break line must happens in the prettify component
|
||||
const breakLike = '\n';
|
||||
return (inputData): string => {
|
||||
// FIXME: review colors by default is true
|
||||
return printMessage(inputData, options, true) + breakLike;
|
||||
};
|
||||
}
|
||||
export { default, buildPretty } from './prettify';
|
||||
export { fillInMsgTemplate } from './formatter';
|
||||
|
|
|
@ -53,6 +53,7 @@ export const subSystemLevels = {
|
|||
white: {
|
||||
in: ARROWS.LEFT,
|
||||
out: ARROWS.RIGHT,
|
||||
auth: ARROWS.NEUTRAL,
|
||||
fs: ARROWS.EQUAL,
|
||||
default: ARROWS.NEUTRAL,
|
||||
},
|
||||
|
|
118
packages/logger-prettify/src/prettify.ts
Normal file
118
packages/logger-prettify/src/prettify.ts
Normal file
|
@ -0,0 +1,118 @@
|
|||
import { isColorSupported } from 'colorette';
|
||||
import { WriteStream } from 'fs';
|
||||
import build from 'pino-abstract-transport';
|
||||
import SonicBoom, { SonicBoomOpts } from 'sonic-boom';
|
||||
import { Transform, pipeline } from 'stream';
|
||||
import { isMainThread } from 'worker_threads';
|
||||
|
||||
import { fillInMsgTemplate, printMessage } from './formatter';
|
||||
import { PrettyOptionsExtended } from './types';
|
||||
|
||||
export { fillInMsgTemplate };
|
||||
|
||||
function noop() {}
|
||||
|
||||
/**
|
||||
* Creates a safe SonicBoom instance
|
||||
*
|
||||
* @param {object} opts Options for SonicBoom
|
||||
*
|
||||
* @returns {object} A new SonicBoom stream
|
||||
*/
|
||||
function buildSafeSonicBoom(opts: SonicBoomOpts) {
|
||||
const stream = new SonicBoom(opts);
|
||||
stream.on('error', filterBrokenPipe);
|
||||
if (!opts.sync && isMainThread) {
|
||||
setupOnExit(stream);
|
||||
}
|
||||
return stream;
|
||||
|
||||
function filterBrokenPipe(err) {
|
||||
if (err.code === 'EPIPE') {
|
||||
// @ts-ignore
|
||||
stream.write = noop;
|
||||
stream.end = noop;
|
||||
stream.flushSync = noop;
|
||||
stream.destroy = noop;
|
||||
return;
|
||||
}
|
||||
stream.removeListener('error', filterBrokenPipe);
|
||||
}
|
||||
}
|
||||
|
||||
function setupOnExit(stream) {
|
||||
/* istanbul ignore next */
|
||||
if (global.WeakRef && global.WeakMap && global.FinalizationRegistry) {
|
||||
// This is leak free, it does not leave event handlers
|
||||
const onExit = require('on-exit-leak-free');
|
||||
|
||||
onExit.register(stream, autoEnd);
|
||||
|
||||
stream.on('close', function () {
|
||||
onExit.unregister(stream);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
function autoEnd(stream, eventName) {
|
||||
// This check is needed only on some platforms
|
||||
|
||||
if (stream.destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventName === 'beforeExit') {
|
||||
// We still have an event loop, let's use it
|
||||
stream.flush();
|
||||
stream.on('drain', function () {
|
||||
stream.end();
|
||||
});
|
||||
} else {
|
||||
// We do not have an event loop, so flush synchronously
|
||||
stream.flushSync();
|
||||
}
|
||||
}
|
||||
|
||||
export function hasColors(colors: boolean | undefined) {
|
||||
if (colors) {
|
||||
return isColorSupported;
|
||||
}
|
||||
return typeof colors === 'undefined' ? true : colors;
|
||||
}
|
||||
|
||||
export function buildPretty(opts: PrettyOptionsExtended) {
|
||||
return (chunk) => {
|
||||
const colors = hasColors(opts.colors);
|
||||
return printMessage(chunk, { prettyStamp: opts.prettyStamp }, colors);
|
||||
};
|
||||
}
|
||||
|
||||
export default function (opts) {
|
||||
const pretty = buildPretty(opts);
|
||||
// @ts-ignore
|
||||
return build(function (source) {
|
||||
const stream = new Transform({
|
||||
objectMode: true,
|
||||
autoDestroy: true,
|
||||
transform(chunk, enc, cb) {
|
||||
const line = pretty(chunk) + '\n';
|
||||
cb(null, line);
|
||||
},
|
||||
});
|
||||
const destination = buildSafeSonicBoom({
|
||||
dest: opts.destination || 1,
|
||||
sync: opts.sync || true,
|
||||
}) as unknown as WriteStream;
|
||||
|
||||
source.on('unknown', function (line) {
|
||||
destination.write(line + '\n');
|
||||
});
|
||||
|
||||
pipeline(source, stream, destination, (err) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('prettify pipeline error ', err);
|
||||
});
|
||||
return stream;
|
||||
});
|
||||
}
|
|
@ -2,4 +2,5 @@ import { PrettyOptions } from 'pino';
|
|||
|
||||
export interface PrettyOptionsExtended extends PrettyOptions {
|
||||
prettyStamp: boolean;
|
||||
colors?: boolean;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ export function padRight(message: string, max = message.length + CUSTOM_PAD_LENG
|
|||
return message.padEnd(max, ' ');
|
||||
}
|
||||
|
||||
export function formatLoggingDate(time: number, message): string {
|
||||
export function formatLoggingDate(time: number, message: string): string {
|
||||
const timeFormatted = dayjs(time).format(FORMAT_DATE);
|
||||
|
||||
return `[${timeFormatted}]${message}`;
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`formatter printMessage should display a bytes request 1`] = `" [31mfatal[39m[37m[32m<--[39m[37m [33m200[39m[37m, user: [1mnull[22m([32m127.0.0.1[39m[37m), req: '[32mGET[39m[37m [32m/verdaccio[39m[37m', bytes: [33m0[39m[37m/[33m150186[39m[37m[39m"`;
|
||||
exports[`formatter printMessage should display a bytes request 1`] = `"fatal<-- 200, user: null(127.0.0.1), req: 'GET /verdaccio', bytes: 0/150186 "`;
|
||||
|
||||
exports[`formatter printMessage should display a resource request 1`] = `"info [32m<--[39m 127.0.0.1 requested 'GET /verdaccio' "`;
|
||||
exports[`formatter printMessage should display a resource request 1`] = `"info <-- 127.0.0.1 requested 'GET /verdaccio' "`;
|
||||
|
||||
exports[`formatter printMessage should display a streaming request 1`] = `" [31mfatal[39m[37m[33m-->[39m[37m [33m304[39m[37m, req: '[32mGET[39m[37m [32mhttps://registry.npmjs.org/verdaccio[39m[37m' (streaming)[39m"`;
|
||||
exports[`formatter printMessage should display a streaming request 1`] = `"fatal--> 304, req: 'GET https://registry.npmjs.org/verdaccio' (streaming) "`;
|
||||
|
||||
exports[`formatter printMessage should display an error request 1`] = `" [31mfatal[39m[37m[33m-->[39m[37m [31mERR[39m[37m, req: '[32mGET[39m[37m [32mhttps://registry.fake.org/aaa[39m[37m', error: [31mgetaddrinfo ENOTFOUND registry.fake.org[39m[37m[39m"`;
|
||||
exports[`formatter printMessage should display an error request 1`] = `"fatal--> ERR, req: 'GET https://registry.fake.org/aaa', error: getaddrinfo ENOTFOUND registry.fake.org "`;
|
||||
|
||||
exports[`formatter printMessage should display an fatal request 1`] = `" [31mfatal[39m[37m[33m-->[39m[37m [31mERR[39m[37m, req: '[32mGET[39m[37m [32mhttps://registry.fake.org/aaa[39m[37m', error: [31mfatal error[39m[37m[39m"`;
|
||||
exports[`formatter printMessage should display an fatal request 1`] = `"fatal--> ERR, req: 'GET https://registry.fake.org/aaa', error: fatal error "`;
|
||||
|
||||
exports[`formatter printMessage should display config file 1`] = `" [33mwarn [39m[37m[34m---[39m[37m config file - [32m/Users/user/.config/verdaccio/config/config.yaml[39m[37m[39m"`;
|
||||
exports[`formatter printMessage should display config file 1`] = `"warn --- config file - /Users/user/.config/verdaccio/config/config.yaml "`;
|
||||
|
||||
exports[`formatter printMessage should display custom log message 1`] = `" [31mfatal[39m[37m[34m---[39m[37m custom - [32mfoo[39m[37m - [90mundefined[39m[37m[39m"`;
|
||||
exports[`formatter printMessage should display custom log message 1`] = `"fatal--- custom - foo - undefined "`;
|
||||
|
||||
exports[`formatter printMessage should display trace level 1`] = `" [37mtrace[39m[37m[34m---[39m[37m [trace] - [32mfoo[39m[37m[39m"`;
|
||||
exports[`formatter printMessage should display trace level 1`] = `"trace--- [trace] - foo "`;
|
||||
|
||||
exports[`formatter printMessage should display trace level with pretty stamp 1`] = `"[formatted-date] [37mtrace[39m[37m[34m---[39m[37m [trace] - [32mfoo[39m[37m[39m"`;
|
||||
exports[`formatter printMessage should display trace level with pretty stamp 1`] = `"[formatted-date]trace--- [trace] - foo "`;
|
||||
|
||||
exports[`formatter printMessage should display version and http address 1`] = `" [33mwarn [39m[37m[34m---[39m[37m http address - [32mhttp://localhost:4873/[39m[37m - [32mverdaccio/5.0.0[39m[37m[39m"`;
|
||||
exports[`formatter printMessage should display version and http address 1`] = `"warn --- http address - http://localhost:4873/ - verdaccio/5.0.0 "`;
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`prettyFactory should return a function with options 1`] = `
|
||||
" [37mtrace[39m[37m[34m---[39m[37m [trace] - [32mfoo[39m[37m[39m
|
||||
"
|
||||
`;
|
|
@ -22,7 +22,7 @@ describe('formatter', () => {
|
|||
msg: 'config file - @{file}',
|
||||
};
|
||||
|
||||
expect(printMessage(log, prettyfierOptions)).toMatchSnapshot();
|
||||
expect(printMessage(log, prettyfierOptions, false)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should display trace level', () => {
|
||||
|
@ -32,7 +32,7 @@ describe('formatter', () => {
|
|||
msg: '[trace] - @{foo}',
|
||||
};
|
||||
|
||||
expect(printMessage(log, prettyfierOptions)).toMatchSnapshot();
|
||||
expect(printMessage(log, prettyfierOptions, false)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should display trace level with pretty stamp', () => {
|
||||
|
@ -48,7 +48,8 @@ describe('formatter', () => {
|
|||
log,
|
||||
Object.assign({}, prettyfierOptions, {
|
||||
prettyStamp: true,
|
||||
})
|
||||
}),
|
||||
false
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
@ -72,7 +73,7 @@ describe('formatter', () => {
|
|||
'bytes: @{bytes.in}/@{bytes.out}',
|
||||
};
|
||||
|
||||
expect(printMessage(log, prettyfierOptions)).toMatchSnapshot();
|
||||
expect(printMessage(log, prettyfierOptions, false)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should display an error request', () => {
|
||||
|
@ -101,7 +102,7 @@ describe('formatter', () => {
|
|||
msg: "@{!status}, req: '@{request.method} @{request.url}', error: @{!error}",
|
||||
};
|
||||
|
||||
expect(printMessage(log, prettyfierOptions)).toMatchSnapshot();
|
||||
expect(printMessage(log, prettyfierOptions, false)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should display an fatal request', () => {
|
||||
|
@ -126,7 +127,7 @@ describe('formatter', () => {
|
|||
msg: "@{!status}, req: '@{request.method} @{request.url}', error: @{!error}",
|
||||
};
|
||||
|
||||
expect(printMessage(log, prettyfierOptions)).toMatchSnapshot();
|
||||
expect(printMessage(log, prettyfierOptions, false)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should display a streaming request', () => {
|
||||
|
@ -142,7 +143,7 @@ describe('formatter', () => {
|
|||
msg: "@{!status}, req: '@{request.method} @{request.url}' (streaming)",
|
||||
};
|
||||
|
||||
expect(printMessage(log, prettyfierOptions)).toMatchSnapshot();
|
||||
expect(printMessage(log, prettyfierOptions, false)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should display version and http address', () => {
|
||||
|
@ -157,7 +158,7 @@ describe('formatter', () => {
|
|||
msg: 'http address - @{addr} - @{version}',
|
||||
};
|
||||
|
||||
expect(printMessage(log, prettyfierOptions)).toMatchSnapshot();
|
||||
expect(printMessage(log, prettyfierOptions, false)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should display custom log message', () => {
|
||||
|
@ -168,7 +169,7 @@ describe('formatter', () => {
|
|||
msg: 'custom - @{something} - @{missingParam}',
|
||||
};
|
||||
|
||||
expect(printMessage(log, prettyfierOptions)).toMatchSnapshot();
|
||||
expect(printMessage(log, prettyfierOptions, false)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should display a resource request', () => {
|
||||
|
|
|
@ -1,18 +1,28 @@
|
|||
import * as factory from '../src';
|
||||
import pino from 'pino';
|
||||
import { Writable } from 'stream';
|
||||
|
||||
import { buildPretty } from '../src';
|
||||
|
||||
describe('prettyFactory', () => {
|
||||
const prettyfierOptions = { messageKey: 'msg', levelFirst: true, prettyStamp: false };
|
||||
test('should return a function', () => {
|
||||
expect(typeof factory['default']({})).toEqual('function');
|
||||
});
|
||||
|
||||
test('should return a function with options', () => {
|
||||
const log = {
|
||||
level: 10,
|
||||
foo: 'foo',
|
||||
msg: '[trace] - @{foo}',
|
||||
const prettyfierOptions = {
|
||||
messageKey: 'msg',
|
||||
levelFirst: true,
|
||||
prettyStamp: false,
|
||||
colors: false,
|
||||
};
|
||||
|
||||
expect(factory['default'](prettyfierOptions)(log)).toMatchSnapshot();
|
||||
test('should return a function', (done) => {
|
||||
const pretty = buildPretty(prettyfierOptions);
|
||||
const log = pino(
|
||||
new Writable({
|
||||
objectMode: true,
|
||||
write(chunk, enc, cb) {
|
||||
const formatted = pretty(JSON.parse(chunk));
|
||||
expect(formatted).toBe('info --- test message ');
|
||||
cb();
|
||||
done();
|
||||
},
|
||||
})
|
||||
);
|
||||
log.info({ test: 'test' }, '@{test} message');
|
||||
});
|
||||
});
|
||||
|
|
20
packages/logger-prettify/test/utils.test.ts
Normal file
20
packages/logger-prettify/test/utils.test.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { formatLoggingDate, padLeft, padRight } from '../src/utils';
|
||||
|
||||
describe('formatLoggingDate', () => {
|
||||
test('basic', () => {
|
||||
expect(formatLoggingDate(1585411248203, ' message')).toEqual('[2020-03-28 16:00:48] message');
|
||||
});
|
||||
});
|
||||
|
||||
describe('pad', () => {
|
||||
test('pad right with custom length', () => {
|
||||
expect(padRight('message right', 20)).toEqual('message right ');
|
||||
});
|
||||
|
||||
test('pad right 2', () => {
|
||||
expect(padRight('message right')).toEqual('message right ');
|
||||
});
|
||||
test('pad left', () => {
|
||||
expect(padLeft('message left')).toEqual(' message left');
|
||||
});
|
||||
});
|
|
@ -31,7 +31,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf ./build",
|
||||
"test": "jest",
|
||||
"test": "cross-env TZ=utc jest",
|
||||
"type-check": "tsc --noEmit -p tsconfig.build.json",
|
||||
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
|
||||
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
|
||||
|
@ -41,10 +41,9 @@
|
|||
"dependencies": {
|
||||
"@verdaccio/core": "workspace:6.0.0-6-next.5",
|
||||
"@verdaccio/logger-prettify": "workspace:6.0.0-6-next.6",
|
||||
"pino-pretty": "7.6.1",
|
||||
"debug": "4.3.4",
|
||||
"lodash": "4.17.21",
|
||||
"pino": "7.11.0"
|
||||
"colorette": "2.0.7",
|
||||
"pino": "8.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@verdaccio/types": "workspace:11.0.0-6-next.12"
|
||||
|
|
|
@ -1 +1 @@
|
|||
export { setup, createLogger, logger, LoggerConfigItem } from './logger';
|
||||
export { setup, createLogger, logger, prepareSetup } from './logger';
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
// <reference types="node" />
|
||||
import { isColorSupported } from 'colorette';
|
||||
import buildDebug from 'debug';
|
||||
import _ from 'lodash';
|
||||
import pino from 'pino';
|
||||
import pino, { Logger } from 'pino';
|
||||
|
||||
import { warningUtils } from '@verdaccio/core';
|
||||
import prettifier, { fillInMsgTemplate } from '@verdaccio/logger-prettify';
|
||||
import { fillInMsgTemplate } from '@verdaccio/logger-prettify';
|
||||
import { LoggerConfigItem, LoggerFormat } from '@verdaccio/types';
|
||||
|
||||
const debug = buildDebug('verdaccio:logger');
|
||||
|
||||
export let logger;
|
||||
|
||||
function isProd() {
|
||||
return process.env.NODE_ENV === 'production';
|
||||
}
|
||||
|
||||
function hasColors(colors: boolean | undefined) {
|
||||
if (colors) {
|
||||
return isColorSupported;
|
||||
}
|
||||
return typeof colors === 'undefined' ? true : colors;
|
||||
}
|
||||
|
||||
const DEFAULT_LOG_FORMAT = isProd() ? 'json' : 'pretty';
|
||||
|
||||
export type LogPlugin = {
|
||||
|
@ -20,28 +26,19 @@ export type LogPlugin = {
|
|||
options?: any[];
|
||||
};
|
||||
|
||||
export type LogType = 'file' | 'stdout';
|
||||
export type LogFormat = 'json' | 'pretty-timestamped' | 'pretty';
|
||||
type LoggerOptions = { level?: string; path?: string; colors?: boolean; sync?: boolean };
|
||||
|
||||
export function createLogger(
|
||||
options = { level: 'http' },
|
||||
destination = pino.destination(1),
|
||||
prettyPrintOptions = {
|
||||
// we hide warning since the prettifier should not be used in production
|
||||
// https://getpino.io/#/docs/pretty?id=prettifier-api
|
||||
suppressFlushSyncWarning: true,
|
||||
},
|
||||
format: LogFormat = DEFAULT_LOG_FORMAT
|
||||
options: LoggerOptions = { level: 'http' },
|
||||
// eslint-disable-next-line no-undef
|
||||
destination: NodeJS.WritableStream = pino.destination(1),
|
||||
format: LoggerFormat = DEFAULT_LOG_FORMAT
|
||||
) {
|
||||
if (_.isNil(format)) {
|
||||
format = DEFAULT_LOG_FORMAT;
|
||||
}
|
||||
|
||||
debug('setup logger');
|
||||
let pinoConfig = {
|
||||
customLevels: {
|
||||
http: 25,
|
||||
},
|
||||
...options,
|
||||
level: options.level,
|
||||
serializers: {
|
||||
err: pino.stdSerializers.err,
|
||||
|
@ -52,23 +49,32 @@ export function createLogger(
|
|||
|
||||
debug('has prettifier? %o', !isProd());
|
||||
// pretty logs are not allowed in production for performance reasons
|
||||
if ((format === DEFAULT_LOG_FORMAT || format !== 'json') && isProd() === false) {
|
||||
if (['pretty-timestamped', 'pretty'].includes(format) && isProd() === false) {
|
||||
pinoConfig = Object.assign({}, pinoConfig, {
|
||||
prettifier,
|
||||
// more info
|
||||
// https://github.com/pinojs/pino-pretty/issues/37
|
||||
prettyPrint: {
|
||||
levelFirst: true,
|
||||
transport: {
|
||||
target: '@verdaccio/logger-prettify',
|
||||
options: {
|
||||
// string or 1 (file descriptor for process.stdout)
|
||||
destination: options.path || 1,
|
||||
colors: hasColors(options.colors),
|
||||
prettyStamp: format === 'pretty-timestamped',
|
||||
...prettyPrintOptions,
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
pinoConfig = Object.assign({}, pinoConfig, {
|
||||
pinoConfig = {
|
||||
...pinoConfig,
|
||||
// more info
|
||||
// https://github.com/pinojs/pino/blob/v7.1.0/docs/api.md#hooks-object
|
||||
// TODO: improve typings here
|
||||
// @ts-ignore
|
||||
hooks: {
|
||||
logMethod(inputArgs, method) {
|
||||
logMethod(
|
||||
inputArgs: [any, any, ...any[]],
|
||||
method: {
|
||||
apply: (arg0: { logMethod: (inputArgs: any, method: any) => any }, arg1: any[]) => any;
|
||||
}
|
||||
) {
|
||||
const [templateObject, message, ...otherArgs] = inputArgs;
|
||||
const templateVars =
|
||||
!!templateObject && typeof templateObject === 'object'
|
||||
|
@ -79,10 +85,12 @@ export function createLogger(
|
|||
return method.apply(this, [templateObject, hydratedMessage, ...otherArgs]);
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
const logger = pino(pinoConfig, destination);
|
||||
|
||||
/* eslint-disable */
|
||||
/* istanbul ignore next */
|
||||
if (process.env.DEBUG) {
|
||||
logger.on('level-change', (lvl, val, prevLvl, prevVal) => {
|
||||
debug('%s (%d) was changed to %s (%d)', lvl, val, prevLvl, prevVal);
|
||||
|
@ -92,34 +100,20 @@ export function createLogger(
|
|||
return logger;
|
||||
}
|
||||
|
||||
export function getLogger() {
|
||||
if (_.isNil(logger)) {
|
||||
// FIXME: not sure about display here a warning
|
||||
warningUtils.emit(warningUtils.Codes.VERWAR002);
|
||||
return;
|
||||
}
|
||||
|
||||
return logger;
|
||||
}
|
||||
|
||||
const DEFAULT_LOGGER_CONF: LoggerConfigItem = {
|
||||
type: 'stdout',
|
||||
format: 'pretty',
|
||||
level: 'http',
|
||||
};
|
||||
|
||||
export type LoggerConfigItem = {
|
||||
type?: LogType;
|
||||
plugin?: LogPlugin;
|
||||
format?: LogFormat;
|
||||
path?: string;
|
||||
level?: string;
|
||||
};
|
||||
|
||||
export type LoggerConfig = LoggerConfigItem;
|
||||
|
||||
export function setup(options: LoggerConfigItem = DEFAULT_LOGGER_CONF) {
|
||||
debug('setup logger');
|
||||
export function prepareSetup(options: LoggerConfigItem = DEFAULT_LOGGER_CONF) {
|
||||
let logger: Logger<{
|
||||
customLevels: { http: number };
|
||||
level: string | undefined;
|
||||
serializers: { err: any; req: any; res: any };
|
||||
}>;
|
||||
let loggerConfig = options;
|
||||
if (!loggerConfig?.level) {
|
||||
loggerConfig = Object.assign(
|
||||
|
@ -134,40 +128,35 @@ export function setup(options: LoggerConfigItem = DEFAULT_LOGGER_CONF) {
|
|||
if (loggerConfig.type === 'file') {
|
||||
debug('logging file enabled');
|
||||
const destination = pino.destination(loggerConfig.path);
|
||||
/* eslint-disable */
|
||||
/* istanbul ignore next */
|
||||
process.on('SIGUSR2', () => destination.reopen());
|
||||
// @ts-ignore
|
||||
logger = createLogger(pinoConfig, destination, loggerConfig.format);
|
||||
// @ts-ignore
|
||||
} else if (loggerConfig.type === 'rotating-file') {
|
||||
warningUtils.emit(warningUtils.Codes.VERWAR003);
|
||||
debug('logging stdout enabled');
|
||||
// @ts-ignore
|
||||
logger = createLogger(pinoConfig, pino.destination(1), loggerConfig.format);
|
||||
logger = createLogger(
|
||||
{ level: loggerConfig.level, path: loggerConfig.path, colors: loggerConfig.colors },
|
||||
destination,
|
||||
loggerConfig.format
|
||||
);
|
||||
return logger;
|
||||
} else {
|
||||
debug('logging stdout enabled');
|
||||
// @ts-ignore
|
||||
logger = createLogger(pinoConfig, pino.destination(1), loggerConfig.format);
|
||||
}
|
||||
|
||||
if (isProd()) {
|
||||
// why only on prod? https://github.com/pinojs/pino/issues/920#issuecomment-710807667
|
||||
const finalHandler = pino.final(logger, (err, finalLogger, event) => {
|
||||
finalLogger.info(`${event} caught`);
|
||||
if (err) {
|
||||
finalLogger.error(err, 'error caused exit');
|
||||
}
|
||||
process.exit(err ? 1 : 0);
|
||||
});
|
||||
|
||||
process.on('uncaughtException', (err) => finalHandler(err, 'uncaughtException'));
|
||||
process.on('unhandledRejection', (err) => finalHandler(err as Error, 'unhandledRejection'));
|
||||
process.on('beforeExit', () => finalHandler(null, 'beforeExit'));
|
||||
process.on('exit', () => finalHandler(null, 'exit'));
|
||||
process.on('uncaughtException', (err) => finalHandler(err, 'uncaughtException'));
|
||||
process.on('SIGINT', () => finalHandler(null, 'SIGINT'));
|
||||
process.on('SIGQUIT', () => finalHandler(null, 'SIGQUIT'));
|
||||
process.on('SIGTERM', () => finalHandler(null, 'SIGTERM'));
|
||||
}
|
||||
|
||||
logger = createLogger(
|
||||
{ level: loggerConfig.level, colors: loggerConfig.colors },
|
||||
pino.destination(1),
|
||||
loggerConfig.format
|
||||
);
|
||||
return logger;
|
||||
}
|
||||
}
|
||||
|
||||
export let logger: Logger;
|
||||
|
||||
export function setup(options: LoggerConfigItem) {
|
||||
if (typeof logger !== 'undefined') {
|
||||
return logger;
|
||||
}
|
||||
|
||||
logger = prepareSetup(options);
|
||||
return logger;
|
||||
}
|
||||
|
|
20
packages/logger/test/createLogger.spec.ts
Normal file
20
packages/logger/test/createLogger.spec.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { Writable } from 'stream';
|
||||
|
||||
import { createLogger } from '../src';
|
||||
|
||||
describe('logger test', () => {
|
||||
describe('json format', () => {
|
||||
test('should write json to a stream', () => {
|
||||
const stream = new Writable({
|
||||
write(chunk, encoding, callback) {
|
||||
expect(JSON.parse(chunk.toString())).toEqual(
|
||||
expect.objectContaining({ level: 30, msg: 'test' })
|
||||
);
|
||||
callback();
|
||||
},
|
||||
});
|
||||
const logger = createLogger({ level: 'http' }, stream, 'json');
|
||||
logger.info('test');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,51 +1,115 @@
|
|||
import { logger, setup } from '../src';
|
||||
import { readFile } from 'fs/promises';
|
||||
import { join } from 'path';
|
||||
import { setTimeout } from 'timers/promises';
|
||||
|
||||
const mockWarningUtils = jest.fn();
|
||||
import { fileUtils } from '@verdaccio/core';
|
||||
|
||||
jest.mock('@verdaccio/core', () => {
|
||||
const original = jest.requireActual('@verdaccio/core');
|
||||
return {
|
||||
warningUtils: {
|
||||
...original.warningUtils,
|
||||
emit: (...args) => {
|
||||
mockWarningUtils(...args);
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
import { prepareSetup } from '../src';
|
||||
|
||||
describe('logger', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
async function readLogFile(path: string) {
|
||||
await setTimeout(1000, 'resolved');
|
||||
return readFile(path, 'utf8');
|
||||
}
|
||||
|
||||
test.skip('should write message logger', () => {
|
||||
jest.spyOn(process.stdout, 'write');
|
||||
setup([
|
||||
{
|
||||
level: 'info',
|
||||
},
|
||||
]);
|
||||
async function createLogFile() {
|
||||
const folder = await fileUtils.createTempFolder('logger-1');
|
||||
const file = join(folder, 'logger.log');
|
||||
return file;
|
||||
}
|
||||
|
||||
logger.info({ packageName: 'test' }, `publishing or updating a new version for @{packageName}`);
|
||||
// FIXME: check expect
|
||||
// expect(spyOn).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
test.skip('throw deprecation warning if multiple loggers configured', () => {
|
||||
setup([
|
||||
{
|
||||
level: 'info',
|
||||
},
|
||||
{
|
||||
const defaultOptions = {
|
||||
format: 'json',
|
||||
level: 'http',
|
||||
},
|
||||
]);
|
||||
// expect(mockWarningUtils).toHaveBeenCalledWith(warningUtils.Codes.VERDEP002);
|
||||
colors: false,
|
||||
};
|
||||
|
||||
describe('logger test', () => {
|
||||
describe('basic', () => {
|
||||
test('should include default level', async () => {
|
||||
const file = await createLogFile();
|
||||
const logger = prepareSetup({ type: 'file', path: file, colors: false });
|
||||
logger.info({ packageName: 'test' }, `testing @{packageName}`);
|
||||
// Note: this should not be logged
|
||||
logger.debug(`this should not be logged`);
|
||||
// Note: this should not be logged
|
||||
logger.trace(`this should not be logged`);
|
||||
logger.error(`this should logged`);
|
||||
const content = await readLogFile(file);
|
||||
expect(content).toBe('info --- testing test \nerror--- this should logged \n');
|
||||
});
|
||||
|
||||
test('regression: do not throw deprecation warning if no logger config is provided', () => {
|
||||
setup();
|
||||
expect(mockWarningUtils).not.toHaveBeenCalled();
|
||||
test('should include all logging level', async () => {
|
||||
const file = await createLogFile();
|
||||
const logger = prepareSetup({ type: 'file', level: 'trace', path: file, colors: false });
|
||||
logger.info({ packageName: 'test' }, `testing @{packageName}`);
|
||||
logger.debug(`this should not be logged`);
|
||||
logger.trace(`this should not be logged`);
|
||||
logger.error(`this should logged`);
|
||||
const content = await readLogFile(file);
|
||||
expect(content).toBe(
|
||||
'info --- testing test \ndebug--- this should not be logged \ntrace--- this should not be logged \nerror--- this should logged \n'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('json format', () => {
|
||||
test('should log into a file with json format', async () => {
|
||||
const file = await createLogFile();
|
||||
const logger = prepareSetup({
|
||||
...defaultOptions,
|
||||
format: 'json',
|
||||
type: 'file',
|
||||
path: file,
|
||||
level: 'info',
|
||||
});
|
||||
logger.info(
|
||||
{ packageName: 'test' },
|
||||
`publishing or updating a new version for @{packageName}`
|
||||
);
|
||||
const content = await readLogFile(file);
|
||||
expect(JSON.parse(content)).toEqual(
|
||||
expect.objectContaining({
|
||||
level: 30,
|
||||
msg: 'publishing or updating a new version for test',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('pretty format', () => {
|
||||
test('should log into a file with pretty', async () => {
|
||||
const file = await createLogFile();
|
||||
const logger = prepareSetup({
|
||||
format: 'pretty',
|
||||
type: 'file',
|
||||
path: file,
|
||||
level: 'trace',
|
||||
colors: false,
|
||||
});
|
||||
logger.info(
|
||||
{ packageName: 'test' },
|
||||
`publishing or updating a new version for @{packageName}`
|
||||
);
|
||||
const content = await readLogFile(file);
|
||||
expect(content).toEqual('info --- publishing or updating a new version for test \n');
|
||||
});
|
||||
|
||||
test('should log into a file with pretty-timestamped', async () => {
|
||||
const file = await createLogFile();
|
||||
const logger = prepareSetup({
|
||||
format: 'pretty-timestamped',
|
||||
type: 'file',
|
||||
path: file,
|
||||
level: 'trace',
|
||||
colors: false,
|
||||
});
|
||||
logger.info(
|
||||
{ packageName: 'test' },
|
||||
`publishing or updating a new version for @{packageName}`
|
||||
);
|
||||
const content = await readLogFile(file);
|
||||
// TODO: we might want mock time for testing
|
||||
expect(content).toMatch('info --- publishing or updating a new version for test \n');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ 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 implements IPluginMiddleware<{}, {}> {
|
||||
public enabled: boolean;
|
||||
public logger: Logger;
|
||||
public strict_ssl: boolean;
|
||||
|
|
|
@ -6,6 +6,7 @@ module.exports = {
|
|||
},
|
||||
globals: {
|
||||
__APP_VERSION__: true,
|
||||
NodeJS: true,
|
||||
},
|
||||
parserOptions: {
|
||||
allowImportExportEverywhere: true,
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
"types": "build/index.d.ts",
|
||||
"scripts": {
|
||||
"clean": "rimraf ./build",
|
||||
"test": "jest",
|
||||
"test": "echo 0",
|
||||
"type-check": "tsc --noEmit -p tsconfig.build.json",
|
||||
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
|
||||
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
|
||||
|
|
275
pnpm-lock.yaml
275
pnpm-lock.yaml
|
@ -381,10 +381,12 @@ importers:
|
|||
packages/core/types:
|
||||
specifiers:
|
||||
'@types/node': 16.11.47
|
||||
tsd: 0.22.0
|
||||
typedoc: beta
|
||||
typedoc-plugin-missing-exports: 1.0.0
|
||||
devDependencies:
|
||||
'@types/node': 16.11.47
|
||||
tsd: 0.22.0
|
||||
typedoc: 0.23.0-beta.7_typescript@4.7.4
|
||||
typedoc-plugin-missing-exports: 1.0.0_typedoc@0.23.0-beta.7
|
||||
|
||||
packages/core/url:
|
||||
specifiers:
|
||||
|
@ -452,36 +454,34 @@ importers:
|
|||
'@verdaccio/core': workspace:6.0.0-6-next.5
|
||||
'@verdaccio/logger-prettify': workspace:6.0.0-6-next.6
|
||||
'@verdaccio/types': workspace:11.0.0-6-next.12
|
||||
colorette: 2.0.7
|
||||
debug: 4.3.4
|
||||
lodash: 4.17.21
|
||||
pino: 7.11.0
|
||||
pino-pretty: 7.6.1
|
||||
pino: 8.4.1
|
||||
dependencies:
|
||||
'@verdaccio/core': link:../core/core
|
||||
'@verdaccio/logger-prettify': link:../logger-prettify
|
||||
colorette: 2.0.7
|
||||
debug: 4.3.4
|
||||
lodash: 4.17.21
|
||||
pino: 7.11.0
|
||||
pino-pretty: 7.6.1
|
||||
pino: 8.4.1
|
||||
devDependencies:
|
||||
'@verdaccio/types': link:../core/types
|
||||
|
||||
packages/logger-prettify:
|
||||
specifiers:
|
||||
colorette: 2.0.7
|
||||
dayjs: 1.11.4
|
||||
fast-safe-stringify: 2.1.1
|
||||
kleur: 3.0.3
|
||||
lodash: 4.17.21
|
||||
pino: 7.11.0
|
||||
prettier-bytes: 1.0.4
|
||||
pino: 8.4.1
|
||||
pino-abstract-transport: 1.0.0
|
||||
sonic-boom: 3.2.0
|
||||
dependencies:
|
||||
colorette: 2.0.7
|
||||
dayjs: 1.11.4
|
||||
fast-safe-stringify: 2.1.1
|
||||
kleur: 3.0.3
|
||||
lodash: 4.17.21
|
||||
prettier-bytes: 1.0.4
|
||||
pino-abstract-transport: 1.0.0
|
||||
sonic-boom: 3.2.0
|
||||
devDependencies:
|
||||
pino: 7.11.0
|
||||
pino: 8.4.1
|
||||
|
||||
packages/middleware:
|
||||
specifiers:
|
||||
|
@ -1291,7 +1291,7 @@ importers:
|
|||
npm: next-8
|
||||
dependencies:
|
||||
'@verdaccio/test-cli-commons': link:../cli-commons
|
||||
npm: 8.16.0
|
||||
npm: 8.18.0
|
||||
|
||||
test/cli/e2e-pnpm6:
|
||||
specifiers:
|
||||
|
@ -1307,7 +1307,7 @@ importers:
|
|||
pnpm: next-7
|
||||
dependencies:
|
||||
'@verdaccio/test-cli-commons': link:../cli-commons
|
||||
pnpm: 7.9.0
|
||||
pnpm: 7.9.4-0
|
||||
|
||||
test/cli/e2e-yarn1:
|
||||
specifiers:
|
||||
|
@ -7188,11 +7188,6 @@ packages:
|
|||
/@tsconfig/node16/1.0.2:
|
||||
resolution: {integrity: sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==}
|
||||
|
||||
/@tsd/typescript/4.7.4:
|
||||
resolution: {integrity: sha512-jbtC+RgKZ9Kk65zuRZbKLTACf+tvFW4Rfq0JEMXrlmV3P3yme+Hm+pnb5fJRyt61SjIitcrC810wj7+1tgsEmg==}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/@types/aria-query/4.2.0:
|
||||
resolution: {integrity: sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A==}
|
||||
dev: true
|
||||
|
@ -8587,16 +8582,6 @@ packages:
|
|||
/argparse/2.0.1:
|
||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||
|
||||
/args/5.0.1:
|
||||
resolution: {integrity: sha512-1kqmFCFsPffavQFGt8OxJdIcETti99kySRUPMpOhaGjL6mRJn8HFU1OxKY5bMqfZKUwTQc1mZkAjmGYaVOHFtQ==}
|
||||
engines: {node: '>= 6.0.0'}
|
||||
dependencies:
|
||||
camelcase: 5.0.0
|
||||
chalk: 2.4.2
|
||||
leven: 2.1.0
|
||||
mri: 1.1.4
|
||||
dev: false
|
||||
|
||||
/argv/0.0.2:
|
||||
resolution: {integrity: sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=}
|
||||
engines: {node: '>=0.6.10'}
|
||||
|
@ -9352,7 +9337,6 @@ packages:
|
|||
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
|
||||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
dev: false
|
||||
|
||||
/braces/2.3.2:
|
||||
resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==}
|
||||
|
@ -9558,11 +9542,6 @@ packages:
|
|||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/camelcase/5.0.0:
|
||||
resolution: {integrity: sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==}
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/camelcase/5.3.1:
|
||||
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -9992,6 +9971,10 @@ packages:
|
|||
/colorette/2.0.16:
|
||||
resolution: {integrity: sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==}
|
||||
|
||||
/colorette/2.0.7:
|
||||
resolution: {integrity: sha512-wSXeeDPxoi5xKvjvOGxyYlyqB3J+tbowaSsFm1rEsDsDE942aTLftbOE3XMqf3XaYC7QUtcd/3qadNAIEIsAYw==}
|
||||
dev: false
|
||||
|
||||
/combine-promises/1.1.0:
|
||||
resolution: {integrity: sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -10962,10 +10945,6 @@ packages:
|
|||
engines: {node: '>=0.11'}
|
||||
dev: true
|
||||
|
||||
/dateformat/4.6.3:
|
||||
resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==}
|
||||
dev: false
|
||||
|
||||
/dayjs/1.11.3:
|
||||
resolution: {integrity: sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==}
|
||||
dev: false
|
||||
|
@ -11586,14 +11565,6 @@ packages:
|
|||
/duplexer3/0.1.4:
|
||||
resolution: {integrity: sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=}
|
||||
|
||||
/duplexify/4.1.2:
|
||||
resolution: {integrity: sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==}
|
||||
dependencies:
|
||||
end-of-stream: 1.4.4
|
||||
inherits: 2.0.4
|
||||
readable-stream: 3.6.0
|
||||
stream-shift: 1.0.1
|
||||
|
||||
/eastasianwidth/0.2.0:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
|
||||
|
@ -12202,20 +12173,6 @@ packages:
|
|||
eslint: 8.21.0
|
||||
dev: false
|
||||
|
||||
/eslint-formatter-pretty/4.1.0:
|
||||
resolution: {integrity: sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
'@types/eslint': 7.28.2
|
||||
ansi-escapes: 4.3.2
|
||||
chalk: 4.1.2
|
||||
eslint-rule-docs: 1.1.231
|
||||
log-symbols: 4.1.0
|
||||
plur: 4.0.0
|
||||
string-width: 4.2.3
|
||||
supports-hyperlinks: 2.2.0
|
||||
dev: true
|
||||
|
||||
/eslint-import-resolver-node/0.3.6:
|
||||
resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==}
|
||||
dependencies:
|
||||
|
@ -12405,10 +12362,6 @@ packages:
|
|||
engines: {node: '>=4.0.0'}
|
||||
dev: false
|
||||
|
||||
/eslint-rule-docs/1.1.231:
|
||||
resolution: {integrity: sha512-egHz9A1WG7b8CS0x1P6P/Rj5FqZOjray/VjpJa14tMZalfRKvpE2ONJ3plCM7+PcinmU4tcmbPLv0VtwzSdLVA==}
|
||||
dev: true
|
||||
|
||||
/eslint-scope/5.1.1:
|
||||
resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
@ -14640,11 +14593,6 @@ packages:
|
|||
resolution: {integrity: sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
/irregular-plurals/3.3.0:
|
||||
resolution: {integrity: sha512-MVBLKUTangM3EfRPFROhmWQQKRDsrgI83J8GS3jXy+OwYqiR2/aoWndYQ5416jLE3uaGgLH7ncme3X9y09gZ3g==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/is-absolute-url/3.0.3:
|
||||
resolution: {integrity: sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -15607,11 +15555,6 @@ packages:
|
|||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/joycon/3.1.1:
|
||||
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/js-base64/3.7.2:
|
||||
resolution: {integrity: sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==}
|
||||
dev: true
|
||||
|
@ -15832,6 +15775,10 @@ packages:
|
|||
engines: {node: '>=6'}
|
||||
hasBin: true
|
||||
|
||||
/jsonc-parser/3.1.0:
|
||||
resolution: {integrity: sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==}
|
||||
dev: true
|
||||
|
||||
/jsonfile/4.0.0:
|
||||
resolution: {integrity: sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=}
|
||||
optionalDependencies:
|
||||
|
@ -16124,11 +16071,6 @@ packages:
|
|||
dependencies:
|
||||
package-json: 6.5.0
|
||||
|
||||
/leven/2.1.0:
|
||||
resolution: {integrity: sha1-wuep93IJTe6dNCAq6KzORoeHVYA=}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/leven/3.1.0:
|
||||
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -16506,7 +16448,6 @@ packages:
|
|||
|
||||
/lunr/2.3.9:
|
||||
resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==}
|
||||
dev: false
|
||||
|
||||
/lz-string/1.4.4:
|
||||
resolution: {integrity: sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=}
|
||||
|
@ -16582,7 +16523,6 @@ packages:
|
|||
resolution: {integrity: sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==}
|
||||
engines: {node: '>= 12'}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/mathml-tag-names/2.1.3:
|
||||
resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==}
|
||||
|
@ -17270,7 +17210,6 @@ packages:
|
|||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
brace-expansion: 2.0.1
|
||||
dev: false
|
||||
|
||||
/minimist-options/4.1.0:
|
||||
resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
|
||||
|
@ -17331,11 +17270,6 @@ packages:
|
|||
resolution: {integrity: sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==}
|
||||
dev: false
|
||||
|
||||
/mri/1.1.4:
|
||||
resolution: {integrity: sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==}
|
||||
engines: {node: '>=4'}
|
||||
dev: false
|
||||
|
||||
/mri/1.2.0:
|
||||
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||
engines: {node: '>=4'}
|
||||
|
@ -17921,8 +17855,8 @@ packages:
|
|||
- which
|
||||
- write-file-atomic
|
||||
|
||||
/npm/8.16.0:
|
||||
resolution: {integrity: sha512-UfLT/hCbcpV9uiTEBthyrOlQxwk8LG5tAGn283g7f7pRx41KcwFiHV7HYgYm2y2GabfnPtf897ptrXRQwxJWzQ==}
|
||||
/npm/8.18.0:
|
||||
resolution: {integrity: sha512-G07/yKvNUwhwxYhk8BxcuDPB/4s+y755i6CnH3lf9LQBHP5siUx66WbuNGWEnN3xaBER4+IR3OWApKX7eBO5Dw==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
@ -18130,9 +18064,6 @@ packages:
|
|||
/obuf/1.1.2:
|
||||
resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
|
||||
|
||||
/on-exit-leak-free/0.2.0:
|
||||
resolution: {integrity: sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==}
|
||||
|
||||
/on-exit-leak-free/2.1.0:
|
||||
resolution: {integrity: sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==}
|
||||
|
||||
|
@ -18560,47 +18491,22 @@ packages:
|
|||
resolution: {integrity: sha1-clVrgM+g1IqXToDnckjoDtT3+HA=}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
/pino-abstract-transport/0.5.0:
|
||||
resolution: {integrity: sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==}
|
||||
dependencies:
|
||||
duplexify: 4.1.2
|
||||
split2: 4.1.0
|
||||
|
||||
/pino-abstract-transport/1.0.0:
|
||||
resolution: {integrity: sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==}
|
||||
dependencies:
|
||||
readable-stream: 4.0.0
|
||||
split2: 4.1.0
|
||||
|
||||
/pino-pretty/7.6.1:
|
||||
resolution: {integrity: sha512-H7N6ZYkiyrfwBGW9CSjx0uyO9Q2Lyt73881+OTYk8v3TiTdgN92QHrWlEq/LeWw5XtDP64jeSk3mnc6T+xX9/w==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
args: 5.0.1
|
||||
colorette: 2.0.16
|
||||
dateformat: 4.6.3
|
||||
fast-safe-stringify: 2.1.1
|
||||
joycon: 3.1.1
|
||||
on-exit-leak-free: 0.2.0
|
||||
pino-abstract-transport: 0.5.0
|
||||
pump: 3.0.0
|
||||
readable-stream: 3.6.0
|
||||
rfdc: 1.3.0
|
||||
secure-json-parse: 2.4.0
|
||||
sonic-boom: 2.2.3
|
||||
strip-json-comments: 3.1.1
|
||||
dev: false
|
||||
|
||||
/pino-std-serializers/3.2.0:
|
||||
resolution: {integrity: sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==}
|
||||
dev: false
|
||||
|
||||
/pino-std-serializers/4.0.0:
|
||||
resolution: {integrity: sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==}
|
||||
|
||||
/pino-std-serializers/5.6.0:
|
||||
resolution: {integrity: sha512-VdUXCw8gO+xhir7sFuoYSjTnzB+TMDGxhAC/ph3YS3sdHnXNdsK0wMtADNUltfeGkn2KDxEM21fnjF3RwXyC8A==}
|
||||
|
||||
/pino-std-serializers/6.0.0:
|
||||
resolution: {integrity: sha512-mMMOwSKrmyl+Y12Ri2xhH1lbzQxwwpuru9VjyJpgFIH4asSj88F2csdMwN6+M5g1Ll4rmsYghHLQJw81tgZ7LQ==}
|
||||
|
||||
/pino/6.14.0:
|
||||
resolution: {integrity: sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==}
|
||||
hasBin: true
|
||||
|
@ -18614,22 +18520,6 @@ packages:
|
|||
sonic-boom: 1.1.0
|
||||
dev: false
|
||||
|
||||
/pino/7.11.0:
|
||||
resolution: {integrity: sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
atomic-sleep: 1.0.0
|
||||
fast-redact: 3.1.1
|
||||
on-exit-leak-free: 0.2.0
|
||||
pino-abstract-transport: 0.5.0
|
||||
pino-std-serializers: 4.0.0
|
||||
process-warning: 1.0.0
|
||||
quick-format-unescaped: 4.0.3
|
||||
real-require: 0.1.0
|
||||
safe-stable-stringify: 2.3.1
|
||||
sonic-boom: 2.2.3
|
||||
thread-stream: 0.15.2
|
||||
|
||||
/pino/8.1.0:
|
||||
resolution: {integrity: sha512-53jlxs+02UNTtF1XwVWfa0dHipBiM5GK73XhkHn8M2hUl9y3L94dNwB8BwQhpd5WdHjBkyJiO7v0LRt4SGgsPg==}
|
||||
hasBin: true
|
||||
|
@ -18646,6 +18536,22 @@ packages:
|
|||
sonic-boom: 3.0.0
|
||||
thread-stream: 1.0.1
|
||||
|
||||
/pino/8.4.1:
|
||||
resolution: {integrity: sha512-rZnbTUNFiYBH1H2OfYYVNBEFRDhN2nRaEmBD2+MDmGXSGyps+YPJ55LzWZP90zg7zyWKy0ZMqGlk47AO6OaBqQ==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
atomic-sleep: 1.0.0
|
||||
fast-redact: 3.1.1
|
||||
on-exit-leak-free: 2.1.0
|
||||
pino-abstract-transport: 1.0.0
|
||||
pino-std-serializers: 6.0.0
|
||||
process-warning: 2.0.0
|
||||
quick-format-unescaped: 4.0.3
|
||||
real-require: 0.2.0
|
||||
safe-stable-stringify: 2.3.1
|
||||
sonic-boom: 3.2.0
|
||||
thread-stream: 2.0.1
|
||||
|
||||
/pirates/4.0.5:
|
||||
resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==}
|
||||
engines: {node: '>= 6'}
|
||||
|
@ -18679,21 +18585,14 @@ packages:
|
|||
semver-compare: 1.0.0
|
||||
dev: true
|
||||
|
||||
/plur/4.0.0:
|
||||
resolution: {integrity: sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
irregular-plurals: 3.3.0
|
||||
dev: true
|
||||
|
||||
/pnpm/6.34.0:
|
||||
resolution: {integrity: sha512-K79DAT5WtGjrUyLtxAyehtN8uy5cXkzT1v+7RIJ3gygCffoLaLlBoG5gcfjfnX7oZH5rxznv/v8tlMIMfZyzTA==}
|
||||
engines: {node: '>=12.17'}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/pnpm/7.9.0:
|
||||
resolution: {integrity: sha512-xkIVw73yJm/h5M4VvFIS5Q+gQCRDrp3r92g58PtcCK86aZCa7EQ6q6ivdfTAz0KsAVgloA6Anub28n6wju5v3w==}
|
||||
/pnpm/7.9.4-0:
|
||||
resolution: {integrity: sha512-qTilkdOOxwKLXcH7eqReARfMetXZqfWoObZkJCYgPsKD+pJQS+IGuYf1S2w+J+/0Y5518icXnc+nZ6c0CX24Ew==}
|
||||
engines: {node: '>=14.6'}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
@ -20383,6 +20282,10 @@ packages:
|
|||
resolution: {integrity: sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==}
|
||||
engines: {node: '>= 12.13.0'}
|
||||
|
||||
/real-require/0.2.0:
|
||||
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
|
||||
engines: {node: '>= 12.13.0'}
|
||||
|
||||
/rechoir/0.6.2:
|
||||
resolution: {integrity: sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=}
|
||||
engines: {node: '>= 0.10'}
|
||||
|
@ -21382,6 +21285,14 @@ packages:
|
|||
interpret: 1.4.0
|
||||
rechoir: 0.6.2
|
||||
|
||||
/shiki/0.10.1:
|
||||
resolution: {integrity: sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==}
|
||||
dependencies:
|
||||
jsonc-parser: 3.1.0
|
||||
vscode-oniguruma: 1.6.2
|
||||
vscode-textmate: 5.2.0
|
||||
dev: true
|
||||
|
||||
/side-channel/1.0.4:
|
||||
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
|
||||
dependencies:
|
||||
|
@ -21555,13 +21466,13 @@ packages:
|
|||
flatstr: 1.0.12
|
||||
dev: false
|
||||
|
||||
/sonic-boom/2.2.3:
|
||||
resolution: {integrity: sha512-dm32bzlBchhXoJZe0yLY/kdYsHtXhZphidIcCzJib1aEjfciZyvHJ3NjA1zh6jJCO/OBLfdjc5iw6jLS/Go2fg==}
|
||||
/sonic-boom/3.0.0:
|
||||
resolution: {integrity: sha512-p5DiZOZHbJ2ZO5MADczp5qrfOd3W5Vr2vHxfCpe7G4AzPwVOweIjbfgku8wSQUuk+Y5Yuo8W7JqRe6XKmKistg==}
|
||||
dependencies:
|
||||
atomic-sleep: 1.0.0
|
||||
|
||||
/sonic-boom/3.0.0:
|
||||
resolution: {integrity: sha512-p5DiZOZHbJ2ZO5MADczp5qrfOd3W5Vr2vHxfCpe7G4AzPwVOweIjbfgku8wSQUuk+Y5Yuo8W7JqRe6XKmKistg==}
|
||||
/sonic-boom/3.2.0:
|
||||
resolution: {integrity: sha512-SbbZ+Kqj/XIunvIAgUZRlqd6CGQYq71tRRbXR92Za8J/R3Yh4Av+TWENiSiEgnlwckYLyP0YZQWVfyNC0dzLaA==}
|
||||
dependencies:
|
||||
atomic-sleep: 1.0.0
|
||||
|
||||
|
@ -21799,9 +21710,6 @@ packages:
|
|||
stubs: 3.0.0
|
||||
dev: true
|
||||
|
||||
/stream-shift/1.0.1:
|
||||
resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==}
|
||||
|
||||
/stream-transform/2.0.4:
|
||||
resolution: {integrity: sha512-LQXH1pUksoef5Ijo6+2ihnjLLZtZuoqu1vhut6a7xZ77nrLA/shbbx2FAzVC/nkb6wwrPzOO98700mv4HDQcWg==}
|
||||
dependencies:
|
||||
|
@ -22461,16 +22369,16 @@ packages:
|
|||
/text-table/0.2.0:
|
||||
resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=}
|
||||
|
||||
/thread-stream/0.15.2:
|
||||
resolution: {integrity: sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==}
|
||||
dependencies:
|
||||
real-require: 0.1.0
|
||||
|
||||
/thread-stream/1.0.1:
|
||||
resolution: {integrity: sha512-JuZyfzx81e5MBk8uIr8ZH76bXyjEQvbRDEkSdlV1JFBdq/rbby2RuvzBYlTBd/xCljxy6lPxrTLXzB9Jl1bNrw==}
|
||||
dependencies:
|
||||
real-require: 0.1.0
|
||||
|
||||
/thread-stream/2.0.1:
|
||||
resolution: {integrity: sha512-X7vWOdsHLkBq0si20ruEE2ttpS7WOVyD52xKu+TOjrRP9Qi9uB9ynHYpzZUbBptArBSuKYUn4mH+jEBnO2CRGg==}
|
||||
dependencies:
|
||||
real-require: 0.2.0
|
||||
|
||||
/throat/6.0.1:
|
||||
resolution: {integrity: sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==}
|
||||
|
||||
|
@ -22682,19 +22590,6 @@ packages:
|
|||
strip-bom: 3.0.0
|
||||
dev: false
|
||||
|
||||
/tsd/0.22.0:
|
||||
resolution: {integrity: sha512-NH+tfEDQ0Ze8gH7TorB6IxYybD+M68EYawe45YNVrbQcydNBfdQHP9IiD0QbnqmwNXrv+l9GAiULT68mo4q/xA==}
|
||||
engines: {node: '>=14.16'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@tsd/typescript': 4.7.4
|
||||
eslint-formatter-pretty: 4.1.0
|
||||
globby: 11.1.0
|
||||
meow: 9.0.0
|
||||
path-exists: 4.0.0
|
||||
read-pkg-up: 7.0.1
|
||||
dev: true
|
||||
|
||||
/tslib/1.14.1:
|
||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||
|
||||
|
@ -22823,6 +22718,28 @@ packages:
|
|||
dependencies:
|
||||
is-typedarray: 1.0.0
|
||||
|
||||
/typedoc-plugin-missing-exports/1.0.0_typedoc@0.23.0-beta.7:
|
||||
resolution: {integrity: sha512-7s6znXnuAj1eD9KYPyzVzR1lBF5nwAY8IKccP5sdoO9crG4lpd16RoFpLsh2PccJM+I2NASpr0+/NMka6ThwVA==}
|
||||
peerDependencies:
|
||||
typedoc: 0.22.x || 0.23.x
|
||||
dependencies:
|
||||
typedoc: 0.23.0-beta.7_typescript@4.7.4
|
||||
dev: true
|
||||
|
||||
/typedoc/0.23.0-beta.7_typescript@4.7.4:
|
||||
resolution: {integrity: sha512-k8GKXXY4z3HIs7HdSu92jcze1nl71cLiHR329ZflhiO4Ta1rJc4F5uEtwUjCSChXFQaVZUI2l3VaF9nWm1/p7A==}
|
||||
engines: {node: '>= 14.14'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
typescript: 4.6.x || 4.7.x
|
||||
dependencies:
|
||||
lunr: 2.3.9
|
||||
marked: 4.0.18
|
||||
minimatch: 5.1.0
|
||||
shiki: 0.10.1
|
||||
typescript: 4.7.4
|
||||
dev: true
|
||||
|
||||
/typescript/4.7.4:
|
||||
resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==}
|
||||
engines: {node: '>=4.2.0'}
|
||||
|
@ -23567,6 +23484,14 @@ packages:
|
|||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/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
|
||||
|
||||
/w3c-hr-time/1.0.2:
|
||||
resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==}
|
||||
dependencies:
|
||||
|
|
Loading…
Reference in a new issue