1
0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-12-24 21:15:51 +01:00

build: format code prettier, enable ci (#2886)

* fix: format code prettier, enable ci

* chore: add trivago import prettier pluggin
This commit is contained in:
Juan Picado 2022-01-09 20:51:50 +01:00 committed by GitHub
parent 23d0bd7056
commit 558fcafc71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
222 changed files with 3858 additions and 4236 deletions

@ -23,6 +23,8 @@ jobs:
run: yarn install --immutable
- name: Build
run: yarn code:build
- name: Format
run: yarn format:check
- name: Lint
run: yarn lint
- name: Test

299
.pnp.js generated

@ -63,6 +63,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@commitlint/cli", "npm:12.1.4"],
["@commitlint/config-conventional", "npm:12.1.4"],
["@octokit/rest", "npm:18.6.0"],
["@trivago/prettier-plugin-sort-imports", "virtual:7f7b3df50ee4b7b1719ad19fad11505dc2788f3227a7e5cc9ca19f71d8cb309c9d33b532ea2b2b60ab65abf6cc12153df4643c5e6e17d01ea0ae0492723bb4b4#npm:3.1.1"],
["@types/async", "npm:3.2.9"],
["@types/express", "npm:4.17.11"],
["@types/express-rate-limit", "npm:5.1.3"],
@ -233,6 +234,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/highlight", "npm:7.16.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-code-frame-npm-7.16.7-093eb9e124-79eb7c3207.zip/node_modules/@babel/code-frame/",
"packageDependencies": [
["@babel/code-frame", "npm:7.16.7"],
["@babel/highlight", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/compat-data", [
@ -256,6 +265,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/compat-data", "npm:7.16.0"]
],
"linkType": "HARD",
}],
["npm:7.16.4", {
"packageLocation": "./.yarn/cache/@babel-compat-data-npm-7.16.4-9128f11195-5735fb9156.zip/node_modules/@babel/compat-data/",
"packageDependencies": [
["@babel/compat-data", "npm:7.16.4"]
],
"linkType": "HARD",
}]
]],
["@babel/core", [
@ -282,6 +298,29 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],
"linkType": "HARD",
}],
["npm:7.13.10", {
"packageLocation": "./.yarn/cache/@babel-core-npm-7.13.10-57ebf35dd5-728249a0ba.zip/node_modules/@babel/core/",
"packageDependencies": [
["@babel/core", "npm:7.13.10"],
["@babel/code-frame", "npm:7.12.13"],
["@babel/generator", "npm:7.16.7"],
["@babel/helper-compilation-targets", "virtual:57ebf35dd5ea0b818591de63843e65e1ae44db4213e6c4a68ffa85ff9440503ed9f92d3f78b88fde641ad2fdb170f9a17c16f3d13d73ccaa697ab86ec9e7aa1c#npm:7.16.7"],
["@babel/helper-module-transforms", "npm:7.16.7"],
["@babel/helpers", "npm:7.16.7"],
["@babel/parser", "npm:7.16.7"],
["@babel/template", "npm:7.12.13"],
["@babel/traverse", "npm:7.13.0"],
["@babel/types", "npm:7.13.0"],
["convert-source-map", "npm:1.7.0"],
["debug", "virtual:24c0670a0dd5336de8e9d36ce94c8b696cc66bf2f157358e53a1649e6047bfc20104ef799a035ae68ee7761447ecfa64a6d54a5971d436f7ea6ab984abfab5de#npm:4.1.1"],
["gensync", "npm:1.0.0-beta.2"],
["json5", "npm:2.1.3"],
["lodash", "npm:4.17.20"],
["semver", "npm:6.3.0"],
["source-map", "npm:0.5.7"]
],
"linkType": "HARD",
}],
["npm:7.16.0", {
"packageLocation": "./.yarn/cache/@babel-core-npm-7.16.0-5612f0ce31-ee30612e54.zip/node_modules/@babel/core/",
"packageDependencies": [
@ -357,6 +396,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["source-map", "npm:0.5.7"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-generator-npm-7.16.7-3cf12729b6-1df435d689.zip/node_modules/@babel/generator/",
"packageDependencies": [
["@babel/generator", "npm:7.16.7"],
["@babel/types", "npm:7.16.7"],
["jsesc", "npm:2.5.2"],
["source-map", "npm:0.5.7"]
],
"linkType": "HARD",
}]
]],
["@babel/helper-annotate-as-pure", [
@ -403,6 +452,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],
"linkType": "SOFT",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-helper-compilation-targets-npm-7.16.7-8031641957-f7da620a08.zip/node_modules/@babel/helper-compilation-targets/",
"packageDependencies": [
["@babel/helper-compilation-targets", "npm:7.16.7"]
],
"linkType": "SOFT",
}],
["virtual:5612f0ce311a7844500ba5948d5d47b8376a902bfa55b1e3797dd916bf18f7512ba75518521ba3bc2f39f6565fb127bcb8fee5b440624dbebaf9ac5f3566ebd0#npm:7.16.0", {
"packageLocation": "./.yarn/$$virtual/@babel-helper-compilation-targets-virtual-64c9734913/0/cache/@babel-helper-compilation-targets-npm-7.16.0-153c8450fa-5e1396ab10.zip/node_modules/@babel/helper-compilation-targets/",
"packageDependencies": [
@ -420,6 +476,23 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],
"linkType": "HARD",
}],
["virtual:57ebf35dd5ea0b818591de63843e65e1ae44db4213e6c4a68ffa85ff9440503ed9f92d3f78b88fde641ad2fdb170f9a17c16f3d13d73ccaa697ab86ec9e7aa1c#npm:7.16.7", {
"packageLocation": "./.yarn/$$virtual/@babel-helper-compilation-targets-virtual-6847cc1e9a/0/cache/@babel-helper-compilation-targets-npm-7.16.7-8031641957-f7da620a08.zip/node_modules/@babel/helper-compilation-targets/",
"packageDependencies": [
["@babel/helper-compilation-targets", "virtual:57ebf35dd5ea0b818591de63843e65e1ae44db4213e6c4a68ffa85ff9440503ed9f92d3f78b88fde641ad2fdb170f9a17c16f3d13d73ccaa697ab86ec9e7aa1c#npm:7.16.7"],
["@babel/compat-data", "npm:7.16.4"],
["@babel/core", "npm:7.13.10"],
["@babel/helper-validator-option", "npm:7.16.7"],
["@types/babel__core", null],
["browserslist", "npm:4.19.1"],
["semver", "npm:6.3.0"]
],
"packagePeers": [
"@babel/core",
"@types/babel__core"
],
"linkType": "HARD",
}],
["virtual:b5039fc7c576fde82936c64bf3dfa10686342566681ea55522ff1adc0b716868cb771419d9bca4bcac8159bc70c523e3655f9f11e07d832f65be49230a8c85f3#npm:7.13.8", {
"packageLocation": "./.yarn/$$virtual/@babel-helper-compilation-targets-virtual-0890edc99d/0/cache/@babel-helper-compilation-targets-npm-7.13.8-bd6cee5343-dbee371e5f.zip/node_modules/@babel/helper-compilation-targets/",
"packageDependencies": [
@ -543,6 +616,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"linkType": "HARD",
}]
]],
["@babel/helper-environment-visitor", [
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-helper-environment-visitor-npm-7.16.7-3ee2ba2019-da3195cad9.zip/node_modules/@babel/helper-environment-visitor/",
"packageDependencies": [
["@babel/helper-environment-visitor", "npm:7.16.7"],
["@babel/types", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/helper-explode-assignable-expression", [
["npm:7.16.0", {
"packageLocation": "./.yarn/cache/@babel-helper-explode-assignable-expression-npm-7.16.0-c7497452bc-97e5391bc8.zip/node_modules/@babel/helper-explode-assignable-expression/",
@ -593,6 +676,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/types", "npm:7.16.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-helper-function-name-npm-7.16.7-aa24c7b296-919e9f34f4.zip/node_modules/@babel/helper-function-name/",
"packageDependencies": [
["@babel/helper-function-name", "npm:7.16.7"],
["@babel/helper-get-function-arity", "npm:7.16.7"],
["@babel/template", "npm:7.16.7"],
["@babel/types", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/helper-get-function-arity", [
@ -627,6 +720,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/types", "npm:7.16.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-helper-get-function-arity-npm-7.16.7-987b1b1bed-1dfbdb56ef.zip/node_modules/@babel/helper-get-function-arity/",
"packageDependencies": [
["@babel/helper-get-function-arity", "npm:7.16.7"],
["@babel/types", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/helper-hoist-variables", [
@ -637,6 +738,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/types", "npm:7.16.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-helper-hoist-variables-npm-7.16.7-25cc3abba4-d9f544a8b9.zip/node_modules/@babel/helper-hoist-variables/",
"packageDependencies": [
["@babel/helper-hoist-variables", "npm:7.16.7"],
["@babel/types", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/helper-member-expression-to-functions", [
@ -681,6 +790,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/types", "npm:7.16.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-helper-module-imports-npm-7.16.7-19c74fd92b-5248e9ccce.zip/node_modules/@babel/helper-module-imports/",
"packageDependencies": [
["@babel/helper-module-imports", "npm:7.16.7"],
["@babel/types", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/helper-module-transforms", [
@ -712,6 +829,21 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/types", "npm:7.16.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-helper-module-transforms-npm-7.16.7-4b3d4b8254-79e70c79e6.zip/node_modules/@babel/helper-module-transforms/",
"packageDependencies": [
["@babel/helper-module-transforms", "npm:7.16.7"],
["@babel/helper-environment-visitor", "npm:7.16.7"],
["@babel/helper-module-imports", "npm:7.16.7"],
["@babel/helper-simple-access", "npm:7.16.7"],
["@babel/helper-split-export-declaration", "npm:7.16.7"],
["@babel/helper-validator-identifier", "npm:7.16.7"],
["@babel/template", "npm:7.16.7"],
["@babel/traverse", "npm:7.16.7"],
["@babel/types", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/helper-optimise-call-expression", [
@ -825,6 +957,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/types", "npm:7.16.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-helper-simple-access-npm-7.16.7-c4dfb1f5e7-f7c7e1fa77.zip/node_modules/@babel/helper-simple-access/",
"packageDependencies": [
["@babel/helper-simple-access", "npm:7.16.7"],
["@babel/types", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/helper-skip-transparent-expression-wrappers", [
@ -877,6 +1017,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/types", "npm:7.16.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-helper-split-export-declaration-npm-7.16.7-5b9ae90171-a259453a63.zip/node_modules/@babel/helper-split-export-declaration/",
"packageDependencies": [
["@babel/helper-split-export-declaration", "npm:7.16.7"],
["@babel/types", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/helper-validator-identifier", [
@ -907,6 +1055,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/helper-validator-identifier", "npm:7.15.7"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-helper-validator-identifier-npm-7.16.7-8599fb00fc-43b4b4b721.zip/node_modules/@babel/helper-validator-identifier/",
"packageDependencies": [
["@babel/helper-validator-identifier", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/helper-validator-option", [
@ -923,6 +1078,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/helper-validator-option", "npm:7.14.5"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-helper-validator-option-npm-7.16.7-d13e9c1d9e-e446b2cab7.zip/node_modules/@babel/helper-validator-option/",
"packageDependencies": [
["@babel/helper-validator-option", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/helper-wrap-function", [
@ -958,6 +1120,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/types", "npm:7.16.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-helpers-npm-7.16.7-69d23ddac5-02775b84dd.zip/node_modules/@babel/helpers/",
"packageDependencies": [
["@babel/helpers", "npm:7.16.7"],
["@babel/template", "npm:7.16.7"],
["@babel/traverse", "npm:7.16.7"],
["@babel/types", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/highlight", [
@ -1000,6 +1172,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["js-tokens", "npm:4.0.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-highlight-npm-7.16.7-c36734cd1b-fa1ee4f97f.zip/node_modules/@babel/highlight/",
"packageDependencies": [
["@babel/highlight", "npm:7.16.7"],
["@babel/helper-validator-identifier", "npm:7.16.7"],
["chalk", "npm:2.4.2"],
["js-tokens", "npm:4.0.0"]
],
"linkType": "HARD",
}]
]],
["@babel/node", [
@ -1063,6 +1245,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],
"linkType": "HARD",
}],
["npm:7.14.6", {
"packageLocation": "./.yarn/cache/@babel-parser-npm-7.14.6-c6c1f6245c-447ca2627e.zip/node_modules/@babel/parser/",
"packageDependencies": [
["@babel/parser", "npm:7.14.6"],
["@babel/types", "npm:7.11.5"]
],
"linkType": "HARD",
}],
["npm:7.16.2", {
"packageLocation": "./.yarn/cache/@babel-parser-npm-7.16.2-2df15780e2-06a8f0d812.zip/node_modules/@babel/parser/",
"packageDependencies": [
@ -1070,6 +1260,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/types", "npm:7.11.5"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-parser-npm-7.16.7-276b590a17-30649fa885.zip/node_modules/@babel/parser/",
"packageDependencies": [
["@babel/parser", "npm:7.16.7"],
["@babel/types", "npm:7.11.5"]
],
"linkType": "HARD",
}]
]],
["@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression", [
@ -3467,6 +3665,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@babel/types", "npm:7.16.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-template-npm-7.16.7-a18e444be8-bfc9a53563.zip/node_modules/@babel/template/",
"packageDependencies": [
["@babel/template", "npm:7.16.7"],
["@babel/code-frame", "npm:7.16.7"],
["@babel/parser", "npm:7.16.7"],
["@babel/types", "npm:7.16.7"]
],
"linkType": "HARD",
}]
]],
["@babel/traverse", [
@ -3549,6 +3757,23 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["globals", "npm:11.12.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-traverse-npm-7.16.7-65523936f6-f76ac30150.zip/node_modules/@babel/traverse/",
"packageDependencies": [
["@babel/traverse", "npm:7.16.7"],
["@babel/code-frame", "npm:7.16.7"],
["@babel/generator", "npm:7.16.7"],
["@babel/helper-environment-visitor", "npm:7.16.7"],
["@babel/helper-function-name", "npm:7.16.7"],
["@babel/helper-hoist-variables", "npm:7.16.7"],
["@babel/helper-split-export-declaration", "npm:7.16.7"],
["@babel/parser", "npm:7.16.7"],
["@babel/types", "npm:7.16.7"],
["debug", "virtual:24c0670a0dd5336de8e9d36ce94c8b696cc66bf2f157358e53a1649e6047bfc20104ef799a035ae68ee7761447ecfa64a6d54a5971d436f7ea6ab984abfab5de#npm:4.1.1"],
["globals", "npm:11.12.0"]
],
"linkType": "HARD",
}]
]],
["@babel/types", [
@ -3600,6 +3825,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["to-fast-properties", "npm:2.0.0"]
],
"linkType": "HARD",
}],
["npm:7.16.7", {
"packageLocation": "./.yarn/cache/@babel-types-npm-7.16.7-fa27eee382-72a6093b0a.zip/node_modules/@babel/types/",
"packageDependencies": [
["@babel/types", "npm:7.16.7"],
["@babel/helper-validator-identifier", "npm:7.16.7"],
["to-fast-properties", "npm:2.0.0"]
],
"linkType": "HARD",
}]
]],
["@bcoe/v8-coverage", [
@ -4360,6 +4594,35 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"linkType": "HARD",
}]
]],
["@trivago/prettier-plugin-sort-imports", [
["npm:3.1.1", {
"packageLocation": "./.yarn/cache/@trivago-prettier-plugin-sort-imports-npm-3.1.1-3d238d3b28-291139fead.zip/node_modules/@trivago/prettier-plugin-sort-imports/",
"packageDependencies": [
["@trivago/prettier-plugin-sort-imports", "npm:3.1.1"]
],
"linkType": "SOFT",
}],
["virtual:7f7b3df50ee4b7b1719ad19fad11505dc2788f3227a7e5cc9ca19f71d8cb309c9d33b532ea2b2b60ab65abf6cc12153df4643c5e6e17d01ea0ae0492723bb4b4#npm:3.1.1", {
"packageLocation": "./.yarn/$$virtual/@trivago-prettier-plugin-sort-imports-virtual-da3d3a0781/0/cache/@trivago-prettier-plugin-sort-imports-npm-3.1.1-3d238d3b28-291139fead.zip/node_modules/@trivago/prettier-plugin-sort-imports/",
"packageDependencies": [
["@trivago/prettier-plugin-sort-imports", "virtual:7f7b3df50ee4b7b1719ad19fad11505dc2788f3227a7e5cc9ca19f71d8cb309c9d33b532ea2b2b60ab65abf6cc12153df4643c5e6e17d01ea0ae0492723bb4b4#npm:3.1.1"],
["@babel/core", "npm:7.13.10"],
["@babel/generator", "npm:7.13.9"],
["@babel/parser", "npm:7.14.6"],
["@babel/traverse", "npm:7.13.0"],
["@babel/types", "npm:7.13.0"],
["@types/prettier", null],
["javascript-natural-sort", "npm:0.7.1"],
["lodash", "npm:4.17.21"],
["prettier", "npm:2.5.1"]
],
"packagePeers": [
"@types/prettier",
"prettier"
],
"linkType": "HARD",
}]
]],
["@tsconfig/node10", [
["npm:1.0.8", {
"packageLocation": "./.yarn/cache/@tsconfig-node10-npm-1.0.8-90a8cce25d-0336493b89.zip/node_modules/@tsconfig/node10/",
@ -6668,6 +6931,18 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["picocolors", "npm:1.0.0"]
],
"linkType": "HARD",
}],
["npm:4.19.1", {
"packageLocation": "./.yarn/cache/browserslist-npm-4.19.1-e9de2a4009-340af7f052.zip/node_modules/browserslist/",
"packageDependencies": [
["browserslist", "npm:4.19.1"],
["caniuse-lite", "npm:1.0.30001298"],
["electron-to-chromium", "npm:1.4.38"],
["escalade", "npm:3.1.1"],
["node-releases", "npm:2.0.1"],
["picocolors", "npm:1.0.0"]
],
"linkType": "HARD",
}]
]],
["bser", [
@ -6861,6 +7136,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["caniuse-lite", "npm:1.0.30001277"]
],
"linkType": "HARD",
}],
["npm:1.0.30001298", {
"packageLocation": "./.yarn/cache/caniuse-lite-npm-1.0.30001298-f7f894bcff-3f99e795cc.zip/node_modules/caniuse-lite/",
"packageDependencies": [
["caniuse-lite", "npm:1.0.30001298"]
],
"linkType": "HARD",
}]
]],
["capture-exit", [
@ -8362,6 +8644,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["electron-to-chromium", "npm:1.3.888"]
],
"linkType": "HARD",
}],
["npm:1.4.38", {
"packageLocation": "./.yarn/cache/electron-to-chromium-npm-1.4.38-fccaeb9031-a37105253a.zip/node_modules/electron-to-chromium/",
"packageDependencies": [
["electron-to-chromium", "npm:1.4.38"]
],
"linkType": "HARD",
}]
]],
["emittery", [
@ -11540,6 +11829,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"linkType": "HARD",
}]
]],
["javascript-natural-sort", [
["npm:0.7.1", {
"packageLocation": "./.yarn/cache/javascript-natural-sort-npm-0.7.1-9018625996-f097317419.zip/node_modules/javascript-natural-sort/",
"packageDependencies": [
["javascript-natural-sort", "npm:0.7.1"]
],
"linkType": "HARD",
}]
]],
["jest", [
["npm:26.6.3", {
"packageLocation": "./.yarn/cache/jest-npm-26.6.3-dafe93d52f-4ffcfefa2b.zip/node_modules/jest/",
@ -17540,6 +17838,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@commitlint/cli", "npm:12.1.4"],
["@commitlint/config-conventional", "npm:12.1.4"],
["@octokit/rest", "npm:18.6.0"],
["@trivago/prettier-plugin-sort-imports", "virtual:7f7b3df50ee4b7b1719ad19fad11505dc2788f3227a7e5cc9ca19f71d8cb309c9d33b532ea2b2b60ab65abf6cc12153df4643c5e6e17d01ea0ae0492723bb4b4#npm:3.1.1"],
["@types/async", "npm:3.2.9"],
["@types/express", "npm:4.17.11"],
["@types/express-rate-limit", "npm:5.1.3"],

@ -1,11 +0,0 @@
{
"endOfLine": "lf",
"useTabs": false,
"printWidth": 180,
"tabWidth": 2,
"singleQuote": true,
"bracketSpacing": true,
"jsxBracketSameLine": true,
"trailingComma": "es5",
"semi": true
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -8,19 +8,19 @@ In the interest of fostering an open and welcoming environment, we as contributo
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities

@ -14,13 +14,13 @@ Additional information is available on the
- [How Do I Contribute?](#how-do-i-contribute)
- [Development](#development)
- [Reporting Bugs](#reporting-bugs)
- [Issue Search](#issue-search)
- [Check Website For Solution](#check-website-for-solution)
- [Chat](#chat)
- [Check If It's Been Fixed](#check-if-its-been-fixed)
- [Issue Search](#issue-search)
- [Check Website For Solution](#check-website-for-solution)
- [Chat](#chat)
- [Check If It's Been Fixed](#check-if-its-been-fixed)
- [Request Features](#request-features)
- [Submitting a Pull Request](#submitting-a-pull-request)
- [Make Changes and Commit](#make-changes-and-commit)
- [Submitting a Pull Request](#submitting-a-pull-request)
- [Make Changes and Commit](#make-changes-and-commit)
- [Update Tests](#update-tests)
- [Develop Plugins](#develop-plugins)
@ -29,10 +29,10 @@ Additional information is available on the
There are different ways to contribute, each with a different level
of involvement and technical knowledge required, such as:
* [Reporting Bugs](#reporting-bugs)
* [Request Features](#request-features)
* [Develop Plugins](#develop-plugins)
* [Improve Documentation](http://www.verdaccio.org/docs/en/installation.html)
- [Reporting Bugs](#reporting-bugs)
- [Request Features](#request-features)
- [Develop Plugins](#develop-plugins)
- [Improve Documentation](http://www.verdaccio.org/docs/en/installation.html)
**Please read this document carefully. It will help maintainers and readers
in solving your issue(s), evaluating your feature request, etc.**
@ -41,8 +41,8 @@ in solving your issue(s), evaluating your feature request, etc.**
Development guides can be found on the [wiki](https://github.com/verdaccio/verdaccio/wiki):
* [Building the project](https://github.com/verdaccio/verdaccio/wiki/Build-Source-Code)
* [Running, debugging, and testing](https://github.com/verdaccio/verdaccio/wiki/Running-and-Debugging-tests)
- [Building the project](https://github.com/verdaccio/verdaccio/wiki/Build-Source-Code)
- [Running, debugging, and testing](https://github.com/verdaccio/verdaccio/wiki/Running-and-Debugging-tests)
## Reporting Bugs
@ -51,7 +51,7 @@ We welcome clear, detailed bug reports.
**Bugs are considered features that are not working as described in
documentation.**
If you've found a bug in Verdaccio **that isn't a security risk**, please file
If you've found a bug in Verdaccio **that isn't a security risk**, please file
a report in our [issue tracker](https://github.com/verdaccio/verdaccio/issues).
**NOTE: Verdaccio still does not support all npm commands. Some were not
@ -66,7 +66,7 @@ Additionally, we have labelled questions for easy follow-up as [questions](https
If so, up-vote it (using GitHub reactions) or add additional helpful details to
the existing issue to show that it's affecting multiple people.
### Check Website For Solution
Some of the most popular topics can be found in our website(http://www.verdaccio.org/docs/en/installation.html)
@ -89,10 +89,10 @@ the project. Then, detail your request, ensuring context and use case is provide
**Please provide:**
* A detailed description the advantages of your request
* Whether or not it's compatible with `npm` and `yarn`
* A potential implementation or design
* Whatever else you have in your mind 🤓
- A detailed description the advantages of your request
- Whether or not it's compatible with `npm` and `yarn`
- A potential implementation or design
- Whatever else you have in your mind 🤓
### Submitting a Pull Request
@ -137,8 +137,8 @@ semantic versioning.
For example:
* `feat: A new feature`
* `fix: A bug fix`
- `feat: A new feature`
- `fix: A bug fix`
A commit of the type feat introduces a new feature to the codebase
(this correlates with MINOR in semantic versioning).
@ -174,12 +174,13 @@ If you need help with how testing works, please [refer to the following guide](h
features without tests will not be merged.**
Things excluded from tests:
* Documentation
* Website
* Build
* Deployment
* Assets
* Flow types
- Documentation
- Website
- Build
- Deployment
- Assets
- Flow types
## Develop Plugins
@ -188,7 +189,7 @@ Plugins are add-ons that extend the functionality of the application.
If you want to develop your own plugin:
1. Check whether there is a legacy Sinopia plugin for the feature that you need
via [npmjs](https://www.npmjs.com/search?q=sinopia)
via [npmjs](https://www.npmjs.com/search?q=sinopia)
2. Keep in mind the [life-cycle to load a plugin](https://verdaccio.org/docs/en/dev-plugins)
3. You are free to host your plugin in your repository or ours (just ask)
4. Provide a detailed description of your plugin to help users understand it

@ -4,13 +4,12 @@
The following table describes the versions of this project that are currently supported with security updates:
| Version | Supported |
| ------- | ------------------ |
| 2.x | :x: |
| 3.x | :x: |
| 4.x | :white_check_mark: (until 1st July 2021) |
| 5.x | :white_check_mark: |
| Version | Supported |
| ------- | ---------------------------------------- |
| 2.x | :x: |
| 3.x | :x: |
| 4.x | :white_check_mark: (until 1st July 2021) |
| 5.x | :white_check_mark: |
## Responsible disclosure security policy
@ -28,11 +27,11 @@ At Verdaccio, we consider the security of our systems a top priority. But no mat
If you discover a security vulnerability, please use one of the following means of communications to report it to us:
* Report the security issue to the Node.js Security WG through the [HackerOne program](https://hackerone.com/nodejs-ecosystem) for ecosystem modules on npm, or to [Snyk Security Team](https://snyk.io/vulnerability-disclosure). They will help triage the security issue and work with all involved parties to remediate and release a fix.
- Report the security issue to the Node.js Security WG through the [HackerOne program](https://hackerone.com/nodejs-ecosystem) for ecosystem modules on npm, or to [Snyk Security Team](https://snyk.io/vulnerability-disclosure). They will help triage the security issue and work with all involved parties to remediate and release a fix.
Note that time-frame and processes are subject to each programs own policy.
* Report the security issue to the project maintainers directly at verdaccio@pm.me. If the report contains highly sensitive information, please be advised to encrypt your findings using our [PGP key](https://verdaccio.nyc3.digitaloceanspaces.com/gpg/publickey.verdaccio@pm.me.asc) which is also available in this document.
- Report the security issue to the project maintainers directly at verdaccio@pm.me. If the report contains highly sensitive information, please be advised to encrypt your findings using our [PGP key](https://verdaccio.nyc3.digitaloceanspaces.com/gpg/publickey.verdaccio@pm.me.asc) which is also available in this document.
Your efforts to responsibly disclose your findings are sincerely appreciated and will be taken into account to acknowledge your contributions.

@ -2,8 +2,8 @@
This directory host the default configuration file, but you can find more here:
* [https://verdaccio.org/docs/en/installation](https://verdaccio.org/docs/en/installation)
* [Chat with us](http://chat.verdaccio.org) <- You need a Discord account
* [Follow us on Twitter](https://twitter.com/verdaccio_npm)
- [https://verdaccio.org/docs/en/installation](https://verdaccio.org/docs/en/installation)
- [Chat with us](http://chat.verdaccio.org) <- You need a Discord account
- [Follow us on Twitter](https://twitter.com/verdaccio_npm)
Enjoy Verdaccio !

2
debug/bootstrap.js vendored

@ -1,6 +1,6 @@
// this file aims to help local debugging with hot transpilation
// it requires BABEL_ENV=registry set as env variable
require('@babel/register')({
extensions: [".ts", ".js"]
extensions: ['.ts', '.js'],
});
require('../src/lib/cli');

@ -1,100 +1,100 @@
module.exports = {
"extends": [
"eslint:recommended",
"google",
"plugin:jest/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:import/typescript",
"prettier"
extends: [
'eslint:recommended',
'google',
'plugin:jest/recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:import/typescript',
'prettier',
],
"plugins": ["import", "jest"],
"env": {
"es6": true,
"node": true,
"jest": true
plugins: ['import', 'jest'],
env: {
es6: true,
node: true,
jest: true,
},
"globals": {
"__APP_VERSION__": true
globals: {
__APP_VERSION__: true,
},
"parserOptions": {
"allowImportExportEverywhere": true,
"sourceType": "module",
"ecmaVersion": 11,
"ecmaFeatures": {
"impliedStrict": true,
"jsx": true
}
parserOptions: {
allowImportExportEverywhere: true,
sourceType: 'module',
ecmaVersion: 11,
ecmaFeatures: {
impliedStrict: true,
jsx: true,
},
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".ts", ".tsx"]
}
}
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.ts', '.tsx'],
},
},
},
"parser": "@typescript-eslint/parser",
"rules": {
"curly": ["error", "all"],
"react/prop-types": 0,
"jest/no-export": 0,
"jest/no-test-callback": 0,
"jest/expect-expect": 0,
"jest/no-try-expect": 0,
"jest/no-done-callback": "off",
"jest/no-conditional-expect": "off",
"keyword-spacing": "off",
"no-tabs": "off",
"no-useless-escape": "off",
"padded-blocks": "off",
"require-jsdoc": "off",
"valid-jsdoc": "off",
"import/order": ["warn"],
"eol-last": "error",
"no-irregular-whitespace": "error",
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
"no-trailing-spaces": "error",
"camelcase": "off",
"guard-for-in": "error",
"new-cap": "error",
"max-len": ["error", 180],
"no-console": ["error", { "allow": ["warn"] }],
"no-constant-condition": "error",
"no-debugger": "error",
"no-empty": "error",
"no-fallthrough": "error",
"no-invalid-this": "error",
"no-new-require": "error",
"no-undef": "error",
"no-unreachable": "error",
"no-var": "error",
"one-var": "error",
"prefer-rest-params": "error",
"prefer-spread": "error",
"handle-callback-err": 0,
"prefer-const": 0,
"@typescript-eslint/camelcase": 0,
"@typescript-eslint/ban-ts-ignore": 0,
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/no-inferrable-types": 0,
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-this-alias": 0,
"@typescript-eslint/no-use-before-define": 0,
"@typescript-eslint/array-type": ["error"],
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/indent": 0,
"@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/ban-types": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
parser: '@typescript-eslint/parser',
rules: {
curly: ['error', 'all'],
'react/prop-types': 0,
'jest/no-export': 0,
'jest/no-test-callback': 0,
'jest/expect-expect': 0,
'jest/no-try-expect': 0,
'jest/no-done-callback': 'off',
'jest/no-conditional-expect': 'off',
'keyword-spacing': 'off',
'no-tabs': 'off',
'no-useless-escape': 'off',
'padded-blocks': 'off',
'require-jsdoc': 'off',
'valid-jsdoc': 'off',
'import/order': ['warn'],
'eol-last': 'error',
'no-irregular-whitespace': 'error',
'no-mixed-spaces-and-tabs': ['error', 'smart-tabs'],
'no-trailing-spaces': 'error',
camelcase: 'off',
'guard-for-in': 'error',
'new-cap': 'error',
'max-len': ['error', 180],
'no-console': ['error', { allow: ['warn'] }],
'no-constant-condition': 'error',
'no-debugger': 'error',
'no-empty': 'error',
'no-fallthrough': 'error',
'no-invalid-this': 'error',
'no-new-require': 'error',
'no-undef': 'error',
'no-unreachable': 'error',
'no-var': 'error',
'one-var': 'error',
'prefer-rest-params': 'error',
'prefer-spread': 'error',
'handle-callback-err': 0,
'prefer-const': 0,
'@typescript-eslint/camelcase': 0,
'@typescript-eslint/ban-ts-ignore': 0,
'@typescript-eslint/no-var-requires': 0,
'@typescript-eslint/no-inferrable-types': 0,
'@typescript-eslint/no-empty-function': 0,
'@typescript-eslint/no-this-alias': 0,
'@typescript-eslint/no-use-before-define': 0,
'@typescript-eslint/array-type': ['error'],
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/indent': 0,
'@typescript-eslint/ban-ts-comment': 0,
'@typescript-eslint/ban-types': 0,
'@typescript-eslint/explicit-module-boundary-types': 0,
// rules to fix
"no-unused-vars": ["warn", { "vars": "all", "args": "none" }],
"jest/no-identical-title": ["warn"],
"prefer-promise-reject-errors": ["warn"],
"jest/no-disabled-tests": ["warn"],
"jest/no-commented-out-tests": ["warn"],
"@typescript-eslint/prefer-optional-chain": ["warn"],
"@typescript-eslint/explicit-member-accessibility": ["warn"],
"@typescript-eslint/no-unused-vars": ["warn"]
}
}
'no-unused-vars': ['warn', { vars: 'all', args: 'none' }],
'jest/no-identical-title': ['warn'],
'prefer-promise-reject-errors': ['warn'],
'jest/no-disabled-tests': ['warn'],
'jest/no-commented-out-tests': ['warn'],
'@typescript-eslint/prefer-optional-chain': ['warn'],
'@typescript-eslint/explicit-member-accessibility': ['warn'],
'@typescript-eslint/no-unused-vars': ['warn'],
},
};

@ -1 +1 @@
export {default as startVerdaccio} from './build/index';
export { default as startVerdaccio } from './build/index';

@ -4,14 +4,14 @@ module.exports = {
name: 'verdaccio-unit-jest',
verbose: true,
collectCoverage: true,
reporters: ["default", ["jest-junit", { outputDirectory: 'reports' }]],
reporters: ['default', ['jest-junit', { outputDirectory: 'reports' }]],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
testURL: 'http://localhost',
testRegex: '(test/unit.*\\.spec)\\.ts',
// Some unit tests rely on data folders that look like packages. This confuses jest-hast-map
// when it tries to scan for package.json files.
transform: {
'^.+\\.(js|jsx|ts|tsx)$': 'babel-jest'
'^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
},
modulePathIgnorePatterns: [
'<rootDir>/test/unit/partials/mock-store/.*/package.json',
@ -31,14 +31,6 @@ module.exports = {
'<rootDir>/build',
'<rootDir>/.vscode/',
],
testPathIgnorePatterns: [
'__snapshots__',
'<rootDir>/build',
],
coveragePathIgnorePatterns: [
'node_modules',
'fixtures',
'<rootDir>/src/api/debug',
'<rootDir>/test',
]
testPathIgnorePatterns: ['__snapshots__', '<rootDir>/build'],
coveragePathIgnorePatterns: ['node_modules', 'fixtures', '<rootDir>/src/api/debug', '<rootDir>/test'],
};

@ -88,6 +88,7 @@
"@commitlint/cli": "12.1.4",
"@commitlint/config-conventional": "12.1.4",
"@octokit/rest": "18.6.0",
"@trivago/prettier-plugin-sort-imports": "3.1.1",
"@types/async": "3.2.9",
"@types/express": "4.17.11",
"@types/express-rate-limit": "5.1.3",
@ -157,8 +158,8 @@
"release": "standard-version -a -s",
"type-check": "tsc --noEmit",
"type-check:watch": "yarn run type-check -- --watch",
"format": "prettier --single-quote --trailing-comma none --write \"{src,test}/**/*.ts\"",
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md}\" --debug-check",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md}\"",
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md}\"",
"test": "yarn run test:unit",
"test:clean": "npx jest --clearCache",
"test:unit": "cross-env NODE_ENV=test TZ=UTC FORCE_COLOR=1 jest --config ./jest.config.js --maxWorkers 2 --passWithNoTests",

15
prettier.config.js Normal file

@ -0,0 +1,15 @@
module.exports = {
endOfLine: 'lf',
useTabs: false,
printWidth: 180,
tabWidth: 2,
singleQuote: true,
bracketSpacing: true,
trailingComma: 'es5',
semi: true,
plugins: [require('@trivago/prettier-plugin-sort-imports')],
importOrder: ['^@verdaccio/(.*)$', '^[./]'],
importOrderSeparation: true,
importOrderParserPlugins: ['typescript', 'classProperties', 'jsx'],
importOrderSortSpecifiers: true,
};

@ -3,6 +3,6 @@
// this file aims to help local debugging with hot transpilation
// it requires BABEL_ENV=registry set as env variable
require('@babel/register')({
extensions: [".ts", ".js"]
extensions: ['.ts', '.js'],
});
require('../src/lib/cli');

@ -1,7 +1,6 @@
/* eslint-disable no-console */
import { execSync } from 'child_process';
import { Octokit } from '@octokit/rest';
import { execSync } from 'child_process';
const [, , /* node */ /* file */ tag] = process.argv;

@ -1,26 +1,24 @@
import { $ResponseExtend, $RequestExtend, $NextFunctionVer } from '../../../types';
import _ from 'lodash';
import { Application } from 'express';
import _ from 'lodash';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../../../types';
export default (app: Application, selfPath: string): void => {
// Hook for tests only
app.get(
'/-/_debug',
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const doGarbabeCollector = _.isNil(global.gc) === false;
app.get('/-/_debug', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const doGarbabeCollector = _.isNil(global.gc) === false;
if (doGarbabeCollector) {
global.gc();
}
next({
pid: process.pid,
// @ts-ignore
main: process.mainModule.filename,
conf: selfPath,
mem: process.memoryUsage(),
gc: doGarbabeCollector
});
if (doGarbabeCollector) {
global.gc();
}
);
next({
pid: process.pid,
// @ts-ignore
main: process.mainModule.filename,
conf: selfPath,
mem: process.memoryUsage(),
gc: doGarbabeCollector,
});
});
};

@ -1,25 +1,17 @@
import { media, allow } from '../../middleware';
import {
IAuth,
$ResponseExtend,
$RequestExtend,
$NextFunctionVer,
IStorageHandler
} from '../../../../types';
import { API_MESSAGE, HTTP_STATUS, DIST_TAGS } from '../../../lib/constants';
import mime from 'mime';
import _ from 'lodash';
import { Router } from 'express';
import _ from 'lodash';
import mime from 'mime';
import { VerdaccioError } from '@verdaccio/commons-api';
import { Package } from '@verdaccio/types';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend, IAuth, IStorageHandler } from '../../../../types';
import { API_MESSAGE, DIST_TAGS, HTTP_STATUS } from '../../../lib/constants';
import { allow, media } from '../../middleware';
export default function (route: Router, auth: IAuth, storage: IStorageHandler): void {
const can = allow(auth);
const tag_package_version = function (
req: $RequestExtend,
res: $ResponseExtend,
next: $NextFunctionVer
): $NextFunctionVer {
const tag_package_version = function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): $NextFunctionVer {
if (_.isString(req.body) === false) {
return next('route');
}
@ -38,74 +30,48 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler):
// tagging a package
route.put('/:package/:tag', can('publish'), media(mime.getType('json')), tag_package_version);
route.post(
'/-/package/:package/dist-tags/:tag',
can('publish'),
media(mime.getType('json')),
tag_package_version
);
route.post('/-/package/:package/dist-tags/:tag', can('publish'), media(mime.getType('json')), tag_package_version);
route.put(
'/-/package/:package/dist-tags/:tag',
can('publish'),
media(mime.getType('json')),
tag_package_version
);
route.put('/-/package/:package/dist-tags/:tag', can('publish'), media(mime.getType('json')), tag_package_version);
route.delete(
'/-/package/:package/dist-tags/:tag',
can('publish'),
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const tags = {};
tags[req.params.tag] = null;
storage.mergeTags(req.params.package, tags, function (err: VerdaccioError): $NextFunctionVer {
route.delete('/-/package/:package/dist-tags/:tag', can('publish'), function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const tags = {};
tags[req.params.tag] = null;
storage.mergeTags(req.params.package, tags, function (err: VerdaccioError): $NextFunctionVer {
if (err) {
return next(err);
}
res.status(HTTP_STATUS.CREATED);
return next({
ok: API_MESSAGE.TAG_REMOVED,
});
});
});
route.get('/-/package/:package/dist-tags', can('access'), function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
storage.getPackage({
name: req.params.package,
uplinksLook: true,
req,
callback: function (err: VerdaccioError, info: Package): $NextFunctionVer {
if (err) {
return next(err);
}
res.status(HTTP_STATUS.CREATED);
return next({
ok: API_MESSAGE.TAG_REMOVED
});
next(info[DIST_TAGS]);
},
});
});
route.post('/-/package/:package/dist-tags', can('publish'), function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
storage.mergeTags(req.params.package, req.body, function (err: VerdaccioError): $NextFunctionVer {
if (err) {
return next(err);
}
res.status(HTTP_STATUS.CREATED);
return next({
ok: API_MESSAGE.TAG_UPDATED,
});
}
);
route.get(
'/-/package/:package/dist-tags',
can('access'),
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
storage.getPackage({
name: req.params.package,
uplinksLook: true,
req,
callback: function (err: VerdaccioError, info: Package): $NextFunctionVer {
if (err) {
return next(err);
}
next(info[DIST_TAGS]);
}
});
}
);
route.post(
'/-/package/:package/dist-tags',
can('publish'),
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
storage.mergeTags(
req.params.package,
req.body,
function (err: VerdaccioError): $NextFunctionVer {
if (err) {
return next(err);
}
res.status(HTTP_STATUS.CREATED);
return next({
ok: API_MESSAGE.TAG_UPDATED
});
}
);
}
);
});
});
}

@ -1,24 +1,14 @@
import { allow } from '../../middleware';
import { convertDistRemoteToLocalTarballUrls, getVersion, ErrorCode } from '../../../lib/utils';
import { HEADERS, DIST_TAGS, API_ERROR } from '../../../lib/constants';
import {
IAuth,
$ResponseExtend,
$RequestExtend,
$NextFunctionVer,
IStorageHandler
} from '../../../../types';
import { Config, Package } from '@verdaccio/types';
import { Router } from 'express';
import _ from 'lodash';
const downloadStream = (
packageName: string,
filename: string,
storage: any,
req: $RequestExtend,
res: $ResponseExtend
): void => {
import { Config, Package } from '@verdaccio/types';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend, IAuth, IStorageHandler } from '../../../../types';
import { API_ERROR, DIST_TAGS, HEADERS } from '../../../lib/constants';
import { ErrorCode, convertDistRemoteToLocalTarballUrls, getVersion } from '../../../lib/utils';
import { allow } from '../../middleware';
const downloadStream = (packageName: string, filename: string, storage: any, req: $RequestExtend, res: $ResponseExtend): void => {
const stream = storage.getTarball(packageName, filename);
stream.on('content-length', function (content): void {
@ -33,101 +23,78 @@ const downloadStream = (
stream.pipe(res);
};
const redirectOrDownloadStream = (
packageName: string,
filename: string,
storage: any,
req: $RequestExtend,
res: $ResponseExtend,
config: Config
): void => {
const redirectOrDownloadStream = (packageName: string, filename: string, storage: any, req: $RequestExtend, res: $ResponseExtend, config: Config): void => {
const tarballUrlRedirect = _.get(config, 'experiments.tarball_url_redirect');
storage.hasLocalTarball(packageName, filename).then(hasLocalTarball => {
if (hasLocalTarball) {
const context = { packageName, filename };
const tarballUrl = typeof tarballUrlRedirect === 'function'
? tarballUrlRedirect(context)
: _.template(tarballUrlRedirect)(context);
res.redirect(tarballUrl);
} else {
downloadStream(packageName, filename, storage, req, res)
}
}).catch(err => {
res.locals.report_error(err);
});
}
storage
.hasLocalTarball(packageName, filename)
.then((hasLocalTarball) => {
if (hasLocalTarball) {
const context = { packageName, filename };
const tarballUrl = typeof tarballUrlRedirect === 'function' ? tarballUrlRedirect(context) : _.template(tarballUrlRedirect)(context);
res.redirect(tarballUrl);
} else {
downloadStream(packageName, filename, storage, req, res);
}
})
.catch((err) => {
res.locals.report_error(err);
});
};
export default function (
route: Router,
auth: IAuth,
storage: IStorageHandler,
config: Config
): void {
export default function (route: Router, auth: IAuth, storage: IStorageHandler, config: Config): void {
const can = allow(auth);
// TODO: anonymous user?
route.get(
'/:package/:version?',
can('access'),
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const getPackageMetaCallback = function (err, metadata: Package): void {
if (err) {
return next(err);
}
metadata = convertDistRemoteToLocalTarballUrls(metadata, req, config.url_prefix);
route.get('/:package/:version?', can('access'), function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const getPackageMetaCallback = function (err, metadata: Package): void {
if (err) {
return next(err);
}
metadata = convertDistRemoteToLocalTarballUrls(metadata, req, config.url_prefix);
let queryVersion = req.params.version;
if (_.isNil(queryVersion)) {
return next(metadata);
}
let queryVersion = req.params.version;
if (_.isNil(queryVersion)) {
return next(metadata);
}
let version = getVersion(metadata, queryVersion);
if (_.isNil(version) === false) {
return next(version);
}
let version = getVersion(metadata, queryVersion);
if (_.isNil(version) === false) {
return next(version);
}
if (_.isNil(metadata[DIST_TAGS]) === false) {
if (_.isNil(metadata[DIST_TAGS][queryVersion]) === false) {
queryVersion = metadata[DIST_TAGS][queryVersion];
version = getVersion(metadata, queryVersion);
if (_.isNil(version) === false) {
return next(version);
}
if (_.isNil(metadata[DIST_TAGS]) === false) {
if (_.isNil(metadata[DIST_TAGS][queryVersion]) === false) {
queryVersion = metadata[DIST_TAGS][queryVersion];
version = getVersion(metadata, queryVersion);
if (_.isNil(version) === false) {
return next(version);
}
}
return next(ErrorCode.getNotFound(`${API_ERROR.VERSION_NOT_EXIST}: ${req.params.version}`));
};
storage.getPackage({
name: req.params.package,
uplinksLook: true,
req,
callback: getPackageMetaCallback
});
}
);
route.get(
'/:scopedPackage/-/:scope/:filename',
can('access'),
function (req: $RequestExtend, res: $ResponseExtend): void {
const { scopedPackage, filename } = req.params;
if (_.get(config, 'experiments.tarball_url_redirect') === undefined) {
downloadStream(scopedPackage, filename, storage, req, res);
} else {
redirectOrDownloadStream(scopedPackage, filename, storage, req, res, config);
}
}
);
return next(ErrorCode.getNotFound(`${API_ERROR.VERSION_NOT_EXIST}: ${req.params.version}`));
};
route.get(
'/:package/-/:filename',
can('access'),
function (req: $RequestExtend, res: $ResponseExtend): void {
if (_.get(config, 'experiments.tarball_url_redirect') === undefined) {
downloadStream(req.params.package, req.params.filename, storage, req, res);
} else {
redirectOrDownloadStream(req.params.package, req.params.filename, storage, req, res, config);
}
storage.getPackage({
name: req.params.package,
uplinksLook: true,
req,
callback: getPackageMetaCallback,
});
});
route.get('/:scopedPackage/-/:scope/:filename', can('access'), function (req: $RequestExtend, res: $ResponseExtend): void {
const { scopedPackage, filename } = req.params;
if (_.get(config, 'experiments.tarball_url_redirect') === undefined) {
downloadStream(scopedPackage, filename, storage, req, res);
} else {
redirectOrDownloadStream(scopedPackage, filename, storage, req, res, config);
}
);
});
route.get('/:package/-/:filename', can('access'), function (req: $RequestExtend, res: $ResponseExtend): void {
if (_.get(config, 'experiments.tarball_url_redirect') === undefined) {
downloadStream(req.params.package, req.params.filename, storage, req, res);
} else {
redirectOrDownloadStream(req.params.package, req.params.filename, storage, req, res, config);
}
});
}

@ -2,15 +2,12 @@
* @prettier
* @flow
*/
import { $RequestExtend, $ResponseExtend, $NextFunctionVer } from '../../../../types';
import { Router } from 'express';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../../../../types';
export default function (route: Router): void {
route.get(
'/-/ping',
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
next({});
}
);
route.get('/-/ping', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
next({});
});
}

@ -1,19 +1,19 @@
import buildDebug from 'debug';
import { Router } from 'express';
import _ from 'lodash';
import mime from 'mime';
import Path from 'path';
import { API_MESSAGE, HEADERS, DIST_TAGS, API_ERROR, HTTP_STATUS } from '../../../lib/constants';
import { validateMetadata, isObject, ErrorCode, hasDiffOneKey, isRelatedToDeprecation } from '../../../lib/utils';
import { media, expectJson, allow } from '../../middleware';
import { notify } from '../../../lib/notify';
import { Callback, Config, MergeTags, Package, Version } from '@verdaccio/types';
import { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler } from '../../../../types';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend, IAuth, IStorageHandler } from '../../../../types';
import { API_ERROR, API_MESSAGE, DIST_TAGS, HEADERS, HTTP_STATUS } from '../../../lib/constants';
import { logger } from '../../../lib/logger';
import { notify } from '../../../lib/notify';
import { isPublishablePackage } from '../../../lib/storage-utils';
import { ErrorCode, hasDiffOneKey, isObject, isRelatedToDeprecation, validateMetadata } from '../../../lib/utils';
import { allow, expectJson, media } from '../../middleware';
import star from './star';
import { Config, Callback, MergeTags, Version, Package } from '@verdaccio/types';
import { Router } from 'express';
import mime from 'mime';
import buildDebug from 'debug';
import _ from 'lodash';
const debug = buildDebug('verdaccio:publish');

@ -1,11 +1,11 @@
// @flow
import { USERS, HTTP_STATUS } from '../../../lib/constants';
import { $RequestExtend, $NextFunctionVer, IStorageHandler } from '../../../../types';
import { logger } from '../../../lib/logger';
import buildDebug from 'debug';
import { Response } from 'express';
import _ from 'lodash';
import buildDebug from 'debug';
import { $NextFunctionVer, $RequestExtend, IStorageHandler } from '../../../../types';
import { HTTP_STATUS, USERS } from '../../../lib/constants';
import { logger } from '../../../lib/logger';
const debug = buildDebug('verdaccio:star');
export default function (storage: IStorageHandler): (req: $RequestExtend, res: Response, next: $NextFunctionVer) => void {

@ -2,36 +2,33 @@
* @prettier
*/
import { USERS, HTTP_STATUS } from '../../../lib/constants';
import { $RequestExtend, $NextFunctionVer, IStorageHandler } from '../../../../types';
import _ from 'lodash';
import { Response, Router } from 'express';
import _ from 'lodash';
import { Package } from '@verdaccio/types';
import { $NextFunctionVer, $RequestExtend, IStorageHandler } from '../../../../types';
import { HTTP_STATUS, USERS } from '../../../lib/constants';
type Packages = Package[];
export default function (route: Router, storage: IStorageHandler): void {
route.get(
'/-/_view/starredByUser',
(req: $RequestExtend, res: Response, next: $NextFunctionVer): void => {
const remoteUsername = req.remote_user.name;
route.get('/-/_view/starredByUser', (req: $RequestExtend, res: Response, next: $NextFunctionVer): void => {
const remoteUsername = req.remote_user.name;
storage.getLocalDatabase((err, localPackages: Packages) => {
if (err) {
return next(err);
}
storage.getLocalDatabase((err, localPackages: Packages) => {
if (err) {
return next(err);
}
const filteredPackages: Packages = localPackages.filter((localPackage: Package) =>
_.keys(localPackage[USERS]).includes(remoteUsername)
);
const filteredPackages: Packages = localPackages.filter((localPackage: Package) => _.keys(localPackage[USERS]).includes(remoteUsername));
res.status(HTTP_STATUS.OK);
next({
rows: filteredPackages.map((filteredPackage: Package) => ({
value: filteredPackage.name
}))
});
res.status(HTTP_STATUS.OK);
next({
rows: filteredPackages.map((filteredPackage: Package) => ({
value: filteredPackage.name,
})),
});
}
);
});
});
}

@ -1,16 +1,16 @@
import { ErrorCode } from '../../../lib/utils';
import { API_ERROR, API_MESSAGE, HEADERS, HTTP_STATUS } from '../../../lib/constants';
import { createRemoteUser, createSessionToken, getApiToken, getAuthenticatedMessage, validatePassword } from '../../../lib/auth-utils';
import { logger } from '../../../lib/logger';
import { $RequestExtend, $ResponseExtend, $NextFunctionVer, IAuth } from '../../../../types';
import { limiter } from '../../rate-limiter';
import express, { Response, Router } from 'express';
import { Config, RemoteUser } from '@verdaccio/types';
import Cookies from 'cookies';
import express, { Response, Router } from 'express';
import _ from 'lodash';
import { Config, RemoteUser } from '@verdaccio/types';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend, IAuth } from '../../../../types';
import { createRemoteUser, createSessionToken, getApiToken, getAuthenticatedMessage, validatePassword } from '../../../lib/auth-utils';
import { API_ERROR, API_MESSAGE, HEADERS, HTTP_STATUS } from '../../../lib/constants';
import { logger } from '../../../lib/logger';
import { ErrorCode } from '../../../lib/utils';
import { limiter } from '../../rate-limiter';
export default function (route: Router, auth: IAuth, config: Config): void {
/* eslint new-cap:off */
const userRouter = express.Router();

@ -1,6 +1,7 @@
import { Response, Router } from 'express';
import profile from './profile';
import token from './token';
import { Response, Router } from 'express';
export default (auth, storage, config) => {
const route = Router(); /* eslint new-cap: 0 */

@ -1,12 +1,12 @@
import { API_ERROR, APP_ERROR, HTTP_STATUS, SUPPORT_ERRORS } from '../../../../lib/constants';
import { ErrorCode } from '../../../../lib/utils';
import { validatePassword } from '../../../../lib/auth-utils';
import { $NextFunctionVer, $RequestExtend, IAuth } from '../../../../../types';
import { limiter } from '../../../rate-limiter';
import { Response, Router } from 'express';
import _ from 'lodash';
import { $NextFunctionVer, $RequestExtend, IAuth } from '../../../../../types';
import { validatePassword } from '../../../../lib/auth-utils';
import { API_ERROR, APP_ERROR, HTTP_STATUS, SUPPORT_ERRORS } from '../../../../lib/constants';
import { ErrorCode } from '../../../../lib/utils';
import { limiter } from '../../../rate-limiter';
export interface Profile {
tfa: boolean;
name: string;

@ -1,9 +1,11 @@
import { logger } from '../../../../lib/logger';
import { HTTP_STATUS } from '../../../../lib/constants';
import semver from 'semver';
import _ from 'lodash';
import semver from 'semver';
import { Package } from '@verdaccio/types';
import { HTTP_STATUS } from '../../../../lib/constants';
import { logger } from '../../../../lib/logger';
type PublisherMaintainer = {
username: string;
email: string;

@ -1,15 +1,16 @@
import { HEADERS, HTTP_STATUS, SUPPORT_ERRORS } from '../../../../lib/constants';
import { ErrorCode, mask } from '../../../../lib/utils';
import { getApiToken } from '../../../../lib/auth-utils';
import { stringToMD5 } from '../../../../lib/crypto-utils';
import { logger } from '../../../../lib/logger';
import buildDebug from 'debug';
import { Response, Router } from 'express';
import _ from 'lodash';
import { Config, RemoteUser, Token } from '@verdaccio/types';
import { $NextFunctionVer, $RequestExtend, IAuth, IStorageHandler } from '../../../../../types';
import { getApiToken } from '../../../../lib/auth-utils';
import { HEADERS, HTTP_STATUS, SUPPORT_ERRORS } from '../../../../lib/constants';
import { stringToMD5 } from '../../../../lib/crypto-utils';
import { logger } from '../../../../lib/logger';
import { ErrorCode, mask } from '../../../../lib/utils';
import { limiter } from '../../../rate-limiter';
import { Config, RemoteUser, Token } from '@verdaccio/types';
import { Response, Router } from 'express';
import buildDebug from 'debug';
import _ from 'lodash';
const debug = buildDebug('verdaccio:token');
export type NormalizeToken = Token & {

@ -1,6 +1,7 @@
import { $RequestExtend, $NextFunctionVer } from '../../../../types';
import { Response, Router } from 'express';
import { $NextFunctionVer, $RequestExtend } from '../../../../types';
export default function (route: Router): void {
route.get('/whoami', (req: $RequestExtend, res: Response, next: $NextFunctionVer): void => {
if (req.get('referer') === 'whoami') {

@ -1,19 +1,21 @@
import { IAuth, IStorageHandler } from '../../../types';
import whoami from './api/whoami';
import ping from './api/ping';
import user from './api/user';
import distTags from './api/dist-tags';
import publish from './api/publish';
import search from './api/search';
import pkg from './api/package';
import stars from './api/stars';
import npmV1 from './api/v1';
import v1Search from './api/v1/search';
import bodyParser from 'body-parser';
import express from 'express';
import _ from 'lodash';
import { Config } from '@verdaccio/types';
import { IAuth, IStorageHandler } from '../../../types';
import distTags from './api/dist-tags';
import pkg from './api/package';
import ping from './api/ping';
import publish from './api/publish';
import search from './api/search';
import stars from './api/stars';
import user from './api/user';
import npmV1 from './api/v1';
import v1Search from './api/v1/search';
import whoami from './api/whoami';
const { match, validateName, validatePackage, encodeScopePackage, antiLoop } = require('../middleware');
export default function (config: Config, auth: IAuth, storage: IStorageHandler) {

@ -1,23 +1,25 @@
import Storage from '../lib/storage';
import loadPlugin from '../lib/plugin-loader';
import Auth from '../lib/auth';
import { ErrorCode, getUserAgent } from '../lib/utils';
import { API_ERROR, HTTP_STATUS } from '../lib/constants';
import AppConfig from '../lib/config';
import { $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler, IAuth } from '../../types';
import { setup, logger } from '../lib/logger';
import webAPI from './web/api';
import web from './web';
import apiEndpoint from './endpoint';
import hookDebug from './debug';
import { log, final, errorReportingMiddleware, serveFavicon } from './middleware';
import { Config as IConfig, IPluginMiddleware, IPluginStorageFilter } from '@verdaccio/types';
import { HttpError } from 'http-errors';
import cors from 'cors';
import compression from 'compression';
import cors from 'cors';
import express, { Application } from 'express';
import { HttpError } from 'http-errors';
import _ from 'lodash';
import { Config as IConfig, IPluginMiddleware, IPluginStorageFilter } from '@verdaccio/types';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend, IAuth, IStorageHandler } from '../../types';
import Auth from '../lib/auth';
import AppConfig from '../lib/config';
import { API_ERROR, HTTP_STATUS } from '../lib/constants';
import { logger, setup } from '../lib/logger';
import loadPlugin from '../lib/plugin-loader';
import Storage from '../lib/storage';
import { ErrorCode, getUserAgent } from '../lib/utils';
import hookDebug from './debug';
import apiEndpoint from './endpoint';
import { errorReportingMiddleware, final, log, serveFavicon } from './middleware';
import web from './web';
import webAPI from './web/api';
const defineAPI = function (config: IConfig, storage: IStorageHandler): any {
const auth: IAuth = new Auth(config);
const app: Application = express();

@ -1,16 +1,17 @@
import fs from 'fs';
import path from 'path';
import { validateName as utilValidateName, validatePackage as utilValidatePackage, getVersionFromTarball, isObject, ErrorCode } from '../lib/utils';
import { API_ERROR, HEADER_TYPE, HEADERS, HTTP_STATUS, TOKEN_BASIC, TOKEN_BEARER } from '../lib/constants';
import { stringToMD5 } from '../lib/crypto-utils';
import { $ResponseExtend, $RequestExtend, $NextFunctionVer, IAuth } from '../../types';
import { logger } from '../lib/logger';
import _ from 'lodash';
import buildDebug from 'debug';
import fs from 'fs';
import _ from 'lodash';
import path from 'path';
import validator from 'validator';
import { Config, Package, RemoteUser } from '@verdaccio/types';
import { VerdaccioError } from '@verdaccio/commons-api';
import { Config, Package, RemoteUser } from '@verdaccio/types';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend, IAuth } from '../../types';
import { API_ERROR, HEADERS, HEADER_TYPE, HTTP_STATUS, TOKEN_BASIC, TOKEN_BEARER } from '../lib/constants';
import { stringToMD5 } from '../lib/crypto-utils';
import { logger } from '../lib/logger';
import { ErrorCode, getVersionFromTarball, isObject, validateName as utilValidateName, validatePackage as utilValidatePackage } from '../lib/utils';
const debug = buildDebug('verdaccio');

@ -1,4 +1,5 @@
import RateLimit from 'express-rate-limit';
import { RateLimit as RateLimitType } from '@verdaccio/types';
const limiter = (rateLimitOptions: RateLimitType) => {

@ -1,11 +1,13 @@
import Search from '../../lib/search';
import { match, validateName, validatePackage, setSecurityWebHeaders } from '../middleware';
import { IAuth, IStorageHandler } from '../../../types';
import webApi from './endpoint';
import { Config } from '@verdaccio/types';
import bodyParser from 'body-parser';
import { Router } from 'express';
import { Config } from '@verdaccio/types';
import { IAuth, IStorageHandler } from '../../../types';
import Search from '../../lib/search';
import { match, setSecurityWebHeaders, validateName, validatePackage } from '../middleware';
import webApi from './endpoint';
const route = Router(); /* eslint new-cap: 0 */
/*

@ -1,8 +1,9 @@
import { Response, Router } from 'express';
import { limiter } from '../../rate-limiter';
import packageApi from './package';
import search from './search';
import user from './user';
import { Response, Router } from 'express';
export default (auth, storage, config) => {
const route = Router(); /* eslint new-cap: 0 */

@ -1,24 +1,26 @@
import {
addScope,
addGravatarSupport,
deleteProperties,
sortByName,
parseReadme,
formatAuthor,
convertDistRemoteToLocalTarballUrls,
getLocalRegistryTarballUri,
isVersionValid,
ErrorCode,
} from '../../../lib/utils';
import { allow } from '../../middleware';
import { DIST_TAGS, HEADER_TYPE, HEADERS, HTTP_STATUS } from '../../../lib/constants';
import { generateGravatarUrl } from '../../../utils/user';
import { logger } from '../../../lib/logger';
import { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler, $SidebarPackage } from '../../../../types';
import { Config, Package } from '@verdaccio/types';
import { Router } from 'express';
import _ from 'lodash';
import { Config, Package } from '@verdaccio/types';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend, $SidebarPackage, IAuth, IStorageHandler } from '../../../../types';
import { DIST_TAGS, HEADERS, HEADER_TYPE, HTTP_STATUS } from '../../../lib/constants';
import { logger } from '../../../lib/logger';
import {
ErrorCode,
addGravatarSupport,
addScope,
convertDistRemoteToLocalTarballUrls,
deleteProperties,
formatAuthor,
getLocalRegistryTarballUri,
isVersionValid,
parseReadme,
sortByName,
} from '../../../lib/utils';
import { generateGravatarUrl } from '../../../utils/user';
import { allow } from '../../middleware';
const getOrder = (order = 'asc') => {
return order === 'asc';
};

@ -2,13 +2,14 @@
* @prettier
* @flow
*/
import Search from '../../../lib/search';
import { DIST_TAGS } from '../../../lib/constants';
import { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler } from '../../../../types';
import { Package } from '@verdaccio/types';
import { Router } from 'express';
import { Package } from '@verdaccio/types';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend, IAuth, IStorageHandler } from '../../../../types';
import { DIST_TAGS } from '../../../lib/constants';
import Search from '../../../lib/search';
function addSearchWebApi(storage: IStorageHandler, auth: IAuth): Router {
const route = Router(); /* eslint new-cap: 0 */
// Search package

@ -1,15 +1,16 @@
/**
* @prettier
*/
import { API_ERROR, APP_ERROR, HEADERS, HTTP_STATUS } from '../../../lib/constants';
import { IAuth, $NextFunctionVer } from '../../../../types';
import { ErrorCode } from '../../../lib/utils';
import { getSecurity, validatePassword } from '../../../lib/auth-utils';
import { Config, RemoteUser, JWTSignOptions } from '@verdaccio/types';
import express, { Router, Response, Request } from 'express';
import express, { Request, Response, Router } from 'express';
import _ from 'lodash';
import { Config, JWTSignOptions, RemoteUser } from '@verdaccio/types';
import { $NextFunctionVer, IAuth } from '../../../../types';
import { getSecurity, validatePassword } from '../../../lib/auth-utils';
import { API_ERROR, APP_ERROR, HEADERS, HTTP_STATUS } from '../../../lib/constants';
import { ErrorCode } from '../../../lib/utils';
function addUserAuthApi(auth: IAuth, config: Config): Router {
const route = Router(); /* eslint new-cap: 0 */
route.post('/login', function (req: Request, res: Response, next: $NextFunctionVer): void {

@ -1,12 +1,13 @@
import { URL } from 'url';
import path from 'path';
import { getPublicUrl, isHTTPProtocol } from '../../../lib/utils';
import { WEB_TITLE } from '../../../lib/constants';
import renderTemplate from './template';
import buildDebug from 'debug';
import LRU from 'lru-cache';
import path from 'path';
import { URL } from 'url';
import { HEADERS } from '@verdaccio/commons-api';
import { WEB_TITLE } from '../../../lib/constants';
import { getPublicUrl, isHTTPProtocol } from '../../../lib/utils';
import renderTemplate from './template';
const pkgJSON = require('../../../../package.json');
const DEFAULT_LANGUAGE = 'es-US';

@ -1,6 +1,7 @@
import { getManifestValue, Manifest } from './manifest';
import buildDebug from 'debug';
import { Manifest, getManifestValue } from './manifest';
const debug = buildDebug('verdaccio');
export type TemplateUIOptions = {
@ -52,7 +53,9 @@ export default function renderTemplate(template: Template, manifest: WebpackMani
<body class="body">
${template?.scriptsbodyBefore ? template.scriptsbodyBefore.join('') : ''}
<div id="root"></div>
${getManifestValue(template.manifest.js, manifest, template?.options.base).map((item) => `<script defer="defer" src="${item}"></script>`).join('')}
${getManifestValue(template.manifest.js, manifest, template?.options.base)
.map((item) => `<script defer="defer" src="${item}"></script>`)
.join('')}
${template?.scriptsBodyAfter ? template.scriptsBodyAfter.join('') : ''}
</body>
</html>

@ -1,18 +1,17 @@
import fs from 'fs';
import path from 'path';
import Search from '../../lib/search';
import { HTTP_STATUS } from '../../lib/constants';
import loadPlugin from '../../lib/plugin-loader';
import { isHTTPProtocol } from '../../lib/utils';
import { logger } from '../../lib/logger';
import renderHTML from './html/renderHTML';
import { Config } from '@verdaccio/types';
import buildDebug from 'debug';
import express from 'express';
import fs from 'fs';
import _ from 'lodash';
import path from 'path';
import { Config } from '@verdaccio/types';
import { HTTP_STATUS } from '../../lib/constants';
import { logger } from '../../lib/logger';
import loadPlugin from '../../lib/plugin-loader';
import Search from '../../lib/search';
import { isHTTPProtocol } from '../../lib/utils';
import renderHTML from './html/renderHTML';
const { setSecurityWebHeaders } = require('../middleware');

@ -9,5 +9,5 @@ const APP_ROOT = path.resolve(__dirname, '../../');
module.exports = {
APP_ROOT,
SRC_ROOT: path.resolve(APP_ROOT, 'src/'),
DIST_PATH: path.resolve(APP_ROOT, 'static/')
DIST_PATH: path.resolve(APP_ROOT, 'static/'),
};

@ -1,5 +1,4 @@
// @flow
import { startVerdaccio } from './lib/bootstrap';
export default startVerdaccio;

@ -1,12 +1,14 @@
import { CookieSessionToken, IAuthWebUI, AuthMiddlewarePayload, AuthTokenHeader, BasicPayload } from '../../types';
import { logger } from '../lib/logger';
import { convertPayloadToBase64, ErrorCode } from './utils';
import { API_ERROR, HTTP_STATUS, ROLES, TIME_EXPIRATION_1H, TOKEN_BASIC, TOKEN_BEARER, DEFAULT_MIN_LIMIT_PASSWORD } from './constants';
import { aesDecrypt, verifyPayload } from './crypto-utils';
import { RemoteUser, Package, Callback, Config, Security, APITokenOptions, JWTOptions, IPluginAuth } from '@verdaccio/types';
import buildDebug from 'debug';
import _ from 'lodash';
import { APITokenOptions, Callback, Config, IPluginAuth, JWTOptions, Package, RemoteUser, Security } from '@verdaccio/types';
import { AuthMiddlewarePayload, AuthTokenHeader, BasicPayload, CookieSessionToken, IAuthWebUI } from '../../types';
import { logger } from '../lib/logger';
import { API_ERROR, DEFAULT_MIN_LIMIT_PASSWORD, HTTP_STATUS, ROLES, TIME_EXPIRATION_1H, TOKEN_BASIC, TOKEN_BEARER } from './constants';
import { aesDecrypt, verifyPayload } from './crypto-utils';
import { ErrorCode, convertPayloadToBase64 } from './utils';
const debug = buildDebug('verdaccio');
export function validatePassword(

@ -1,27 +1,29 @@
import buildDebug from 'debug';
import { NextFunction } from 'express';
import _ from 'lodash';
import { VerdaccioError } from '@verdaccio/commons-api';
import { AllowAccess, AuthPluginPackage, Callback, Config, IPluginAuth, JWTSignOptions, Logger, PackageAccess, RemoteUser, Security } from '@verdaccio/types';
import { $RequestExtend, $ResponseExtend, AESPayload, IAuth } from '../../types';
import loadPlugin from '../lib/plugin-loader';
import { $RequestExtend, $ResponseExtend, IAuth, AESPayload } from '../../types';
import {
createAnonymousRemoteUser,
createRemoteUser,
getDefaultPlugins,
getMiddlewareCredentials,
getSecurity,
isAESLegacy,
isAuthHeaderValid,
parseAuthTokenHeader,
parseBasicPayload,
verifyJWTPayload,
} from './auth-utils';
import { getMatchedPackagesSpec } from './config-utils';
import { API_ERROR, SUPPORT_ERRORS, TOKEN_BASIC, TOKEN_BEARER } from './constants';
import { aesEncrypt, signPayload } from './crypto-utils';
import { logger } from './logger';
import {
getDefaultPlugins,
getMiddlewareCredentials,
verifyJWTPayload,
createAnonymousRemoteUser,
isAuthHeaderValid,
getSecurity,
isAESLegacy,
parseAuthTokenHeader,
parseBasicPayload,
createRemoteUser,
} from './auth-utils';
import { convertPayloadToBase64, ErrorCode } from './utils';
import { getMatchedPackagesSpec } from './config-utils';
import { NextFunction } from 'express';
import { Config, Logger, Callback, IPluginAuth, RemoteUser, JWTSignOptions, Security, AuthPluginPackage, AllowAccess, PackageAccess } from '@verdaccio/types';
import buildDebug from 'debug';
import { VerdaccioError } from '@verdaccio/commons-api';
import _ from 'lodash';
import { ErrorCode, convertPayloadToBase64 } from './utils';
const debug = buildDebug('verdaccio:auth');

@ -1,16 +1,17 @@
import URL from 'url';
import constants from 'constants';
import express from 'express';
import { Application } from 'express';
import fs from 'fs';
import http from 'http';
import https from 'https';
import constants from 'constants';
import endPointAPI from '../api/index';
import { API_ERROR, certPem, csrPem, keyPem } from './constants';
import { getListListenAddresses, resolveConfigPath } from './cli/utils';
import express from 'express';
import { assign, isObject, isFunction } from 'lodash';
import { assign, isFunction, isObject } from 'lodash';
import URL from 'url';
import { Callback, ConfigWithHttps, HttpsConfKeyCert, HttpsConfPfx } from '@verdaccio/types';
import { Application } from 'express';
import endPointAPI from '../api/index';
import { getListListenAddresses, resolveConfigPath } from './cli/utils';
import { API_ERROR, certPem, csrPem, keyPem } from './constants';
const logger = require('./logger');

@ -1,8 +1,9 @@
import { Cli } from 'clipanion';
import { InfoCommand } from './commands/info';
import { InitCommand } from './commands/init';
import { isVersionValid, MIN_NODE_VERSION } from './utils';
import { VersionCommand } from './commands/version';
import { Cli } from 'clipanion';
import { MIN_NODE_VERSION, isVersionValid } from './utils';
require('pkginfo')(module);
const pkgVersion = module.exports.version;

@ -1,5 +1,5 @@
import envinfo from 'envinfo';
import { Command } from 'clipanion';
import envinfo from 'envinfo';
export class InfoCommand extends Command {
static paths = [[`--info`], [`-i`]];

@ -1,9 +1,9 @@
import { Command, Option } from 'clipanion';
import path from 'path';
import { startVerdaccio, listenDefaultCallback } from '../../bootstrap';
import { listenDefaultCallback, startVerdaccio } from '../../bootstrap';
import findConfigFile from '../../config-path';
import { parseConfigFile } from '../../utils';
import { Command, Option } from 'clipanion';
require('pkginfo')(module);
const pkgVersion = module.exports.version;

@ -1,4 +1,5 @@
import { Command } from 'clipanion';
require('pkginfo')(module);
const pkgVersion = module.exports.version;

@ -1,9 +1,9 @@
import path from 'path';
import { parseAddress } from '../utils';
import { DEFAULT_PORT } from '../constants';
import semver from 'semver';
import { DEFAULT_PORT } from '../constants';
import { parseAddress } from '../utils';
const logger = require('../logger');
export const resolveConfigPath = function (storageLocation: string, file: string) {
@ -16,7 +16,6 @@ export function isVersionValid(version) {
return semver.satisfies(version, `>=${MIN_NODE_VERSION}`);
}
/**
* Retrieve all addresses defined in the config file.
* Verdaccio is able to listen multiple ports
@ -48,9 +47,7 @@ export function getListListenAddresses(argListen: string, configListen: any): an
if (!parsedAddr) {
logger.logger.warn(
{ addr: addr },
'invalid address - @{addr}, we expect a port (e.g. "4873"),' +
' host:port (e.g. "localhost:4873") or full url' +
' (e.g. "http://localhost:4873/")'
'invalid address - @{addr}, we expect a port (e.g. "4873"),' + ' host:port (e.g. "localhost:4873") or full url' + ' (e.g. "http://localhost:4873/")'
);
}

@ -1,11 +1,11 @@
import fs from 'fs';
import Path from 'path';
import { logger } from './logger';
import { folderExists, fileExists } from './utils';
import { CHARACTER_ENCODING } from './constants';
import mkdirp from 'mkdirp';
import _ from 'lodash';
import mkdirp from 'mkdirp';
import Path from 'path';
import { CHARACTER_ENCODING } from './constants';
import { logger } from './logger';
import { fileExists, folderExists } from './utils';
const CONFIG_FILE = 'config.yaml';
const XDG = 'xdg';
@ -34,9 +34,7 @@ function findConfigFile(configPath: string): string {
throw new Error('no configuration files can be processed');
}
const primaryConf: any = _.find(configPaths, (configLocation: any) =>
fileExists(configLocation.path)
);
const primaryConf: any = _.find(configPaths, (configLocation: any) => fileExists(configLocation.path));
if (_.isNil(primaryConf) === false) {
return primaryConf.path;
}
@ -71,8 +69,7 @@ function updateStorageLinks(configLocation, defaultConfig): string {
// $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored,
// If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used.
// $FlowFixMe
let dataDir =
process.env.XDG_DATA_HOME || Path.join(process.env.HOME as string, '.local', 'share');
let dataDir = process.env.XDG_DATA_HOME || Path.join(process.env.HOME as string, '.local', 'share');
if (folderExists(dataDir)) {
dataDir = Path.resolve(Path.join(dataDir, pkgJSON.name, 'storage'));
return defaultConfig.replace(/^storage: .\/storage$/m, `storage: ${dataDir}`);
@ -81,17 +78,16 @@ function updateStorageLinks(configLocation, defaultConfig): string {
}
function getConfigPaths(): SetupDirectory[] {
const listPaths: SetupDirectory[] = [
getXDGDirectory(),
getWindowsDirectory(),
getRelativeDefaultDirectory(),
getOldDirectory()
].reduce(function (acc, currentValue: any): SetupDirectory[] {
const listPaths: SetupDirectory[] = [getXDGDirectory(), getWindowsDirectory(), getRelativeDefaultDirectory(), getOldDirectory()].reduce(function (
acc,
currentValue: any
): SetupDirectory[] {
if (_.isUndefined(currentValue) === false) {
acc.push(currentValue);
}
return acc;
}, [] as SetupDirectory[]);
},
[] as SetupDirectory[]);
return listPaths;
}
@ -102,7 +98,7 @@ const getXDGDirectory = (): SetupDirectory | void => {
if (XDGConfig && folderExists(XDGConfig)) {
return {
path: Path.join(XDGConfig, pkgJSON.name, CONFIG_FILE),
type: XDG
type: XDG,
};
}
};
@ -113,7 +109,7 @@ const getWindowsDirectory = (): SetupDirectory | void => {
if (process.platform === WIN32 && process.env.APPDATA && folderExists(process.env.APPDATA)) {
return {
path: Path.resolve(Path.join(process.env.APPDATA, pkgJSON.name, CONFIG_FILE)),
type: WIN
type: WIN,
};
}
};
@ -121,14 +117,14 @@ const getWindowsDirectory = (): SetupDirectory | void => {
const getRelativeDefaultDirectory = (): SetupDirectory => {
return {
path: Path.resolve(Path.join('.', pkgJSON.name, CONFIG_FILE)),
type: 'def'
type: 'def',
};
};
const getOldDirectory = (): SetupDirectory => {
return {
path: Path.resolve(Path.join('.', CONFIG_FILE)),
type: 'old'
type: 'old',
};
};

@ -2,21 +2,21 @@
* @prettier
* @flow
*/
import assert from 'assert';
import { MatchedPackage, LegacyPackageList } from '../../types';
import { ErrorCode } from './utils';
import _ from 'lodash';
import minimatch from 'minimatch';
import { PackageList, UpLinksConfList } from '@verdaccio/types';
import { LegacyPackageList, MatchedPackage } from '../../types';
import { ErrorCode } from './utils';
const BLACKLIST = {
all: true,
anonymous: true,
undefined: true,
owner: true,
none: true
none: true,
};
/**
@ -38,18 +38,13 @@ export function normalizeUserList(oldFormat: any, newFormat: any): any {
} else if (Array.isArray(arguments[i])) {
result.push(arguments[i]);
} else {
throw ErrorCode.getInternalError(
'CONFIG: bad package acl (array or string expected): ' + JSON.stringify(arguments[i])
);
throw ErrorCode.getInternalError('CONFIG: bad package acl (array or string expected): ' + JSON.stringify(arguments[i]));
}
}
return _.flatten(result);
}
export function uplinkSanityCheck(
uplinks: UpLinksConfList,
users: any = BLACKLIST
): UpLinksConfList {
export function uplinkSanityCheck(uplinks: UpLinksConfList, users: any = BLACKLIST): UpLinksConfList {
const newUplinks = _.clone(uplinks);
let newUsers = _.clone(users);
@ -66,14 +61,7 @@ export function uplinkSanityCheck(
}
export function sanityCheckNames(item: string, users: any): any {
assert(
item !== 'all' &&
item !== 'owner' &&
item !== 'anonymous' &&
item !== 'undefined' &&
item !== 'none',
'CONFIG: reserved uplink name: ' + item
);
assert(item !== 'all' && item !== 'owner' && item !== 'anonymous' && item !== 'undefined' && item !== 'none', 'CONFIG: reserved uplink name: ' + item);
assert(!item.match(/\s/), 'CONFIG: invalid uplink name: ' + item);
assert(_.isNil(users[item]), 'CONFIG: duplicate uplink name: ' + item);
users[item] = true;
@ -126,29 +114,15 @@ export function normalisePackageAccess(packages: LegacyPackageList): LegacyPacka
for (const pkg in packages) {
if (Object.prototype.hasOwnProperty.call(packages, pkg)) {
assert(
_.isObject(packages[pkg]) && _.isArray(packages[pkg]) === false,
`CONFIG: bad "'${pkg}'" package description (object expected)`
);
normalizedPkgs[pkg].access = normalizeUserList(
packages[pkg].allow_access,
packages[pkg].access
);
assert(_.isObject(packages[pkg]) && _.isArray(packages[pkg]) === false, `CONFIG: bad "'${pkg}'" package description (object expected)`);
normalizedPkgs[pkg].access = normalizeUserList(packages[pkg].allow_access, packages[pkg].access);
delete normalizedPkgs[pkg].allow_access;
normalizedPkgs[pkg].publish = normalizeUserList(
packages[pkg].allow_publish,
packages[pkg].publish
);
normalizedPkgs[pkg].publish = normalizeUserList(packages[pkg].allow_publish, packages[pkg].publish);
delete normalizedPkgs[pkg].allow_publish;
normalizedPkgs[pkg].proxy = normalizeUserList(
packages[pkg].proxy_access,
packages[pkg].proxy
);
normalizedPkgs[pkg].proxy = normalizeUserList(packages[pkg].proxy_access, packages[pkg].proxy);
delete normalizedPkgs[pkg].proxy_access;
// if unpublish is not defined, we set to false to fallback in publish access
normalizedPkgs[pkg].unpublish = _.isUndefined(packages[pkg].unpublish)
? false
: normalizeUserList([], packages[pkg].unpublish);
normalizedPkgs[pkg].unpublish = _.isUndefined(packages[pkg].unpublish) ? false : normalizeUserList([], packages[pkg].unpublish);
}
}

@ -1,13 +1,14 @@
import assert from 'assert';
import _ from 'lodash';
import { Config as AppConfig, Logger, PackageList, RateLimit, Security } from '@verdaccio/types';
import { MatchedPackage, StartUpConfig } from '../../types';
import { generateRandomHexString } from './crypto-utils';
import { getMatchedPackagesSpec, normalisePackageAccess, sanityCheckUplinksProps, uplinkSanityCheck } from './config-utils';
import { getUserAgent, isObject } from './utils';
import { APP_ERROR } from './constants';
import { defaultUserRateLimiting } from './auth-utils';
import { PackageList, Config as AppConfig, Security, Logger, RateLimit } from '@verdaccio/types';
import _ from 'lodash';
import { getMatchedPackagesSpec, normalisePackageAccess, sanityCheckUplinksProps, uplinkSanityCheck } from './config-utils';
import { APP_ERROR } from './constants';
import { generateRandomHexString } from './crypto-utils';
import { getUserAgent, isObject } from './utils';
const LoggerApi = require('./logger');
const strategicConfigProps = ['uplinks', 'packages'];

@ -1,4 +1,4 @@
import { createDecipher, createCipher, createHash, pseudoRandomBytes, Hash } from 'crypto';
import { Hash, createCipher, createDecipher, createHash, pseudoRandomBytes } from 'crypto';
import jwt from 'jsonwebtoken';
import { JWTSignOptions, RemoteUser } from '@verdaccio/types';
@ -49,18 +49,14 @@ export function generateRandomHexString(length = 8): string {
return pseudoRandomBytes(length).toString('hex');
}
export async function signPayload(
payload: RemoteUser,
secretOrPrivateKey: string,
options: JWTSignOptions
): Promise<string> {
export async function signPayload(payload: RemoteUser, secretOrPrivateKey: string, options: JWTSignOptions): Promise<string> {
return new Promise(function (resolve, reject): Promise<string> {
return jwt.sign(
payload,
secretOrPrivateKey,
{
notBefore: '1', // Make sure the time will not rollback :)
...options
...options,
},
(error, token) => (error ? reject(error) : resolve(token))
);

@ -1,37 +1,39 @@
import assert from 'assert';
import builDebug from 'debug';
import _ from 'lodash';
import UrlNode from 'url';
import loadPlugin from '../lib/plugin-loader';
import { IStorage, StringValue } from '../../types';
import { ErrorCode, isObject, getLatestVersion, tagVersion, validateName } from './utils';
import { generatePackageTemplate, normalizePackage, generateRevision, getLatestReadme, cleanUpReadme, normalizeContributors } from './storage-utils';
import { API_ERROR, DIST_TAGS, HTTP_STATUS, STORAGE, SUPPORT_ERRORS, USERS } from './constants';
import { createTarballHash } from './crypto-utils';
import { prepareSearchPackage } from './storage-utils';
import { VerdaccioError } from '@verdaccio/commons-api';
import LocalDatabase from '@verdaccio/local-storage';
import { ReadTarball, UploadTarball } from '@verdaccio/streams';
import {
Author,
Callback,
CallbackAction,
Config,
DistFile,
IPackageStorage,
IPluginStorage,
IReadTarball,
IUploadTarball,
Logger,
MergeTags,
Package,
StorageUpdateCallback,
Token,
TokenFilter,
Package,
Config,
IUploadTarball,
IReadTarball,
MergeTags,
Version,
DistFile,
Callback,
Logger,
IPluginStorage,
IPackageStorage,
Author,
CallbackAction,
onSearchPackage,
onEndSearchPackage,
StorageUpdateCallback,
onSearchPackage,
} from '@verdaccio/types';
import { UploadTarball, ReadTarball } from '@verdaccio/streams';
import LocalDatabase from '@verdaccio/local-storage';
import _ from 'lodash';
import builDebug from 'debug';
import { IStorage, StringValue } from '../../types';
import loadPlugin from '../lib/plugin-loader';
import { API_ERROR, DIST_TAGS, HTTP_STATUS, STORAGE, SUPPORT_ERRORS, USERS } from './constants';
import { createTarballHash } from './crypto-utils';
import { cleanUpReadme, generatePackageTemplate, generateRevision, getLatestReadme, normalizeContributors, normalizePackage } from './storage-utils';
import { prepareSearchPackage } from './storage-utils';
import { ErrorCode, getLatestVersion, isObject, tagVersion, validateName } from './utils';
const debug = builDebug('verdaccio:local-storage');
/**
@ -842,14 +844,9 @@ class LocalStorage implements IStorage {
};
// eslint-disable-next-line max-len
const plugins: IPluginStorage<Config>[] = loadPlugin<IPluginStorage<Config>>(
this.config,
this.config.store,
plugin_params,
(plugin): IPluginStorage<Config> => {
return plugin.getPackageStorage;
}
);
const plugins: IPluginStorage<Config>[] = loadPlugin<IPluginStorage<Config>>(this.config, this.config.store, plugin_params, (plugin): IPluginStorage<Config> => {
return plugin.getPackageStorage;
});
return _.head(plugins);
}

@ -1,4 +1,4 @@
import { printMessage, PrettyOptionsExtended } from './prettifier';
import { PrettyOptionsExtended, printMessage } from './prettifier';
export type PrettyFactory = (param) => string;

@ -1,27 +1,27 @@
import { inspect } from 'util';
import {calculateLevel, LevelCode, levelsColors, subSystemLevels} from "../levels";
import { padLeft, padRight } from '../utils';
import { white, red, green } from 'kleur';
import _ from 'lodash';
import dayjs from 'dayjs';
import {PrettyOptions} from "pino";
import { green, red, white } from 'kleur';
import _ from 'lodash';
import { PrettyOptions } from 'pino';
import { inspect } from 'util';
import { LevelCode, calculateLevel, levelsColors, subSystemLevels } from '../levels';
import { padLeft, padRight } from '../utils';
export const CUSTOM_PAD_LENGTH = 1;
export const FORMAT_DATE = 'YYYY-MM-DD HH:mm:ss';
export function isObject(obj: unknown): boolean {
return _.isObject(obj) && _.isNull(obj) === false && _.isArray(obj) === false;
return _.isObject(obj) && _.isNull(obj) === false && _.isArray(obj) === false;
}
export function formatLoggingDate(time: number, message): string {
const timeFormatted = dayjs(time).format(FORMAT_DATE);
const timeFormatted = dayjs(time).format(FORMAT_DATE);
return `[${timeFormatted}]${message}`;
return `[${timeFormatted}]${message}`;
}
export interface PrettyOptionsExtended extends PrettyOptions {
prettyStamp: boolean;
export interface PrettyOptionsExtended extends PrettyOptions {
prettyStamp: boolean;
}
let LEVEL_VALUE_MAX = 0;
// eslint-disable-next-line guard-for-in
@ -42,7 +42,6 @@ export function fillInMsgTemplate(msg, templateOptions: ObjectTemplate, colors):
const templateRegex = /@{(!?[$A-Za-z_][$0-9A-Za-z\._]*)}/g;
return msg.replace(templateRegex, (_, name): string => {
let str = templateOptions;
let isError;
if (name[0] === ERROR_FLAG) {
@ -87,10 +86,7 @@ function getMessage(debugLevel, msg, sub, templateObjects, hasColors) {
return padRight(logString);
}
export function printMessage(
templateObjects: ObjectTemplate,
options: PrettyOptionsExtended,
hasColors = true): string {
export function printMessage(templateObjects: ObjectTemplate, options: PrettyOptionsExtended, hasColors = true): string {
const { prettyStamp } = options;
const { level, msg, sub } = templateObjects;
const debugLevel = calculateLevel(level);

@ -1,58 +1,58 @@
import { yellow, green, red, magenta, black, blue, cyan, white } from 'kleur';
import { black, blue, cyan, green, magenta, red, white, yellow } from 'kleur';
export type LogLevel = 'trace' | 'debug' | 'info' | 'http' | 'warn' | 'error' | 'fatal';
export type LevelCode = number;
export function calculateLevel(levelCode: LevelCode): LogLevel {
switch (true) {
case levelCode === 10:
return 'trace';
case levelCode === 20:
return 'debug';
case levelCode === 25:
return 'http';
case levelCode === 30:
return 'info';
case levelCode === 40:
return 'warn';
case levelCode === 50:
return 'error';
case levelCode === 60:
return 'fatal';
default:
return 'fatal';
}
switch (true) {
case levelCode === 10:
return 'trace';
case levelCode === 20:
return 'debug';
case levelCode === 25:
return 'http';
case levelCode === 30:
return 'info';
case levelCode === 40:
return 'warn';
case levelCode === 50:
return 'error';
case levelCode === 60:
return 'fatal';
default:
return 'fatal';
}
}
export const levelsColors = {
fatal: red,
error: red,
warn: yellow,
http: magenta,
info: cyan,
debug: green,
trace: white,
fatal: red,
error: red,
warn: yellow,
http: magenta,
info: cyan,
debug: green,
trace: white,
};
enum ARROWS {
LEFT = '<--',
RIGHT = '-->',
EQUAL = '-=-',
NEUTRAL = '---'
NEUTRAL = '---',
}
export const subSystemLevels = {
color: {
in: green(ARROWS.LEFT),
out: yellow(ARROWS.RIGHT),
fs: black(ARROWS.EQUAL),
default: blue(ARROWS.NEUTRAL),
in: green(ARROWS.LEFT),
out: yellow(ARROWS.RIGHT),
fs: black(ARROWS.EQUAL),
default: blue(ARROWS.NEUTRAL),
},
white: {
in: ARROWS.LEFT,
out: ARROWS.RIGHT,
fs: ARROWS.EQUAL,
default: ARROWS.NEUTRAL,
in: ARROWS.LEFT,
out: ARROWS.RIGHT,
fs: ARROWS.EQUAL,
default: ARROWS.NEUTRAL,
},
};

@ -1,8 +1,9 @@
import { padLeft } from './utils';
import pino from 'pino';
import _ from 'lodash';
import buildDebug from 'debug';
import { yellow } from 'kleur';
import _ from 'lodash';
import pino from 'pino';
import { padLeft } from './utils';
function isProd() {
return process.env.NODE_ENV === 'production';
@ -21,7 +22,7 @@ export type LogType = 'file' | 'stdout';
export type LogFormat = 'json' | 'pretty-timestamped' | 'pretty';
export function createLogger(
options = {level: 'http'},
options = { level: 'http' },
destination = pino.destination(1),
format: LogFormat = DEFAULT_LOG_FORMAT,
prettyPrintOptions = {
@ -63,10 +64,10 @@ export function createLogger(
}
const logger = pino(pinoConfig, destination);
if(process.env.DEBUG) {
if (process.env.DEBUG) {
logger.on('level-change', (lvl, val, prevLvl, prevVal) => {
debug('%s (%d) was changed to %s (%d)', lvl, val, prevLvl, prevVal);
})
});
}
return logger;
@ -110,9 +111,13 @@ export function setup(options: LoggerConfig | LoggerConfigItem = [DEFAULT_LOGGER
// next major will thrown an error
let loggerConfig = isLegacyConf ? options[0] : options;
if (!loggerConfig?.level) {
loggerConfig = Object.assign({}, {
level: 'http',
}, loggerConfig);
loggerConfig = Object.assign(
{},
{
level: 'http',
},
loggerConfig
);
}
const pinoConfig = { level: loggerConfig.level };
if (loggerConfig.type === 'file') {

@ -11,6 +11,6 @@ export function padLeft(message: string) {
return message.padStart(message.length + CUSTOM_PAD_LENGTH, ' ');
}
export function padRight(message: string, max = message.length + CUSTOM_PAD_LENGTH ) {
export function padRight(message: string, max = message.length + CUSTOM_PAD_LENGTH) {
return message.padEnd(max, ' ');
}

@ -2,11 +2,12 @@
* @prettier
* @flow
*/
import _ from 'lodash';
import semver from 'semver';
import { Package } from '@verdaccio/types';
import { DIST_TAGS } from './constants';
import semver from 'semver';
import _ from 'lodash';
import { Package } from '@verdaccio/types';
/**
* Function gets a local info and an info from uplinks and tries to merge it

@ -1,18 +1,14 @@
import { notifyRequest } from './notify-request';
import Handlebars from 'handlebars';
import _ from 'lodash';
import { OptionsWithUrl } from 'request';
import { Config, Package, RemoteUser } from '@verdaccio/types';
import { notifyRequest } from './notify-request';
type TemplateMetadata = Package & { publishedPackage: string };
export function handleNotify(
metadata: Package,
notifyEntry,
remoteUser: RemoteUser,
publishedPackage: string
): Promise<any> | void {
export function handleNotify(metadata: Package, notifyEntry, remoteUser: RemoteUser, publishedPackage: string): Promise<any> | void {
let regex;
if (metadata.name && notifyEntry.packagePattern) {
regex = new RegExp(notifyEntry.packagePattern, notifyEntry.packagePatternFlags || '');
@ -35,7 +31,7 @@ export function handleNotify(
const options: OptionsWithUrl = {
body: content,
url: ''
url: '',
};
// provides fallback support, it's accept an Object {} and Array of {}
@ -65,34 +61,17 @@ export function handleNotify(
return notifyRequest(options, content);
}
export function sendNotification(
metadata: Package,
notify: any,
remoteUser: RemoteUser,
publishedPackage: string
): Promise<any> {
export function sendNotification(metadata: Package, notify: any, remoteUser: RemoteUser, publishedPackage: string): Promise<any> {
return handleNotify(metadata, notify, remoteUser, publishedPackage) as Promise<any>;
}
export function notify(
metadata: Package,
config: Config,
remoteUser: RemoteUser,
publishedPackage: string
): Promise<any> | void {
export function notify(metadata: Package, config: Config, remoteUser: RemoteUser, publishedPackage: string): Promise<any> | void {
if (config.notify) {
if (config.notify.content) {
return sendNotification(
metadata,
(config.notify as unknown) as any,
remoteUser,
publishedPackage
);
return sendNotification(metadata, config.notify as unknown as any, remoteUser, publishedPackage);
}
// multiple notifications endpoints PR #108
return Promise.all(
_.map(config.notify, (key) => sendNotification(metadata, key, remoteUser, publishedPackage))
);
return Promise.all(_.map(config.notify, (key) => sendNotification(metadata, key, remoteUser, publishedPackage)));
}
return Promise.resolve();

@ -1,9 +1,10 @@
import { logger } from '../logger';
import { HTTP_STATUS } from '../constants';
import isNil from 'lodash/isNil';
import buildDebug from 'debug';
import isNil from 'lodash/isNil';
import request, { RequiredUriUrl } from 'request';
import { HTTP_STATUS } from '../constants';
import { logger } from '../logger';
const debug = buildDebug('verdaccio:notify-request');
export function notifyRequest(options: RequiredUriUrl, content): Promise<any | Error> {
return new Promise((resolve, reject): void => {

@ -1,9 +1,11 @@
import Path from 'path';
import { logger } from './logger';
import { MODULE_NOT_FOUND } from './constants';
import _ from 'lodash';
import Path from 'path';
import { Config, IPlugin } from '@verdaccio/types';
import { MODULE_NOT_FOUND } from './constants';
import { logger } from './logger';
/**
* Requires a module.
* @param {*} path the module's path
@ -46,96 +48,74 @@ function isES6(plugin): boolean {
* @param {*} sanityCheck callback that check the shape that should fulfill the plugin
* @return {Array} list of plugins
*/
export default function loadPlugin<T extends IPlugin<T>>(
config: Config,
pluginConfigs: any = {},
params: any,
sanityCheck: any,
prefix: string = 'verdaccio'
): any[] {
return Object.keys(pluginConfigs).map(
(pluginId: string): IPlugin<T> => {
let plugin;
export default function loadPlugin<T extends IPlugin<T>>(config: Config, pluginConfigs: any = {}, params: any, sanityCheck: any, prefix: string = 'verdaccio'): any[] {
return Object.keys(pluginConfigs).map((pluginId: string): IPlugin<T> => {
let plugin;
const localPlugin = Path.resolve(__dirname + '/../plugins', pluginId);
// try local plugins first
plugin = tryLoad(localPlugin);
const localPlugin = Path.resolve(__dirname + '/../plugins', pluginId);
// try local plugins first
plugin = tryLoad(localPlugin);
// try the external plugin directory
if (plugin === null && config.plugins) {
const pluginDir = config.plugins;
const externalFilePlugin = Path.resolve(pluginDir, pluginId);
plugin = tryLoad(externalFilePlugin);
// npm package
if (plugin === null && pluginId.match(/^[^\.\/]/)) {
plugin = tryLoad(Path.resolve(pluginDir, `${prefix}-${pluginId}`));
// compatibility for old sinopia plugins
if (!plugin) {
plugin = tryLoad(Path.resolve(pluginDir, `sinopia-${pluginId}`));
}
}
}
// try the external plugin directory
if (plugin === null && config.plugins) {
const pluginDir = config.plugins;
const externalFilePlugin = Path.resolve(pluginDir, pluginId);
plugin = tryLoad(externalFilePlugin);
// npm package
if (plugin === null && pluginId.match(/^[^\.\/]/)) {
plugin = tryLoad(`${prefix}-${pluginId}`);
plugin = tryLoad(Path.resolve(pluginDir, `${prefix}-${pluginId}`));
// compatibility for old sinopia plugins
if (!plugin) {
plugin = tryLoad(`sinopia-${pluginId}`);
plugin = tryLoad(Path.resolve(pluginDir, `sinopia-${pluginId}`));
}
}
if (plugin === null) {
plugin = tryLoad(pluginId);
}
// relative to config path
if (plugin === null && pluginId.match(/^\.\.?($|\/)/)) {
plugin = tryLoad(Path.resolve(Path.dirname(config.self_path), pluginId));
}
if (plugin === null) {
logger.error(
{ content: pluginId, prefix },
'plugin not found. try npm install @{prefix}-@{content}'
);
throw Error(`
${prefix}-${pluginId} plugin not found. try "npm install ${prefix}-${pluginId}"`);
}
if (!isValid(plugin)) {
logger.error(
{ content: pluginId },
'@{prefix}-@{content} plugin does not have the right code structure'
);
throw Error(`"${pluginId}" plugin does not have the right code structure`);
}
/* eslint new-cap:off */
try {
plugin = isES6(plugin)
? new plugin.default(mergeConfig(config, pluginConfigs[pluginId]), params)
: plugin(pluginConfigs[pluginId], params);
} catch (error) {
plugin = null;
logger.error({ error, pluginId }, 'error loading a plugin @{pluginId}: @{error}');
}
/* eslint new-cap:off */
if (plugin === null || !sanityCheck(plugin)) {
logger.error(
{ content: pluginId, prefix },
"@{prefix}-@{content} doesn't look like a valid plugin"
);
throw Error(`sanity check has failed, "${pluginId}" is not a valid plugin`);
}
logger.warn(
{ content: pluginId, prefix },
'Plugin successfully loaded: @{prefix}-@{content}'
);
return plugin;
}
);
// npm package
if (plugin === null && pluginId.match(/^[^\.\/]/)) {
plugin = tryLoad(`${prefix}-${pluginId}`);
// compatibility for old sinopia plugins
if (!plugin) {
plugin = tryLoad(`sinopia-${pluginId}`);
}
}
if (plugin === null) {
plugin = tryLoad(pluginId);
}
// relative to config path
if (plugin === null && pluginId.match(/^\.\.?($|\/)/)) {
plugin = tryLoad(Path.resolve(Path.dirname(config.self_path), pluginId));
}
if (plugin === null) {
logger.error({ content: pluginId, prefix }, 'plugin not found. try npm install @{prefix}-@{content}');
throw Error(`
${prefix}-${pluginId} plugin not found. try "npm install ${prefix}-${pluginId}"`);
}
if (!isValid(plugin)) {
logger.error({ content: pluginId }, '@{prefix}-@{content} plugin does not have the right code structure');
throw Error(`"${pluginId}" plugin does not have the right code structure`);
}
/* eslint new-cap:off */
try {
plugin = isES6(plugin) ? new plugin.default(mergeConfig(config, pluginConfigs[pluginId]), params) : plugin(pluginConfigs[pluginId], params);
} catch (error) {
plugin = null;
logger.error({ error, pluginId }, 'error loading a plugin @{pluginId}: @{error}');
}
/* eslint new-cap:off */
if (plugin === null || !sanityCheck(plugin)) {
logger.error({ content: pluginId, prefix }, "@{prefix}-@{content} doesn't look like a valid plugin");
throw Error(`sanity check has failed, "${pluginId}" is not a valid plugin`);
}
logger.warn({ content: pluginId, prefix }, 'Plugin successfully loaded: @{prefix}-@{content}');
return plugin;
});
}

@ -1,8 +1,10 @@
// eslint-disable no-invalid-this
import { IStorageHandler, IWebSearch, IStorage } from '../../types';
import lunrMutable from 'lunr-mutable-indexes';
import { Version } from '@verdaccio/types';
import { IStorage, IStorageHandler, IWebSearch } from '../../types';
/**
* Handle the search Indexer.
*/
@ -49,17 +51,16 @@ class Search implements IWebSearch {
query = query.replace('@', '');
}
const results = query === '*'
? localStorage.storagePlugin.get((items): any => {
items.map(function (pkg): any {
return { ref: pkg, score: 1 };
});
})
: this.index.search(`*${query}*`);
const results =
query === '*'
? localStorage.storagePlugin.get((items): any => {
items.map(function (pkg): any {
return { ref: pkg, score: 1 };
});
})
: this.index.search(`*${query}*`);
return hasScope
? results.filter(({ ref }) => ref.startsWith('@'))
: results;
return hasScope ? results.filter(({ ref }) => ref.startsWith('@')) : results;
}
/**
@ -73,7 +74,7 @@ class Search implements IWebSearch {
description: pkg.description,
version: `v${pkg.version}`,
keywords: pkg.keywords,
author: pkg._npmUser ? pkg._npmUser.name : '???'
author: pkg._npmUser ? pkg._npmUser.name : '???',
});
}

@ -1,12 +1,13 @@
import { generateRandomHexString } from '../lib/crypto-utils';
import { IStorage } from '../../types';
import { ErrorCode, isObject, normalizeDistTags, semverSort } from './utils';
import Search from './search';
import { API_ERROR, HTTP_STATUS, DIST_TAGS, USERS, STORAGE } from './constants';
import { Package, Version, Author } from '@verdaccio/types';
import _ from 'lodash';
import { Author, Package, Version } from '@verdaccio/types';
import { IStorage } from '../../types';
import { generateRandomHexString } from '../lib/crypto-utils';
import { API_ERROR, DIST_TAGS, HTTP_STATUS, STORAGE, USERS } from './constants';
import Search from './search';
import { ErrorCode, isObject, normalizeDistTags, semverSort } from './utils';
export function generatePackageTemplate(name: string): Package {
return {
// standard things
@ -18,7 +19,7 @@ export function generatePackageTemplate(name: string): Package {
_uplinks: {},
_distfiles: {},
_attachments: {},
_rev: ''
_rev: '',
};
}
@ -98,24 +99,15 @@ export function normalizeContributors(contributors: Author[]): Author[] {
} else if (_.isString(contributors)) {
return [
{
name: contributors
}
name: contributors,
},
];
}
return contributors;
}
export const WHITELIST = [
'_rev',
'name',
'versions',
'dist-tags',
'readme',
'time',
'_id',
'users'
];
export const WHITELIST = ['_rev', 'name', 'versions', 'dist-tags', 'readme', 'time', '_id', 'users'];
export function cleanUpLinksRef(keepUpLinkData: boolean, result: Package): Package {
const propertyToKeep = [...WHITELIST];
@ -165,11 +157,7 @@ export function publishPackage(name: string, metadata: any, localStorage: IStora
});
}
export function checkPackageRemote(
name: string,
isAllowPublishOffline: boolean,
syncMetadata: Function
): Promise<void> {
export function checkPackageRemote(name: string, isAllowPublishOffline: boolean, syncMetadata: Function): Promise<void> {
return new Promise((resolve, reject): void => {
syncMetadata(name, null, {}, (err, packageJsonLocal, upLinksErrors): void => {
// something weird
@ -212,8 +200,7 @@ export function mergeUplinkTimeIntoLocal(localMetadata: Package, remoteMetadata:
export function prepareSearchPackage(data: Package, time: unknown): any {
const listVersions: string[] = Object.keys(data.versions);
const versions: string[] = semverSort(listVersions);
const latest: string | undefined =
data[DIST_TAGS] && data[DIST_TAGS].latest ? data[DIST_TAGS].latest : versions.pop();
const latest: string | undefined = data[DIST_TAGS] && data[DIST_TAGS].latest ? data[DIST_TAGS].latest : versions.pop();
if (latest && data.versions[latest]) {
const version: Version = data.versions[latest];
@ -231,9 +218,9 @@ export function prepareSearchPackage(data: Package, time: unknown): any {
bugs: version.bugs,
license: version.license,
time: {
modified: time
modified: time,
},
versions
versions,
};
return pkg;

@ -1,22 +1,24 @@
import assert from 'assert';
import Stream from 'stream';
import { IStorage, IProxy, IStorageHandler, ProxyList, StringValue, IGetPackageOptions, ISyncUplinks, IPluginFilters } from '../../types';
import { logger } from '../lib/logger';
import ProxyStorage from './up-storage';
import Search from './search';
import { API_ERROR, HTTP_STATUS, DIST_TAGS } from './constants';
import LocalStorage from './local-storage';
import { checkPackageLocal, publishPackage, checkPackageRemote, cleanUpLinksRef, mergeUplinkTimeIntoLocal, generatePackageTemplate } from './storage-utils';
import { setupUpLinks, updateVersionsHiddenUpLink } from './uplink-util';
import { mergeVersions } from './metadata-utils';
import { ErrorCode, normalizeDistTags, validateMetadata, isObject } from './utils';
import { hasProxyTo } from './config-utils';
import { VerdaccioError } from '@verdaccio/commons-api';
import { GenericBody, TokenFilter, Token } from '@verdaccio/types';
import { IReadTarball, IUploadTarball, Versions, Package, Config, MergeTags, Version, DistFile, Callback, Logger } from '@verdaccio/types';
import { ReadTarball } from '@verdaccio/streams';
import async, { AsyncResultArrayCallback } from 'async';
import _ from 'lodash';
import Stream from 'stream';
import { VerdaccioError } from '@verdaccio/commons-api';
import { ReadTarball } from '@verdaccio/streams';
import { GenericBody, Token, TokenFilter } from '@verdaccio/types';
import { Callback, Config, DistFile, IReadTarball, IUploadTarball, Logger, MergeTags, Package, Version, Versions } from '@verdaccio/types';
import { IGetPackageOptions, IPluginFilters, IProxy, IStorage, IStorageHandler, ISyncUplinks, ProxyList, StringValue } from '../../types';
import { logger } from '../lib/logger';
import { hasProxyTo } from './config-utils';
import { API_ERROR, DIST_TAGS, HTTP_STATUS } from './constants';
import LocalStorage from './local-storage';
import { mergeVersions } from './metadata-utils';
import Search from './search';
import { checkPackageLocal, checkPackageRemote, cleanUpLinksRef, generatePackageTemplate, mergeUplinkTimeIntoLocal, publishPackage } from './storage-utils';
import ProxyStorage from './up-storage';
import { setupUpLinks, updateVersionsHiddenUpLink } from './uplink-util';
import { ErrorCode, isObject, normalizeDistTags, validateMetadata } from './utils';
class Storage implements IStorageHandler {
public localStorage: IStorage;

@ -1,16 +1,18 @@
import zlib from 'zlib';
import Stream from 'stream';
import URL, { UrlWithStringQuery } from 'url';
import { IProxy, UpLinkConfLocal } from '../../types';
import { parseInterval, isObject, ErrorCode, buildToken, isObjectOrArray } from './utils';
import { logger } from './logger';
import { ERROR_CODE, TOKEN_BASIC, TOKEN_BEARER, HEADERS, HTTP_STATUS, API_ERROR, HEADER_TYPE, CHARACTER_ENCODING } from './constants';
import JSONStream from 'JSONStream';
import buildDebug from 'debug';
import _ from 'lodash';
import request from 'request';
import Stream from 'stream';
import URL, { UrlWithStringQuery } from 'url';
import zlib from 'zlib';
import { ReadTarball } from '@verdaccio/streams';
import { Config, Callback, Headers, Logger, Package } from '@verdaccio/types';
import { Callback, Config, Headers, Logger, Package } from '@verdaccio/types';
import { IProxy, UpLinkConfLocal } from '../../types';
import { API_ERROR, CHARACTER_ENCODING, ERROR_CODE, HEADERS, HEADER_TYPE, HTTP_STATUS, TOKEN_BASIC, TOKEN_BEARER } from './constants';
import { logger } from './logger';
import { ErrorCode, buildToken, isObject, isObjectOrArray, parseInterval } from './utils';
const debug = buildDebug('verdaccio:up-storage');

@ -1,6 +1,7 @@
import { Config, Versions } from '@verdaccio/types';
import { IProxy, ProxyList } from '../../types';
import ProxyStorage from './up-storage';
import { Versions, Config } from '@verdaccio/types';
/**
* Set up the Up Storage for each link.

@ -1,25 +1,24 @@
import fs from 'fs';
import assert from 'assert';
import DefaultURL, { URL } from 'url';
import { generateGravatarUrl, GENERIC_AVATAR } from '../utils/user';
import { StringValue, AuthorAvatar } from '../../types';
import { APP_ERROR, DEFAULT_PORT, DEFAULT_DOMAIN, DEFAULT_PROTOCOL, HEADERS, DIST_TAGS, DEFAULT_USER } from './constants';
import { normalizeContributors } from './storage-utils';
import { logger } from './logger';
import _ from 'lodash';
import buildDebug from 'debug';
import semver from 'semver';
import YAML from 'js-yaml';
import validator from 'validator';
import memoizee from 'memoizee';
import sanitizyReadme from '@verdaccio/readme';
import { Package, Version, Author } from '@verdaccio/types';
import { Request } from 'express';
import fs from 'fs';
import YAML from 'js-yaml';
import _ from 'lodash';
import memoizee from 'memoizee';
import semver from 'semver';
import DefaultURL, { URL } from 'url';
import validator from 'validator';
// eslint-disable-next-line max-len
import { getConflict, getBadData, getBadRequest, getInternalError, getUnauthorized, getForbidden, getServiceUnavailable, getNotFound, getCode } from '@verdaccio/commons-api';
import { getBadData, getBadRequest, getCode, getConflict, getForbidden, getInternalError, getNotFound, getServiceUnavailable, getUnauthorized } from '@verdaccio/commons-api';
import sanitizyReadme from '@verdaccio/readme';
import { Author, Package, Version } from '@verdaccio/types';
import { AuthorAvatar, StringValue } from '../../types';
import { GENERIC_AVATAR, generateGravatarUrl } from '../utils/user';
import { APP_ERROR, DEFAULT_DOMAIN, DEFAULT_PORT, DEFAULT_PROTOCOL, DEFAULT_USER, DIST_TAGS, HEADERS } from './constants';
import { logger } from './logger';
import { normalizeContributors } from './storage-utils';
const debug = buildDebug('verdaccio');

@ -1,7 +1,8 @@
// @flow
import { stringToMD5 } from '../lib/crypto-utils';
import _ from 'lodash';
import { stringToMD5 } from '../lib/crypto-utils';
// this is a generic avatar
// https://www.iconfinder.com/icons/403017/anonym_avatar_default_head_person_unknown_user_icon
// license: free commercial usage

@ -8,15 +8,15 @@ First of all, we should explain the testing frameworks being used. We use `jest`
We go along with the following rules in order to be consistent with all tests which will make your code review smooth and fast:
* We **type** all our tests. eg `const foo: number = 3;`
* **Each test should be as small as possible**: You should use the `test()` block to test only one thing and do not depend on other tests. If the test requires different steps, group them with a `describe()` block.
* All `test()` **headers titles** should begin with `test('should test ...')`: For consistency with reporting tools, this makes it easier to match the test with the feature needed to be tested.
* **Any mock data** should be located in the `partials` folder in each section.
* Use `yaml` for **configuration files examples** instead of JSON.
* If you use a **file based mock storage**, it should be located in the `store` folder in each section.
* All tests **MUST NOT** rely on external sources and must be able to run them **offline**.
* Tests **must run on the following Operating Systems**: Unix (Mac, Linux) and Windows (7 -> latest).
* If you are creating mock data file which use the state and need a clean state, use `rimraf` to remove folders.
- We **type** all our tests. eg `const foo: number = 3;`
- **Each test should be as small as possible**: You should use the `test()` block to test only one thing and do not depend on other tests. If the test requires different steps, group them with a `describe()` block.
- All `test()` **headers titles** should begin with `test('should test ...')`: For consistency with reporting tools, this makes it easier to match the test with the feature needed to be tested.
- **Any mock data** should be located in the `partials` folder in each section.
- Use `yaml` for **configuration files examples** instead of JSON.
- If you use a **file based mock storage**, it should be located in the `store` folder in each section.
- All tests **MUST NOT** rely on external sources and must be able to run them **offline**.
- Tests **must run on the following Operating Systems**: Unix (Mac, Linux) and Windows (7 -> latest).
- If you are creating mock data file which use the state and need a clean state, use `rimraf` to remove folders.
## Testing sections
@ -24,11 +24,11 @@ Verdaccio testing is split in 3 sections, each of them has different setup and s
If you are adding new tests, comply with the following:
* If you add a new API endpoint, unit and functional tests are mandatory.
* If you add a utility, unit test is mandatory.
* If you are adding a new web API endpoint, the unit test, functional test and if such endpoint has new changes in the UI, E2E test is also mandatory.
* If you add or refactor a core class, unit test is mandatory.
* If you fix a bug, you **must** add a new `test()` block to prove that the patch fixes the bug.
- If you add a new API endpoint, unit and functional tests are mandatory.
- If you add a utility, unit test is mandatory.
- If you are adding a new web API endpoint, the unit test, functional test and if such endpoint has new changes in the UI, E2E test is also mandatory.
- If you add or refactor a core class, unit test is mandatory.
- If you fix a bug, you **must** add a new `test()` block to prove that the patch fixes the bug.
## Unit test
@ -40,14 +40,14 @@ Unit tests aim to test the CLI API and the Web API. The configuration file is lo
We have prepared a template at `test/unit/api/api.__test.template.spec.ts` that you can follow to create your own unit test. Only the tests are appended with `.spec.ts` which will be found and used by `jest`.
> Feel free to suggest improvements to the template, there is still a lot of room for improvement.
> Feel free to suggest improvements to the template, there is still a lot of room for improvement.
We recommend the following approach when you create a unit test:
* For new utilities, we recommend creating a new spec.
* For existing utilities, if the method is already being tested, just add a new `test()` block.
* Notice that all API spec files are appended with `api.[feature].spec.js`, we recommend to follow the same approach. eg: `api.[deprecate].spec.js`.
* Don't mix utilities with API tests.
- For new utilities, we recommend creating a new spec.
- For existing utilities, if the method is already being tested, just add a new `test()` block.
- Notice that all API spec files are appended with `api.[feature].spec.js`, we recommend to follow the same approach. eg: `api.[deprecate].spec.js`.
- Don't mix utilities with API tests.
### How the mockServer works?
@ -86,29 +86,29 @@ const configForTest = configDefault({
The `configDefault({}, 'myConfig.yaml)` function is a method that returns a configuration file that will be the config used for your test.
* The *first argument* allows you to override/extend the default configuration located `/test/unit/partials/config/yaml/default.yaml`.
* The *second argument*s is being used to override the base configuration file, you only need to set the name `api.spec.yaml` you are willing to use, the relative location will be `test/unit/partials/config/yaml/` and will be prefixed on runtime.
- The _first argument_ allows you to override/extend the default configuration located `/test/unit/partials/config/yaml/default.yaml`.
- The *second argument*s is being used to override the base configuration file, you only need to set the name `api.spec.yaml` you are willing to use, the relative location will be `test/unit/partials/config/yaml/` and will be prefixed on runtime.
> **The generated object will be used for run your test, not for mock the mock server.**
The `app = await endPointAPI(configForTest);` is the server that you are about to run your test against. The `app` object is used to call the endoints, for instance:
```js
```js
test('should fetch jquery package from remote uplink', (done) => {
request(app)
.get('/jquery')
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK)
.end(function(err, res) {
if (err) {
return done(err);
}
request(app)
.get('/jquery')
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK)
.end(function (err, res) {
if (err) {
return done(err);
}
expect(res.body).toBeDefined();
expect(res.body.name).toMatch(/jquery/);
done();
});
expect(res.body).toBeDefined();
expect(res.body.name).toMatch(/jquery/);
done();
});
});
```
@ -118,7 +118,7 @@ In the previous example, we are fetching `jquery` metadata from our server, we c
The `mockRegistry = await mockServer(mockServerPort).init();` mock registry will be used as `uplink` for the `app` object described above, **this is optional**, but, the most of the tests are using this approach for increase the number of tested scenarios.
The *mock server* has a static storage which is located `test/unit/partials/mock-store`, if you need add new packages, those must be commited in such folder. **Any modification in the mock server might affect other test, since is a shared context**.
The _mock server_ has a static storage which is located `test/unit/partials/mock-store`, if you need add new packages, those must be commited in such folder. **Any modification in the mock server might affect other test, since is a shared context**.
> It is not possible yet to override the mocks configuration server.
@ -127,7 +127,6 @@ The *mock server* has a static storage which is located `test/unit/partials/mock
> The `const mockServerPort = 55549;` mock server must be added manually, be careful and try to define a port that is not being used by another test, there is not automation here yet.
> To increase debugging you might override the `logs` property using `{ type: 'stdout', format: 'pretty', level: 'trace' }` level **trace**, thus the test will display the server request in your terminal, try to keep it in **warn** by default to avoid noise on run all your test.
>
#### Running a single Unit Test
@ -137,7 +136,7 @@ To run a single test, use the following command:
yarn jest test/unit/modules/api/api.spec.ts --coverage=false
```
You might use the *jest* feature `.only` to limit the test suites you want to run, for instance.
You might use the _jest_ feature `.only` to limit the test suites you want to run, for instance.
```js
describe.only('should test package api', () => {
@ -199,62 +198,58 @@ Ran all test suites matching /test\/unit\/modules\/api\/api.spec.ts/i.
debug-=- updating package jquery info
http <-- 200, user: null(::ffff:127.0.0.1), req: 'GET /jquery', bytes: 0/10300
```
The debug display request headers and other handy information about what is happening between your test and the mock server.
## Functional tests
The functional tests aim to run only **cli endpoint** and **web point** using real request to an existing and compiled running Verdaccio server.
> Be aware if you change something in the `{root}/src` source code, you must run `yarn code:build` before to be able to see your changes because functional tests use the transpiled code.
> Be aware if you change something in the `{root}/src` source code, you must run `yarn code:build` before to be able to see your changes because functional tests use the transpiled code.
All tests must be included in the `test/functional/index.spec.ts` file, which bootstraps the whole process. There is only one spec file and **must be only one**.
The jest configuration file is defined in `test/jest.config.functional.js`. The configuration will create a custom environment launching 3 Verdaccio servers with different configurations.
The servers are linked as follows:
The servers are linked as follows:
* Server 1
* -> Server 2
* -> Server 3
* Server 2
* -> Server 1
* Server 3
* -> Server 2
* -> Server 1
* Express app: (if you need to emulate any external endpoint, use the express app)
- Server 1
- -> Server 2
- -> Server 3
- Server 2
- -> Server 1
- Server 3
- -> Server 2
- -> Server 1
- Express app: (if you need to emulate any external endpoint, use the express app)
Server 1 runs on port `55551`, Server 2 on port `55552` and Server 3 on port `55553`.
> If you have the need to increase the number of servers running, it is possible, but please discuss with the team before you go in that path.
#### Adding a new block
To add a new feature you need to export the feature as a function that take as an argument any of the servers you want to interact.
To add a new feature you need to export the feature as a function that take as an argument any of the servers you want to interact.
```js
// newFeature.ts
export default function(server) {
export default function (server) {
describe('package access control', () => {
test('should ...', (done) => {
done();
});
});
}
```
Then import the feature and run the function within the main `describe` block.
Then import the feature and run the function within the main `describe` block.
```js
// index.spec.ts
import newFeature from './newFeature';
describe('functional test verdaccio', function() {
describe('functional test verdaccio', function () {
// test are fast, but do not change this time out, 10 seconds should be more than enough
jest.setTimeout(10000);
// servers are accessed via a global jest state.
@ -272,39 +267,33 @@ Functional tests run over one single file, thus, it is not possible at this stag
## E2E Test
Verdaccio includes a Web User Interface that must be tested. We use End-to-End testing to run some mock tests against the web API using the UI Theme
Verdaccio includes a Web User Interface that must be tested. We use End-to-End testing to run some mock tests against the web API using the UI Theme
include by default.
```bash
yarn lint && yarn test:all
```
The test does not have aim to test the integrity of the page, mostly, ensure the basic functionality still works. If you add or modify
The test does not have aim to test the integrity of the page, mostly, ensure the basic functionality still works. If you add or modify
a UI feature, the tests must be updated.
> The tests rely on CSS classes naming convention, so, it is required some sort of coordination with the **verdaccio/ui** project.
We uses `puppeteer`, you can find more information about how to use it in their website.
We uses `puppeteer`, you can find more information about how to use it in their website.
## Before commit
We recommend run your tests and linters before commit.
We recommend run your tests and linters before commit.
```bash
yarn lint && yarn test:all
```
You can find more in our [guide about run and debugging test](https://github.com/verdaccio/verdaccio/wiki/Running-and-Debugging-tests#running-the-test).
## Continuous Integration
Verdaccio uses [CircleCI](https://circleci.com/gh/verdaccio) as its primary Continuous Integration tool. We run the tests against the most common Node.js versions available. Among them is LTS and the latest release. Before the PR is being merged, all checks must be green.
Node.js versions available, LTS and the latest release. Before the PR is being merged, all check must be green.
> You need a CircleCI account to be able see the test running
Node.js versions available, LTS and the latest release. Before the PR is being merged, all check must be green.
> You need a CircleCI account to be able see the test running

@ -1,4 +1,4 @@
require('@babel/register')({
extensions: [".ts", ".js"]
extensions: ['.ts', '.js'],
});
module.exports = require('./setup/test_environment');

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