From e61bd6c78fdf36790e92cd8f9c80ec33b886e507 Mon Sep 17 00:00:00 2001 From: Juan Picado Date: Thu, 13 Aug 2020 23:27:00 +0200 Subject: [PATCH] chore: lint prettier update (#1904) * chore: update prettier@2.x * chore: prettier auto fix * chore: fake circleci we don't need it but I want make dissapear the error --- .circleci/config.yml | 8 + .eslintrc | 46 ++- package.json | 2 +- packages/api/src/dist-tags.ts | 22 +- packages/api/src/index.ts | 8 +- packages/api/src/package.ts | 14 +- packages/api/src/ping.ts | 9 +- packages/api/src/publish.ts | 78 ++-- packages/api/src/search.ts | 14 +- packages/api/src/star.ts | 38 +- packages/api/src/stars.ts | 6 +- packages/api/src/user.ts | 10 +- packages/api/src/utils.ts | 6 +- packages/api/src/v1/profile.ts | 6 +- packages/api/src/v1/search.ts | 167 ++++---- packages/api/src/v1/token.ts | 194 ++++----- packages/api/test/integration/_helper.ts | 94 ++--- packages/api/test/integration/package.spec.ts | 135 +++--- packages/api/test/integration/ping.spec.ts | 20 +- packages/api/test/integration/publish.spec.ts | 279 +++++++------ packages/api/test/integration/user.spec.ts | 389 +++++++++--------- packages/api/test/integration/whoami.spec.ts | 79 ++-- packages/api/test/unit/publish.spec.ts | 18 +- packages/auth/src/auth.ts | 171 +++----- packages/auth/src/index.ts | 2 +- packages/auth/src/utils.ts | 159 ++++--- packages/auth/test/auth-utils.spec.ts | 64 ++- packages/auth/test/auth.spec.ts | 26 +- packages/auth/test/helper/plugin.ts | 14 +- packages/cli/src/cli.ts | 26 +- packages/cli/src/commands/info.ts | 28 +- packages/cli/src/commands/init.ts | 64 +-- packages/cli/src/utils.ts | 4 +- packages/cli/test/cli-test.spec.ts | 2 +- packages/commons/src/helpers/pkg.ts | 105 +++-- packages/config/src/config-path.ts | 21 +- packages/config/src/config.ts | 14 +- packages/config/src/index.ts | 4 +- packages/config/test/config.spec.ts | 16 +- packages/hooks/src/index.ts | 2 +- packages/hooks/src/notify-request.ts | 32 +- packages/hooks/src/notify.ts | 36 +- packages/hooks/test/notify.spec.ts | 38 +- packages/loaders/src/plugin-loader.ts | 22 +- packages/loaders/test/plugin_loader.spec.ts | 15 +- packages/logger-prettify/src/formatter.ts | 20 +- packages/logger-prettify/src/index.ts | 18 +- packages/logger-prettify/src/levels.ts | 78 ++-- packages/logger-prettify/src/types.ts | 6 +- packages/logger-prettify/src/utils.ts | 8 +- .../logger-prettify/test/formatter.spec.ts | 378 ++++++++--------- packages/logger-prettify/test/index.spec.ts | 24 +- packages/logger/src/index.ts | 1 - packages/logger/src/logger.ts | 158 +++---- packages/logger/test/logger.spec.ts | 21 +- packages/middleware/src/middleware.ts | 29 +- packages/mock/src/config.ts | 11 +- packages/mock/src/constants.ts | 4 +- packages/mock/src/mock-api.ts | 117 +++--- packages/mock/src/mock.ts | 13 +- packages/mock/src/request.ts | 101 ++--- packages/mock/src/server.ts | 41 +- packages/mock/src/server_process.ts | 45 +- packages/mock/src/utils-test.ts | 51 ++- packages/mock/src/verdaccio-server.ts | 3 +- packages/mock/test/request.spec.ts | 60 +-- packages/node-api/src/bootstrap.ts | 39 +- packages/node-api/src/cli-utils.ts | 4 +- packages/node-api/src/experiments.ts | 14 +- packages/node-api/src/https.ts | 54 +-- packages/node-api/test/node-api.spec.ts | 78 ++-- packages/node-api/test/node-api.utils.spec.ts | 116 +++--- packages/proxy/src/up-storage.ts | 134 +++--- packages/proxy/test/headers.auth.spec.ts | 83 ++-- packages/proxy/test/noProxy.spec.ts | 48 +-- packages/server/src/debug/index.ts | 31 +- packages/server/src/server.ts | 16 +- .../server/test/api/helpers/publish-api.js | 85 ++-- packages/server/test/api/helpers/utils.ts | 208 +++++----- packages/server/test/api/index.spec.ts | 336 ++++++++------- packages/server/test/basic/index.spec.ts | 54 +-- packages/server/test/jwt/index.spec.ts | 39 +- .../server/test/package-access/index.spec.ts | 38 +- packages/server/test/profile/index.spec.ts | 38 +- packages/server/test/proxy/index.spec.ts | 49 +-- packages/server/test/storage/index.spec.ts | 128 +++--- packages/server/test/token/index.spec.ts | 62 +-- packages/server/test/web/index.spec.ts | 74 ++-- packages/store/src/local-storage.ts | 69 ++-- packages/store/src/search.ts | 4 +- packages/store/src/storage-utils.ts | 122 +++--- packages/store/src/storage.ts | 357 +++++++--------- packages/store/test/local-storage.spec.ts | 97 +++-- packages/store/test/merge.dist.tags.spec.ts | 38 +- packages/store/test/search.spec.ts | 4 +- packages/store/test/storage-utils.spec.ts | 39 +- packages/utils/src/auth-utils.ts | 21 +- packages/utils/src/config-utils.ts | 42 +- packages/utils/src/crypto-utils.ts | 6 +- packages/utils/src/utils.ts | 29 +- packages/utils/test/auth-utils.spec.ts | 290 ++++++------- packages/utils/test/config-utils.spec.ts | 72 ++-- packages/utils/test/crypto-utils.spec.ts | 18 +- packages/utils/test/parseAddress.spec.ts | 4 +- packages/utils/test/tag.version.spec.ts | 13 +- packages/utils/test/utils.spec.ts | 191 ++++----- .../test/functional/adduser/adduser.js | 16 +- .../test/functional/adduser/logout.js | 8 +- .../verdaccio/test/functional/basic/basic.ts | 85 ++-- .../test/functional/config.functional.js | 4 +- .../verdaccio/test/functional/index.spec.ts | 11 +- .../test/functional/lib/environment.ts | 21 +- .../test/functional/lib/simple_server.ts | 2 +- .../test/functional/notifications/notify.ts | 229 ++++++----- .../test/functional/package/access.ts | 31 +- .../verdaccio/test/functional/package/gzip.ts | 57 +-- .../test/functional/package/scoped.ts | 68 +-- .../test/functional/performance/race.ts | 41 +- .../verdaccio/test/functional/plugins/auth.ts | 64 +-- .../test/functional/plugins/middleware.ts | 26 +- .../verdaccio/test/functional/pre-setup.js | 2 +- .../test/functional/readme/readme.ts | 27 +- .../test/functional/sanity/incomplete.ts | 40 +- .../test/functional/sanity/mirror.ts | 32 +- .../test/functional/sanity/nullstorage.ts | 52 +-- .../test/functional/sanity/racycrash.ts | 50 ++- .../test/functional/sanity/security.ts | 42 +- .../test/functional/scenarios/gh29.ts | 35 +- .../test/functional/search/simple.search.ts | 67 ++- .../verdaccio/test/functional/tags/addtag.ts | 42 +- .../test/functional/tags/dist-tags-merge.ts | 31 +- .../verdaccio/test/functional/tags/tags.ts | 227 +++++----- .../verdaccio/test/functional/teardown.js | 2 +- .../test/functional/test-environment.js | 2 +- .../test/functional/uplinks/cache.ts | 30 +- .../test/functional/uplinks/timeout.ts | 8 +- .../verdaccio/test/jest.config.functional.js | 2 +- .../verdaccio/test/lib/helper/verdaccio-test | 2 +- .../middleware/example.middleware.plugin.ts | 23 +- .../plugins/storage/example.storage.plugin.ts | 57 ++- .../unit/__helper/__template/api.__test.ts | 26 +- packages/verdaccio/test/unit/__helper/api.ts | 118 +++--- .../verdaccio/test/unit/__helper/expects.ts | 23 +- .../verdaccio/test/unit/__helper/utils.ts | 114 ++--- packages/web/src/endpoint/package.ts | 76 ++-- packages/web/src/endpoint/search.ts | 11 +- packages/web/src/endpoint/user.ts | 4 +- packages/web/src/render-web.ts | 12 +- packages/web/src/user.ts | 37 +- packages/web/src/web-utils.ts | 86 ++-- packages/web/test/utils.spec.ts | 102 +++-- pnpm-lock.yaml | 16 +- website/.prettierrc.json | 12 - 153 files changed, 4313 insertions(+), 4598 deletions(-) create mode 100644 .circleci/config.yml delete mode 100644 website/.prettierrc.json diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000..451258d64 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,8 @@ +version: 2.1 +jobs: + build: + docker: + - image: circleci/node:12 # the primary container, where your job's commands are run + steps: + - checkout # check out the code in the project directory + - run: echo "hello world" # run the `echo` command diff --git a/.eslintrc b/.eslintrc index e5c7501c7..cf4e9c60b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,21 +2,23 @@ "extends": [ "eslint:recommended", "google", + "plugin:prettier/recommended", "plugin:react/recommended", "plugin:jest/recommended", "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", "plugin:import/typescript", - "plugin:prettier/recommended", "plugin:jsx-a11y/recommended", + "prettier", + "prettier/react", "prettier/@typescript-eslint" ], "plugins": [ "import", "jest", - "prettier", "jsx-a11y", - "react-hooks" + "react-hooks", + "prettier" ], "env": { "es6": true, @@ -30,7 +32,7 @@ "parserOptions": { "allowImportExportEverywhere": true, "sourceType": "module", - "ecmaVersion": 2019, + "ecmaVersion": 11, "ecmaFeatures": { "impliedStrict": true, "jsx": true @@ -52,18 +54,25 @@ "error", "all" ], "prettier/prettier": [ - "error", + 2, { - "endOfLine": "auto", - "printWidth": 120, - "tabWidth": 2, "useTabs": false, - "semi": true, - "trailingComma": "es5", + "printWidth": 160, + "tabWidth": 2, "singleQuote": true, - "bracketSpacing": true + "bracketSpacing": true, + "jsxBracketSameLine": true, + "trailingComma": "es5", + "semi": true, + "parser": "typescript" } ], + "react/prop-types": 0, + "jest/no-export": 0, + "jest/no-test-callback": 0, + "jest/expect-expect": 0, + "jest/no-try-expect": 0, + "jest/no-identical-title": 1, "keyword-spacing": "off", "no-tabs": "off", "no-useless-escape": "off", @@ -71,16 +80,10 @@ "require-jsdoc": "off", "valid-jsdoc": "off", "import/order": ["warn"], - "react/prop-types": 0, - "jest/no-export": 0, - "jest/no-test-callback": 0, - "jest/no-try-expect": 1, - "jest/no-identical-title": 1, "eol-last": "warn", "no-irregular-whitespace": "warn", "no-mixed-spaces-and-tabs": ["warn", "smart-tabs"], "no-trailing-spaces": "warn", - "camelcase": "off", "guard-for-in": "error", "new-cap": "error", @@ -99,7 +102,9 @@ "one-var": "error", "prefer-rest-params": "warn", "prefer-spread": "warn", - "semi": 0, + "handle-callback-err": 0, + "prefer-const": 0, + "prefer-promise-reject-errors": 1, "@typescript-eslint/camelcase": 0, "@typescript-eslint/ban-ts-ignore": 0, "@typescript-eslint/no-var-requires": 0, @@ -115,9 +120,6 @@ "@typescript-eslint/ban-types": 0, "@typescript-eslint/explicit-module-boundary-types": 0, "@typescript-eslint/explicit-member-accessibility": ["warn"], - "@typescript-eslint/prefer-optional-chain": ["warn"], - "handle-callback-err": 0, - "prefer-const": 0, - "prefer-promise-reject-errors": 1 + "@typescript-eslint/prefer-optional-chain": ["warn"] } } diff --git a/package.json b/package.json index fe2ff3e26..3cb2b60f7 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "kleur": "3.0.3", "lint-staged": "8.2.1", "nock": "12.0.3", - "prettier": "1.19.1", + "prettier": "2.0.5", "rimraf": "3.0.2", "selfsigned": "1.10.7", "standard-version": "8.0.0", diff --git a/packages/api/src/dist-tags.ts b/packages/api/src/dist-tags.ts index 160845c5a..3bffdd98a 100644 --- a/packages/api/src/dist-tags.ts +++ b/packages/api/src/dist-tags.ts @@ -1,6 +1,6 @@ import mime from 'mime'; import _ from 'lodash'; -import{ Router } from 'express'; +import { Router } from 'express'; import { media, allow } from '@verdaccio/middleware'; import { API_MESSAGE, HTTP_STATUS, DIST_TAGS } from '@verdaccio/dev-commons'; @@ -8,18 +8,18 @@ import { VerdaccioError } from '@verdaccio/commons-api'; import { Package } from '@verdaccio/types'; // @ts-ignore -import{ IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler } from '@verdaccio/dev-types'; +import { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler } from '@verdaccio/dev-types'; -export default function(route: Router, auth: IAuth, storage: IStorageHandler): void { +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'); } const tags = {}; tags[req.params.tag] = req.body; - storage.mergeTags(req.params.package, tags, function(err: Error): $NextFunctionVer { + storage.mergeTags(req.params.package, tags, function (err: Error): $NextFunctionVer { if (err) { return next(err); } @@ -35,10 +35,10 @@ export default function(route: Router, auth: IAuth, storage: IStorageHandler): v 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 { + 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 { + storage.mergeTags(req.params.package, tags, function (err: VerdaccioError): $NextFunctionVer { if (err) { return next(err); } @@ -49,12 +49,12 @@ export default function(route: Router, auth: IAuth, storage: IStorageHandler): v }); }); - route.get('/-/package/:package/dist-tags', can('access'), function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + 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 { + callback: function (err: VerdaccioError, info: Package): $NextFunctionVer { if (err) { return next(err); } @@ -64,8 +64,8 @@ export default function(route: Router, auth: IAuth, storage: IStorageHandler): v }); }); - 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 { + 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); } diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 7ddf2a253..311d7b21f 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import express, {Express} from 'express'; +import express, { Express } from 'express'; import { match, validateName, validatePackage, encodeScopePackage, antiLoop } from '@verdaccio/middleware'; import { IAuth, IStorageHandler } from '@verdaccio/dev-types'; @@ -16,9 +16,9 @@ import pkg from './package'; import stars from './stars'; import profile from './v1/profile'; import token from './v1/token'; -import v1Search from './v1/search' +import v1Search from './v1/search'; -export default function(config: Config, auth: IAuth, storage: IStorageHandler): Express.Application { +export default function (config: Config, auth: IAuth, storage: IStorageHandler): Express.Application { /* eslint new-cap:off */ const app = express.Router(); /* eslint new-cap:off */ @@ -55,7 +55,7 @@ export default function(config: Config, auth: IAuth, storage: IStorageHandler): stars(app, storage); if (_.get(config, 'experiments.search') === true) { - v1Search(app, auth, storage) + v1Search(app, auth, storage); } if (_.get(config, 'experiments.token') === true) { diff --git a/packages/api/src/package.ts b/packages/api/src/package.ts index 425b8c2a7..08630a8bf 100644 --- a/packages/api/src/package.ts +++ b/packages/api/src/package.ts @@ -10,11 +10,11 @@ import { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandl 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 { + stream.on('content-length', function (content): void { res.header('Content-Length', content); }); - stream.on('error', function(err): void { + stream.on('error', function (err): void { return res.locals.report_error(err); }); @@ -22,11 +22,11 @@ const downloadStream = (packageName: string, filename: string, storage: any, req stream.pipe(res); }; -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 { + 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); } @@ -62,13 +62,13 @@ export default function(route: Router, auth: IAuth, storage: IStorageHandler, co }); }); - route.get('/:scopedPackage/-/:scope/:filename', can('access'), function(req: $RequestExtend, res: $ResponseExtend): void { + route.get('/:scopedPackage/-/:scope/:filename', can('access'), function (req: $RequestExtend, res: $ResponseExtend): void { const { scopedPackage, filename } = req.params; downloadStream(scopedPackage, filename, storage, req, res); }); - route.get('/:package/-/:filename', can('access'), function(req: $RequestExtend, res: $ResponseExtend): void { + route.get('/:package/-/:filename', can('access'), function (req: $RequestExtend, res: $ResponseExtend): void { downloadStream(req.params.package, req.params.filename, storage, req, res); }); } diff --git a/packages/api/src/ping.ts b/packages/api/src/ping.ts index 4ff4f323e..2a51c63d9 100644 --- a/packages/api/src/ping.ts +++ b/packages/api/src/ping.ts @@ -2,10 +2,7 @@ import { Router } from 'express'; import { $RequestExtend, $ResponseExtend, $NextFunctionVer } from '@verdaccio/dev-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({}); + }); } diff --git a/packages/api/src/publish.ts b/packages/api/src/publish.ts index a095f9195..a972e840e 100644 --- a/packages/api/src/publish.ts +++ b/packages/api/src/publish.ts @@ -5,14 +5,14 @@ import { Router } from 'express'; import { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler } from '@verdaccio/dev-types'; import { API_MESSAGE, HEADERS, DIST_TAGS, API_ERROR, HTTP_STATUS } from '@verdaccio/dev-commons'; -import {validateMetadata, isObject, ErrorCode, hasDiffOneKey, isRelatedToDeprecation} from '@verdaccio/utils'; +import { validateMetadata, isObject, ErrorCode, hasDiffOneKey, isRelatedToDeprecation } from '@verdaccio/utils'; import { media, expectJson, allow } from '@verdaccio/middleware'; import { notify } from '@verdaccio/hooks'; import { Config, Callback, MergeTags, Version, Package } from '@verdaccio/types'; import { logger } from '@verdaccio/logger'; import star from './star'; -import {isPublishablePackage} from "./utils"; +import { isPublishablePackage } from './utils'; export default function publish(router: Router, auth: IAuth, storage: IStorageHandler, config: Config): void { const can = allow(auth); @@ -103,43 +103,43 @@ export default function publish(router: Router, auth: IAuth, storage: IStorageHa */ export function publishPackage(storage: IStorageHandler, config: Config, auth: IAuth): any { const starApi = star(storage); - return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { const packageName = req.params.package; - logger.debug({packageName} , `publishing or updating a new version for @{packageName}`); + logger.debug({ packageName }, `publishing or updating a new version for @{packageName}`); /** * Write tarball of stream data from package clients. */ - const createTarball = function(filename: string, data, cb: Callback): void { + const createTarball = function (filename: string, data, cb: Callback): void { const stream = storage.addTarball(packageName, filename); - stream.on('error', function(err) { + stream.on('error', function (err) { cb(err); }); - stream.on('success', function() { + stream.on('success', function () { cb(); }); // this is dumb and memory-consuming, but what choices do we have? // flow: we need first refactor this file before decides which type use here - stream.end(Buffer.from(data.data, 'base64')); + stream.end(new Buffer(data.data, 'base64')); stream.done(); }; /** * Add new package version in storage */ - const createVersion = function(version: string, metadata: Version, cb: Callback): void { + const createVersion = function (version: string, metadata: Version, cb: Callback): void { storage.addVersion(packageName, version, metadata, null, cb); }; /** * Add new tags in storage */ - const addTags = function(tags: MergeTags, cb: Callback): void { + const addTags = function (tags: MergeTags, cb: Callback): void { storage.mergeTags(packageName, tags, cb); }; - const afterChange = function(error, okMessage, metadata: Package): void { + const afterChange = function (error, okMessage, metadata: Package): void { const metadataCopy: Package = { ...metadata }; const { _attachments, versions } = metadataCopy; @@ -160,8 +160,7 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I // npm-registry-client 0.3+ embeds tarball into the json upload // https://github.com/isaacs/npm-registry-client/commit/e9fbeb8b67f249394f735c74ef11fe4720d46ca0 // issue https://github.com/rlidwka/sinopia/issues/31, dealing with it here: - const isInvalidBodyFormat = isObject(_attachments) === false || hasDiffOneKey(_attachments) || - isObject(versions) === false || hasDiffOneKey(versions); + const isInvalidBodyFormat = isObject(_attachments) === false || hasDiffOneKey(_attachments) || isObject(versions) === false || hasDiffOneKey(versions); if (isInvalidBodyFormat) { // npm is doing something strange again @@ -177,22 +176,21 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I // at this point document is either created or existed before const [firstAttachmentKey] = Object.keys(_attachments); - createTarball(Path.basename(firstAttachmentKey), _attachments[firstAttachmentKey], function(error) { + createTarball(Path.basename(firstAttachmentKey), _attachments[firstAttachmentKey], function (error) { if (error) { return next(error); } const versionToPublish = Object.keys(versions)[0]; - const versionMetadataToPublish = versions[versionToPublish]; - versionMetadataToPublish.readme = _.isNil(versionMetadataToPublish.readme) === false ? String(versionMetadataToPublish.readme) : ''; + versions[versionToPublish].readme = _.isNil(metadataCopy.readme) === false ? String(metadataCopy.readme) : ''; - createVersion(versionToPublish, versionMetadataToPublish, function(error) { + createVersion(versionToPublish, versions[versionToPublish], function (error) { if (error) { return next(error); } - addTags(metadataCopy[DIST_TAGS], async function(error) { + addTags(metadataCopy[DIST_TAGS], async function (error) { if (error) { return next(error); } @@ -218,27 +216,27 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I const metadata = validateMetadata(req.body, packageName); // treating deprecation as updating a package if (req.params._rev || isRelatedToDeprecation(req.body)) { - logger.debug({packageName} , `updating a new version for @{packageName}`); + logger.debug({ packageName }, `updating a new version for @{packageName}`); // we check unpublish permissions, an update is basically remove versions const remote = req.remote_user; - auth.allow_unpublish({packageName}, remote, (error) => { + auth.allow_unpublish({ packageName }, remote, (error) => { if (error) { - logger.debug({packageName} , `not allowed to unpublish a version for @{packageName}`); + logger.debug({ packageName }, `not allowed to unpublish a version for @{packageName}`); return next(error); } - storage.changePackage(packageName, metadata, req.params.revision, function(error) { + storage.changePackage(packageName, metadata, req.params.revision, function (error) { afterChange(error, API_MESSAGE.PKG_CHANGED, metadata); }); }); } else { - logger.debug({packageName} , `adding a new version for @{packageName}`); - storage.addPackage(packageName, metadata, function(error) { + logger.debug({ packageName }, `adding a new version for @{packageName}`); + storage.addPackage(packageName, metadata, function (error) { afterChange(error, API_MESSAGE.PKG_CREATED, metadata); }); } } catch (error) { - logger.error({packageName}, 'error on publish, bad package data for @{packageName}'); + logger.error({ packageName }, 'error on publish, bad package data for @{packageName}'); return next(ErrorCode.getBadData(API_ERROR.BAD_PACKAGE_DATA)); } }; @@ -248,11 +246,11 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I * un-publish a package */ export function unPublishPackage(storage: IStorageHandler) { - return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { const packageName = req.params.package; - logger.debug({packageName} , `unpublishing @{packageName}`); - storage.removePackage(packageName, function(err) { + logger.debug({ packageName }, `unpublishing @{packageName}`); + storage.removePackage(packageName, function (err) { if (err) { return next(err); } @@ -266,18 +264,18 @@ export function unPublishPackage(storage: IStorageHandler) { * Delete tarball */ export function removeTarball(storage: IStorageHandler) { - return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { const packageName = req.params.package; - const {filename, revision} = req.params; + const { filename, revision } = req.params; - logger.debug({packageName, filename, revision} , `removing a tarball for @{packageName}-@{tarballName}-@{revision}`); - storage.removeTarball(packageName, filename, revision, function(err) { + logger.debug({ packageName, filename, revision }, `removing a tarball for @{packageName}-@{tarballName}-@{revision}`); + storage.removeTarball(packageName, filename, revision, function (err) { if (err) { return next(err); } res.status(HTTP_STATUS.CREATED); - logger.debug({packageName, filename, revision} , `success remove tarball for @{packageName}-@{tarballName}-@{revision}`); + logger.debug({ packageName, filename, revision }, `success remove tarball for @{packageName}-@{tarballName}-@{revision}`); return next({ ok: API_MESSAGE.TARBALL_REMOVED }); }); }; @@ -286,11 +284,11 @@ export function removeTarball(storage: IStorageHandler) { * Adds a new version */ export function addVersion(storage: IStorageHandler) { - return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { const { version, tag } = req.params; const packageName = req.params.package; - storage.addVersion(packageName, version, req.body, tag, function(error) { + storage.addVersion(packageName, version, req.body, tag, function (error) { if (error) { return next(error); } @@ -307,29 +305,29 @@ export function addVersion(storage: IStorageHandler) { * uploadPackageTarball */ export function uploadPackageTarball(storage: IStorageHandler) { - return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { const packageName = req.params.package; const stream = storage.addTarball(packageName, req.params.filename); req.pipe(stream); // checking if end event came before closing let complete = false; - req.on('end', function() { + req.on('end', function () { complete = true; stream.done(); }); - req.on('close', function() { + req.on('close', function () { if (!complete) { stream.abort(); } }); - stream.on('error', function(err) { + stream.on('error', function (err) { return res.locals.report_error(err); }); - stream.on('success', function() { + stream.on('success', function () { res.status(HTTP_STATUS.CREATED); return next({ ok: API_MESSAGE.TARBALL_UPLOADED, diff --git a/packages/api/src/search.ts b/packages/api/src/search.ts index 11ed57e15..07b639feb 100644 --- a/packages/api/src/search.ts +++ b/packages/api/src/search.ts @@ -1,15 +1,15 @@ import { HEADERS } from '@verdaccio/dev-commons'; -export default function(route, auth, storage): void { +export default function (route, auth, storage): void { // searching packages - route.get('/-/all(/since)?', function(req, res) { + route.get('/-/all(/since)?', function (req, res) { let received_end = false; let response_finished = false; let processing_pkgs = 0; let firstPackage = true; res.status(200); - res.set(HEADERS.CONTENT_TYPE, HEADERS.JSON_CHARSET) + res.set(HEADERS.CONTENT_TYPE, HEADERS.JSON_CHARSET); /* * Offical NPM registry (registry.npmjs.org) no longer return whole database, @@ -33,7 +33,7 @@ export default function(route, auth, storage): void { if (!respShouldBeArray) { res.set('Date', 'Mon, 10 Oct 1983 00:12:48 GMT'); } - const check_finish = function(): void { + const check_finish = function (): void { if (!received_end) { return; } @@ -62,7 +62,7 @@ export default function(route, auth, storage): void { stream.on('data', function each(pkg) { processing_pkgs++; - auth.allow_access({ packageName: pkg.name }, req.remote_user, function(err, allowed) { + auth.allow_access({ packageName: pkg.name }, req.remote_user, function (err, allowed) { processing_pkgs--; if (err) { @@ -90,11 +90,11 @@ export default function(route, auth, storage): void { }); }); - stream.on('error', function() { + stream.on('error', function () { res.socket.destroy(); }); - stream.on('end', function() { + stream.on('end', function () { received_end = true; check_finish(); }); diff --git a/packages/api/src/star.ts b/packages/api/src/star.ts index 5bf2639c5..672e8f579 100644 --- a/packages/api/src/star.ts +++ b/packages/api/src/star.ts @@ -1,11 +1,11 @@ import { USERS, HTTP_STATUS } from '@verdaccio/dev-commons'; -import {Response} from 'express'; +import { Response } from 'express'; import _ from 'lodash'; import { logger } from '@verdaccio/logger'; -import {$RequestExtend, $NextFunctionVer, IStorageHandler} from '@verdaccio/dev-types'; +import { $RequestExtend, $NextFunctionVer, IStorageHandler } from '@verdaccio/dev-types'; -export default function(storage: IStorageHandler): (req: $RequestExtend, res: Response, next: $NextFunctionVer) => void { +export default function (storage: IStorageHandler): (req: $RequestExtend, res: Response, next: $NextFunctionVer) => void { const validateInputs = (newUsers, localUsers, username, isStar): boolean => { const isExistlocalUsers = _.isNil(localUsers[username]) === false; if (isStar && isExistlocalUsers && localUsers[username]) { @@ -20,8 +20,8 @@ export default function(storage: IStorageHandler): (req: $RequestExtend, res: Re return (req: $RequestExtend, res: Response, next: $NextFunctionVer): void => { const name = req.params.package; - logger.debug({name}, 'starring a package for @{name}'); - const afterChangePackage = function(err?: Error) { + logger.debug({ name }, 'starring a package for @{name}'); + const afterChangePackage = function (err?: Error) { if (err) { return next(err); } @@ -34,7 +34,7 @@ export default function(storage: IStorageHandler): (req: $RequestExtend, res: Re storage.getPackage({ name, req, - callback: function(err, info) { + callback: function (err, info) { if (err) { return next(err); } @@ -46,16 +46,22 @@ export default function(storage: IStorageHandler): (req: $RequestExtend, res: Re if (_.isNil(localStarUsers) === false && validateInputs(newStarUser, localStarUsers, remoteUsername, isStar)) { return afterChangePackage(); } - const users = isStar ? { - ...localStarUsers, - [remoteUsername]: true, - } : _.reduce(localStarUsers, (users, value, key) => { - if (key !== remoteUsername) { - users[key] = value; - } - return users; - }, {}); - storage.changePackage(name, { ...info, users}, req.body._rev, function(err) { + const users = isStar + ? { + ...localStarUsers, + [remoteUsername]: true, + } + : _.reduce( + localStarUsers, + (users, value, key) => { + if (key !== remoteUsername) { + users[key] = value; + } + return users; + }, + {} + ); + storage.changePackage(name, { ...info, users }, req.body._rev, function (err) { afterChangePackage(err); }); }, diff --git a/packages/api/src/stars.ts b/packages/api/src/stars.ts index f7e5e7896..0bb99afa8 100644 --- a/packages/api/src/stars.ts +++ b/packages/api/src/stars.ts @@ -8,7 +8,7 @@ import { $RequestExtend, $NextFunctionVer, IStorageHandler } from '@verdaccio/de type Packages = Package[]; -export default function(route: Router, storage: IStorageHandler): void { +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; @@ -17,9 +17,7 @@ export default function(route: Router, storage: IStorageHandler): void { 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({ diff --git a/packages/api/src/user.ts b/packages/api/src/user.ts index 187d568af..7464eeb86 100644 --- a/packages/api/src/user.ts +++ b/packages/api/src/user.ts @@ -10,15 +10,15 @@ import { Config, RemoteUser } from '@verdaccio/types'; import { $RequestExtend, $ResponseExtend, $NextFunctionVer, IAuth } from '@verdaccio/dev-types'; import { API_ERROR, API_MESSAGE, HTTP_STATUS } from '@verdaccio/dev-commons'; -export default function(route: Router, auth: IAuth, config: Config): void { - route.get('/-/user/:org_couchdb_user', function(req: $RequestExtend, res: Response, next: $NextFunctionVer): void { +export default function (route: Router, auth: IAuth, config: Config): void { + route.get('/-/user/:org_couchdb_user', function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void { res.status(HTTP_STATUS.OK); next({ ok: getAuthenticatedMessage(req.remote_user.name), }); }); - route.put('/-/user/:org_couchdb_user/:_rev?/:revision?', function(req: $RequestExtend, res: Response, next: $NextFunctionVer): void { + route.put('/-/user/:org_couchdb_user/:_rev?/:revision?', function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void { const { name, password } = req.body; const remoteName = req.remote_user.name; @@ -45,7 +45,7 @@ export default function(route: Router, auth: IAuth, config: Config): void { return next(ErrorCode.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.PASSWORD_SHORT())); } - auth.add_user(name, password, async function(err, user): Promise { + auth.add_user(name, password, async function (err, user): Promise { if (err) { if (err.status >= HTTP_STATUS.BAD_REQUEST && err.status < HTTP_STATUS.INTERNAL_ERROR) { // With npm registering is the same as logging in, @@ -68,7 +68,7 @@ export default function(route: Router, auth: IAuth, config: Config): void { } }); - route.delete('/-/user/token/*', function(req: $RequestExtend, res: Response, next: $NextFunctionVer): void { + route.delete('/-/user/token/*', function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void { res.status(HTTP_STATUS.OK); next({ ok: API_MESSAGE.LOGGED_OUT, diff --git a/packages/api/src/utils.ts b/packages/api/src/utils.ts index d4dc51a9f..76ad05747 100644 --- a/packages/api/src/utils.ts +++ b/packages/api/src/utils.ts @@ -1,4 +1,4 @@ -import {Package} from '@verdaccio/types'; +import { Package } from '@verdaccio/types'; import _ from 'lodash'; /** @@ -7,7 +7,7 @@ import _ from 'lodash'; */ export function isPublishablePackage(pkg: Package): boolean { - const keys: string[] = Object.keys(pkg); + const keys: string[] = Object.keys(pkg); - return _.includes(keys, 'versions'); + return _.includes(keys, 'versions'); } diff --git a/packages/api/src/v1/profile.ts b/packages/api/src/v1/profile.ts index bb7280086..04bc124c9 100644 --- a/packages/api/src/v1/profile.ts +++ b/packages/api/src/v1/profile.ts @@ -16,7 +16,7 @@ export interface Profile { fullname: string; } -export default function(route: Router, auth: IAuth): void { +export default function (route: Router, auth: IAuth): void { function buildProfile(name: string): Profile { return { tfa: false, @@ -30,7 +30,7 @@ export default function(route: Router, auth: IAuth): void { }; } - route.get('/-/npm/v1/user', function(req: $RequestExtend, res: Response, next: $NextFunctionVer): void { + route.get('/-/npm/v1/user', function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void { if (_.isNil(req.remote_user.name) === false) { return next(buildProfile(req.remote_user.name)); } @@ -41,7 +41,7 @@ export default function(route: Router, auth: IAuth): void { }); }); - route.post('/-/npm/v1/user', function(req: $RequestExtend, res: Response, next: $NextFunctionVer): void { + route.post('/-/npm/v1/user', function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void { if (_.isNil(req.remote_user.name)) { res.status(HTTP_STATUS.UNAUTHORIZED); return next({ diff --git a/packages/api/src/v1/search.ts b/packages/api/src/v1/search.ts index 38d01fd15..0466f46b9 100644 --- a/packages/api/src/v1/search.ts +++ b/packages/api/src/v1/search.ts @@ -1,98 +1,101 @@ -import semver from 'semver' +import semver from 'semver'; import { Package } from '@verdaccio/types'; -function compileTextSearch(textSearch: string): ((pkg: Package) => boolean) { - const personMatch = (person, search) => { - if(typeof person === 'string') - {return person.includes(search);} +function compileTextSearch(textSearch: string): (pkg: Package) => boolean { + const personMatch = (person, search) => { + if (typeof person === 'string') { + return person.includes(search); + } - if(typeof person === 'object') - {for(const field of Object.values(person)) - {if(typeof field === 'string' && field.includes(search)) - {return true;}}} - - return false; + if (typeof person === 'object') { + for (const field of Object.values(person)) { + if (typeof field === 'string' && field.includes(search)) { + return true; } - const matcher = function(q) { - const match = q.match(/author:(.*)/) - if(match !== null) - {return (pkg) => personMatch(pkg.author, match[1])} + } + } - // TODO: maintainer, keywords, not/is unstable insecure, boost-exact - // TODO implement some scoring system for freetext - return (pkg) => { - return ['name', 'displayName', 'description'] - .map(k => pkg[k]) - .filter(x => x !== undefined) - .some(txt => txt.includes(q)) - }; - } + return false; + }; + const matcher = function (q) { + const match = q.match(/author:(.*)/); + if (match !== null) { + return (pkg) => personMatch(pkg.author, match[1]); + } - const textMatchers = (textSearch || '').split(' ').map(matcher); - return (pkg) => textMatchers.every(m => m(pkg)); + // TODO: maintainer, keywords, not/is unstable insecure, boost-exact + // TODO implement some scoring system for freetext + return (pkg) => { + return ['name', 'displayName', 'description'] + .map((k) => pkg[k]) + .filter((x) => x !== undefined) + .some((txt) => txt.includes(q)); + }; + }; + + const textMatchers = (textSearch || '').split(' ').map(matcher); + return (pkg) => textMatchers.every((m) => m(pkg)); } -export default function(route, auth, storage): void { - route.get('/-/v1/search', (req, res)=>{ - // TODO: implement proper result scoring weighted by quality, popularity and maintenance query parameters - let [text, size, from /* , quality, popularity, maintenance */] = - ['text', 'size', 'from' /* , 'quality', 'popularity', 'maintenance' */] - .map(k => req.query[k]) +export default function (route, auth, storage): void { + route.get('/-/v1/search', (req, res) => { + // TODO: implement proper result scoring weighted by quality, popularity and maintenance query parameters + let [text, size, from /* , quality, popularity, maintenance */] = ['text', 'size', 'from' /* , 'quality', 'popularity', 'maintenance' */].map( + (k) => req.query[k] + ); - size = parseInt(size) || 20; - from = parseInt(from) || 0; + size = parseInt(size) || 20; + from = parseInt(from) || 0; - const isInteresting = compileTextSearch(text); + const isInteresting = compileTextSearch(text); - const resultStream = storage.search(0, {req: {query: {local: true}}}); - const resultBuf = [] as any; - let completed = false; + const resultStream = storage.search(0, { req: { query: { local: true } } }); + const resultBuf = [] as any; + let completed = false; - const sendResponse = (): void => { - completed = true; - resultStream.destroy() + const sendResponse = (): void => { + completed = true; + resultStream.destroy(); - const final = resultBuf.slice(from, size).map(pkg => { - return { - package: pkg, - flags: { - unstable: - Object.keys(pkg.versions) - .some(v => semver.satisfies(v, '^1.0.0')) - ? undefined - : true - }, - score: { - final: 1, - detail: { - quality: 1, - popularity: 1, - maintenance: 0 - } - }, - searchScore: 100000 - } - }) - const response = { - objects: final, - total: final.length, - time: new Date().toUTCString() - } + const final = resultBuf.slice(from, size).map((pkg) => { + return { + package: pkg, + flags: { + unstable: Object.keys(pkg.versions).some((v) => semver.satisfies(v, '^1.0.0')) ? undefined : true, + }, + score: { + final: 1, + detail: { + quality: 1, + popularity: 1, + maintenance: 0, + }, + }, + searchScore: 100000, + }; + }); + const response = { + objects: final, + total: final.length, + time: new Date().toUTCString(), + }; - res.status(200) - .json(response) - } + res.status(200).json(response); + }; - resultStream.on('data', (pkg)=>{ - if(!isInteresting(pkg)) - {return;} - resultBuf.push(pkg) - if(!completed && resultBuf.length >= size + from) - {sendResponse();} - }) - resultStream.on('end', ()=>{ - if(!completed) - {sendResponse()} - }) - }) + resultStream.on('data', (pkg) => { + if (!isInteresting(pkg)) { + return; + } + resultBuf.push(pkg); + if (!completed && resultBuf.length >= size + from) { + sendResponse(); + } + }); + resultStream.on('end', () => { + if (!completed) { + sendResponse(); + } + }); + }); } diff --git a/packages/api/src/v1/token.ts b/packages/api/src/v1/token.ts index d55ebc75f..03dd7b58a 100644 --- a/packages/api/src/v1/token.ts +++ b/packages/api/src/v1/token.ts @@ -1,122 +1,126 @@ import _ from 'lodash'; import { HTTP_STATUS, SUPPORT_ERRORS } from '@verdaccio/dev-commons'; -import {ErrorCode, stringToMD5, mask } from '@verdaccio/utils'; +import { ErrorCode, stringToMD5, mask } from '@verdaccio/utils'; import { getApiToken } from '@verdaccio/auth'; import { logger } from '@verdaccio/logger'; import { Response, Router } from 'express'; import { Config, RemoteUser, Token } from '@verdaccio/types'; -import {$NextFunctionVer, $RequestExtend, IAuth, IStorageHandler} from '../../../types'; +import { $NextFunctionVer, $RequestExtend, IAuth, IStorageHandler } from '../../../types'; export type NormalizeToken = Token & { - created: string; + created: string; }; function normalizeToken(token: Token): NormalizeToken { - return { - ...token, - created: new Date(token.created).toISOString(), - }; -}; + return { + ...token, + created: new Date(token.created).toISOString(), + }; +} // https://github.com/npm/npm-profile/blob/latest/lib/index.js -export default function(route: Router, auth: IAuth, storage: IStorageHandler, config: Config): void { - route.get('/-/npm/v1/tokens', async function(req: $RequestExtend, res: Response, next: $NextFunctionVer) { - const { name } = req.remote_user; +export default function (route: Router, auth: IAuth, storage: IStorageHandler, config: Config): void { + route.get('/-/npm/v1/tokens', async function (req: $RequestExtend, res: Response, next: $NextFunctionVer) { + const { name } = req.remote_user; - if (_.isNil(name) === false) { - try { - const tokens = await storage.readTokens({user: name}); - const totalTokens = tokens.length; - logger.debug({totalTokens}, 'token list retrieved: @{totalTokens}'); + if (_.isNil(name) === false) { + try { + const tokens = await storage.readTokens({ user: name }); + const totalTokens = tokens.length; + logger.debug({ totalTokens }, 'token list retrieved: @{totalTokens}'); - res.status(HTTP_STATUS.OK); - return next({ - objects: tokens.map(normalizeToken), - urls: { - next: '', // TODO: pagination? - }, - }); - } catch (error) { - logger.error({ error: error.msg }, 'token list has failed: @{error}'); - return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message)); - } - } - return next(ErrorCode.getUnauthorized()); - }); + res.status(HTTP_STATUS.OK); + return next({ + objects: tokens.map(normalizeToken), + urls: { + next: '', // TODO: pagination? + }, + }); + } catch (error) { + logger.error({ error: error.msg }, 'token list has failed: @{error}'); + return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message)); + } + } + return next(ErrorCode.getUnauthorized()); + }); - route.post('/-/npm/v1/tokens', function(req: $RequestExtend, res: Response, next: $NextFunctionVer) { - const { password, readonly, cidr_whitelist } = req.body; - const { name } = req.remote_user; + route.post('/-/npm/v1/tokens', function (req: $RequestExtend, res: Response, next: $NextFunctionVer) { + const { password, readonly, cidr_whitelist } = req.body; + const { name } = req.remote_user; - if (!_.isBoolean(readonly) || !_.isArray(cidr_whitelist)) { - return next(ErrorCode.getCode(HTTP_STATUS.BAD_DATA, SUPPORT_ERRORS.PARAMETERS_NOT_VALID)); - } + if (!_.isBoolean(readonly) || !_.isArray(cidr_whitelist)) { + return next(ErrorCode.getCode(HTTP_STATUS.BAD_DATA, SUPPORT_ERRORS.PARAMETERS_NOT_VALID)); + } - auth.authenticate(name, password, async (err, user: RemoteUser) => { - if (err) { - const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR; - return next(ErrorCode.getCode(errorCode, err.message)); - } + auth.authenticate(name, password, async (err, user: RemoteUser) => { + if (err) { + const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR; + return next(ErrorCode.getCode(errorCode, err.message)); + } - req.remote_user = user; + req.remote_user = user; - if (!_.isFunction(storage.saveToken)) { - return next(ErrorCode.getCode(HTTP_STATUS.NOT_IMPLEMENTED, SUPPORT_ERRORS.STORAGE_NOT_IMPLEMENT)); - } + if (!_.isFunction(storage.saveToken)) { + return next(ErrorCode.getCode(HTTP_STATUS.NOT_IMPLEMENTED, SUPPORT_ERRORS.STORAGE_NOT_IMPLEMENT)); + } - try { - const token = await getApiToken(auth, config, user, password); - const key = stringToMD5(token); - // TODO: use a utility here - const maskedToken = mask(token, 5); - const created = new Date().getTime(); + try { + const token = await getApiToken(auth, config, user, password); + const key = stringToMD5(token); + // TODO: use a utility here + const maskedToken = mask(token, 5); + const created = new Date().getTime(); - /** - * cidr_whitelist: is not being used, we pass it through - * token: we do not store the real token (it is generated once and retrieved to the user), just a mask of it. - */ - const saveToken: Token = { - user: name, - token: maskedToken, - key, - cidr: cidr_whitelist, - readonly, - created, - }; + /** + * cidr_whitelist: is not being used, we pass it through + * token: we do not store the real token (it is generated once and retrieved to the user), just a mask of it. + */ + const saveToken: Token = { + user: name, + token: maskedToken, + key, + cidr: cidr_whitelist, + readonly, + created, + }; - await storage.saveToken(saveToken); - logger.debug({ key, name }, 'token @{key} was created for user @{name}'); - return next(normalizeToken({ - token, - user: name, - key: saveToken.key, - cidr: cidr_whitelist, - readonly, - created: saveToken.created, - })); - } catch (error) { - logger.error({ error: error.msg }, 'token creation has failed: @{error}'); - return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message)); - } - }); - }); + await storage.saveToken(saveToken); + logger.debug({ key, name }, 'token @{key} was created for user @{name}'); + return next( + normalizeToken({ + token, + user: name, + key: saveToken.key, + cidr: cidr_whitelist, + readonly, + created: saveToken.created, + }) + ); + } catch (error) { + logger.error({ error: error.msg }, 'token creation has failed: @{error}'); + return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message)); + } + }); + }); - route.delete('/-/npm/v1/tokens/token/:tokenKey', async (req: $RequestExtend, res: Response, next: $NextFunctionVer) => { - const { params: { tokenKey }} = req; - const { name } = req.remote_user; + route.delete('/-/npm/v1/tokens/token/:tokenKey', async (req: $RequestExtend, res: Response, next: $NextFunctionVer) => { + const { + params: { tokenKey }, + } = req; + const { name } = req.remote_user; - if (_.isNil(name) === false) { - logger.debug({name}, '@{name} has requested remove a token'); - try { - await storage.deleteToken(name, tokenKey); - logger.info({ tokenKey, name }, 'token id @{tokenKey} was revoked for user @{name}'); - return next({}); - } catch(error) { - logger.error({ error: error.msg }, 'token creation has failed: @{error}'); - return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message)); - } - } - return next(ErrorCode.getUnauthorized()); - }); + if (_.isNil(name) === false) { + logger.debug({ name }, '@{name} has requested remove a token'); + try { + await storage.deleteToken(name, tokenKey); + logger.info({ tokenKey, name }, 'token id @{tokenKey} was revoked for user @{name}'); + return next({}); + } catch (error) { + logger.error({ error: error.msg }, 'token creation has failed: @{error}'); + return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message)); + } + } + return next(ErrorCode.getUnauthorized()); + }); } diff --git a/packages/api/test/integration/_helper.ts b/packages/api/test/integration/_helper.ts index e5d3d6c3c..12c4a4d5a 100644 --- a/packages/api/test/integration/_helper.ts +++ b/packages/api/test/integration/_helper.ts @@ -1,72 +1,72 @@ -import path from "path"; -import express, {Application} from 'express'; +import path from 'path'; +import express, { Application } from 'express'; import supertest from 'supertest'; import bodyParser from 'body-parser'; -import {parseConfigFile} from '@verdaccio/utils'; +import { parseConfigFile } from '@verdaccio/utils'; import { Config } from '@verdaccio/config'; import { Storage } from '@verdaccio/store'; import { final, handleError, errorReportingMiddleware } from '@verdaccio/middleware'; import { Auth } from '@verdaccio/auth'; -import {IAuth} from "@verdaccio/dev-types"; -import {HEADER_TYPE, HTTP_STATUS, generatePackageMetadata} from "@verdaccio/dev-commons"; -import {HEADERS} from "@verdaccio/commons-api"; +import { IAuth } from '@verdaccio/dev-types'; +import { HEADER_TYPE, HTTP_STATUS, generatePackageMetadata } from '@verdaccio/dev-commons'; +import { HEADERS } from '@verdaccio/commons-api'; import apiEndpoints from '../../src'; const getConf = (conf) => { - const configPath = path.join(__dirname, 'config', conf); + const configPath = path.join(__dirname, 'config', conf); - return parseConfigFile(configPath); + return parseConfigFile(configPath); }; export async function initializeServer(configName): Promise { - const app = express(); - const config = new Config(getConf(configName)); - const storage = new Storage(config); - await storage.init(config, []); - const auth: IAuth = new Auth(config); - app.use(bodyParser.json({ strict: false, limit: '10mb' })); - // @ts-ignore - app.use(errorReportingMiddleware); - // @ts-ignore - app.use(apiEndpoints(config, auth, storage)); - // @ts-ignore - app.use(handleError); - // @ts-ignore - app.use(final); + const app = express(); + const config = new Config(getConf(configName)); + const storage = new Storage(config); + await storage.init(config, []); + const auth: IAuth = new Auth(config); + app.use(bodyParser.json({ strict: false, limit: '10mb' })); + // @ts-ignore + app.use(errorReportingMiddleware); + // @ts-ignore + app.use(apiEndpoints(config, auth, storage)); + // @ts-ignore + app.use(handleError); + // @ts-ignore + app.use(final); - app.use(function(request, response) { - response.status(590); - console.log('respo', response); - response.json({error: 'cannot handle this'}); - }); + app.use(function (request, response) { + response.status(590); + console.log('respo', response); + response.json({ error: 'cannot handle this' }); + }); - return app; + return app; } export function publishVersion(app, configFile, pkgName, version): supertest.Test { - const pkgMetadata = generatePackageMetadata(pkgName, version); + const pkgMetadata = generatePackageMetadata(pkgName, version); - return supertest(app) - .put(`/${encodeURIComponent(pkgName)}`) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .send(JSON.stringify(pkgMetadata)) - .set('accept', HEADERS.GZIP) - .set(HEADER_TYPE.ACCEPT_ENCODING, HEADERS.JSON) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); + return supertest(app) + .put(`/${encodeURIComponent(pkgName)}`) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .send(JSON.stringify(pkgMetadata)) + .set('accept', HEADERS.GZIP) + .set(HEADER_TYPE.ACCEPT_ENCODING, HEADERS.JSON) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); } export async function publishTaggedVersion(app, configFile, pkgName: string, version: string, tag: string) { - const pkgMetadata = generatePackageMetadata(pkgName, version, { - [tag]: version - }); + const pkgMetadata = generatePackageMetadata(pkgName, version, { + [tag]: version, + }); - return supertest(app) - .put(`/${encodeURIComponent(pkgName)}/${encodeURIComponent(version)}/-tag/${encodeURIComponent(tag)}`) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .send(JSON.stringify(pkgMetadata)) - .expect(HTTP_STATUS.CREATED) - .set('accept', HEADERS.GZIP) - .set(HEADER_TYPE.ACCEPT_ENCODING, HEADERS.JSON) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); + return supertest(app) + .put(`/${encodeURIComponent(pkgName)}/${encodeURIComponent(version)}/-tag/${encodeURIComponent(tag)}`) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .send(JSON.stringify(pkgMetadata)) + .expect(HTTP_STATUS.CREATED) + .set('accept', HEADERS.GZIP) + .set(HEADER_TYPE.ACCEPT_ENCODING, HEADERS.JSON) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); } diff --git a/packages/api/test/integration/package.spec.ts b/packages/api/test/integration/package.spec.ts index a561e9717..37f5751a7 100644 --- a/packages/api/test/integration/package.spec.ts +++ b/packages/api/test/integration/package.spec.ts @@ -1,83 +1,80 @@ import supertest from 'supertest'; import { HTTP_STATUS } from '@verdaccio/commons-api'; -import {HEADER_TYPE, HEADERS} from '@verdaccio/dev-commons'; -import {$RequestExtend, $ResponseExtend} from "@verdaccio/dev-types"; -import {initializeServer, publishTaggedVersion, publishVersion} from './_helper'; +import { HEADER_TYPE, HEADERS } from '@verdaccio/dev-commons'; +import { $RequestExtend, $ResponseExtend } from '@verdaccio/dev-types'; +import { initializeServer, publishTaggedVersion, publishVersion } from './_helper'; -const mockApiJWTmiddleware = jest.fn(() => - (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: 'foo', groups: [], real_groups: []} - _next(); - } -); +const mockApiJWTmiddleware = jest.fn(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: 'foo', groups: [], real_groups: [] }; + _next(); +}); jest.mock('@verdaccio/auth', () => ({ - Auth: class { - apiJWTmiddleware() { - return mockApiJWTmiddleware(); - } - allow_access (_d, f_, cb) { - cb(null, true) - } - allow_publish (_d, f_, cb) { - cb(null, true) - } - } + Auth: class { + apiJWTmiddleware() { + return mockApiJWTmiddleware(); + } + allow_access(_d, f_, cb) { + cb(null, true); + } + allow_publish(_d, f_, cb) { + cb(null, true); + } + }, })); describe('package', () => { - let app; - beforeAll(async () => { - app = await initializeServer('package.yaml'); - await publishVersion(app, 'package.yaml', 'foo', '1.0.0'); - }); + let app; + beforeAll(async () => { + app = await initializeServer('package.yaml'); + await publishVersion(app, 'package.yaml', 'foo', '1.0.0'); + }); - test('should return a package', async (done) => { + test('should return a package', async (done) => { + return supertest(app) + .get('/foo') + .set('Accept', HEADERS.JSON) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.OK) + .then((response) => { + expect(response.body.name).toEqual('foo'); + done(); + }); + }); - return supertest(app) - .get('/foo') - .set('Accept', HEADERS.JSON) - .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.OK) - .then(response => { - expect(response.body.name).toEqual('foo'); - done(); - }); - }); + test('should return a package by version', async (done) => { + return supertest(app) + .get('/foo/1.0.0') + .set('Accept', HEADERS.JSON) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.OK) + .then((response) => { + expect(response.body.name).toEqual('foo'); + done(); + }); + }); - test('should return a package by version', async (done) => { - return supertest(app) - .get('/foo/1.0.0') - .set('Accept', HEADERS.JSON) - .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.OK) - .then(response => { - expect(response.body.name).toEqual('foo'); - done(); - }); - }); + // TODO: investigate the 404 + test.skip('should return a package by dist-tag', async (done) => { + await publishVersion(app, 'package.yaml', 'foo-tagged', '1.0.0'); + await publishTaggedVersion(app, 'package.yaml', 'foo-tagged', '1.0.1', 'test'); + return supertest(app) + .get('/foo-tagged/1.0.0') + .set('Accept', HEADERS.JSON) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.CREATED) + .then((response) => { + expect(response.body.name).toEqual('foo'); + done(); + }); + }); - // TODO: investigate the 404 - test.skip('should return a package by dist-tag', async (done) => { - await publishVersion(app, 'package.yaml', 'foo-tagged', '1.0.0'); - await publishTaggedVersion(app, 'package.yaml', 'foo-tagged', '1.0.1', 'test'); - return supertest(app) - .get('/foo-tagged/1.0.0') - .set('Accept', HEADERS.JSON) - .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.CREATED) - .then(response => { - expect(response.body.name).toEqual('foo'); - done(); - }); - }); - - test('should return 404', async () => { - return supertest(app) - .get('/404-not-found') - .set('Accept', HEADERS.JSON) - .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.NOT_FOUND); - }); + test('should return 404', async () => { + return supertest(app) + .get('/404-not-found') + .set('Accept', HEADERS.JSON) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.NOT_FOUND); + }); }); diff --git a/packages/api/test/integration/ping.spec.ts b/packages/api/test/integration/ping.spec.ts index 449d789ca..818bf205e 100644 --- a/packages/api/test/integration/ping.spec.ts +++ b/packages/api/test/integration/ping.spec.ts @@ -1,16 +1,16 @@ import supertest from 'supertest'; import { HTTP_STATUS } from '@verdaccio/commons-api'; -import {HEADER_TYPE, HEADERS} from '@verdaccio/dev-commons'; -import {initializeServer } from './_helper'; +import { HEADER_TYPE, HEADERS } from '@verdaccio/dev-commons'; +import { initializeServer } from './_helper'; describe('ping', () => { - test('should return the reply the ping', async () => { - return supertest(await initializeServer('ping.yaml')) - .get('/-/ping') - .set('Accept', HEADERS.JSON) - .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.OK) - .then(response => expect(response.body).toEqual({})); - }); + test('should return the reply the ping', async () => { + return supertest(await initializeServer('ping.yaml')) + .get('/-/ping') + .set('Accept', HEADERS.JSON) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.OK) + .then((response) => expect(response.body).toEqual({})); + }); }); diff --git a/packages/api/test/integration/publish.spec.ts b/packages/api/test/integration/publish.spec.ts index 78e832f52..52051ed07 100644 --- a/packages/api/test/integration/publish.spec.ts +++ b/packages/api/test/integration/publish.spec.ts @@ -1,34 +1,32 @@ import { HTTP_STATUS } from '@verdaccio/commons-api'; -import {API_ERROR, API_MESSAGE, generatePackageMetadata, HEADER_TYPE, HEADERS} from '@verdaccio/dev-commons'; -import {$RequestExtend, $ResponseExtend} from '@verdaccio/dev-types'; -import supertest from "supertest"; -import {initializeServer, publishVersion} from './_helper'; +import { API_ERROR, API_MESSAGE, generatePackageMetadata, HEADER_TYPE, HEADERS } from '@verdaccio/dev-commons'; +import { $RequestExtend, $ResponseExtend } from '@verdaccio/dev-types'; +import supertest from 'supertest'; +import { initializeServer, publishVersion } from './_helper'; -const mockApiJWTmiddleware = jest.fn(() => - (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: 'foo', groups: [], real_groups: []} - _next(); - } -); +const mockApiJWTmiddleware = jest.fn(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: 'foo', groups: [], real_groups: [] }; + _next(); +}); jest.setTimeout(50000000); jest.mock('@verdaccio/auth', () => ({ - Auth: class { - apiJWTmiddleware() { - return mockApiJWTmiddleware(); - } - allow_access (_d, f_, cb) { - cb(null, true) - } - allow_publish (_d, f_, cb) { - cb(null, true) - } + Auth: class { + apiJWTmiddleware() { + return mockApiJWTmiddleware(); + } + allow_access(_d, f_, cb) { + cb(null, true); + } + allow_publish(_d, f_, cb) { + cb(null, true); + } - allow_unpublish (_d, f_, cb) { - cb(null, true) - } - } + allow_unpublish(_d, f_, cb) { + cb(null, true); + } + }, })); // const mockStorage = jest.fn(() => { @@ -55,125 +53,134 @@ jest.mock('@verdaccio/auth', () => ({ // }); describe('publish', () => { - describe('handle invalid publish formats', () => { - const pkgName = 'test'; - const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0'); - test.skip('should fail on publish a bad _attachments package', async (done) => { - const app = await initializeServer('publish.yaml'); - return supertest(app) - .put(`/${encodeURIComponent(pkgName)}`) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .send(JSON.stringify(Object.assign({}, pkgMetadata, { - _attachments: {} - }))) - .set('accept', HEADERS.GZIP) - .expect(HTTP_STATUS.BAD_REQUEST) - .then(response => { - console.log("response.body", response.body); - expect(response.body.error).toEqual(API_ERROR.UNSUPORTED_REGISTRY_CALL); - done(); - }); - }); + describe('handle invalid publish formats', () => { + const pkgName = 'test'; + const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0'); + test.skip('should fail on publish a bad _attachments package', async (done) => { + const app = await initializeServer('publish.yaml'); + return supertest(app) + .put(`/${encodeURIComponent(pkgName)}`) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .send( + JSON.stringify( + Object.assign({}, pkgMetadata, { + _attachments: {}, + }) + ) + ) + .set('accept', HEADERS.GZIP) + .expect(HTTP_STATUS.BAD_REQUEST) + .then((response) => { + console.log('response.body', response.body); + expect(response.body.error).toEqual(API_ERROR.UNSUPORTED_REGISTRY_CALL); + done(); + }); + }); - test('should fail on publish a bad versions package', async (done) => { - const app = await initializeServer('publish.yaml'); - return supertest(app) - .put(`/${encodeURIComponent(pkgName)}`) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .send(JSON.stringify(Object.assign({}, pkgMetadata, { - versions: '' - }))) - .set('accept', HEADERS.GZIP) - .expect(HTTP_STATUS.BAD_REQUEST) - .then(response => { - console.log("response.body", response.body); - expect(response.body.error).toEqual(API_ERROR.UNSUPORTED_REGISTRY_CALL); - done(); - }); - }); - }); + test('should fail on publish a bad versions package', async (done) => { + const app = await initializeServer('publish.yaml'); + return supertest(app) + .put(`/${encodeURIComponent(pkgName)}`) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .send( + JSON.stringify( + Object.assign({}, pkgMetadata, { + versions: '', + }) + ) + ) + .set('accept', HEADERS.GZIP) + .expect(HTTP_STATUS.BAD_REQUEST) + .then((response) => { + console.log('response.body', response.body); + expect(response.body.error).toEqual(API_ERROR.UNSUPORTED_REGISTRY_CALL); + done(); + }); + }); + }); - describe('publish a package', () => { - test('should publish a package', async (done) => { - const app = await initializeServer('publish.yaml'); - return publishVersion(app, 'publish.yaml', 'foo', '1.0.0') - .expect(HTTP_STATUS.CREATED) - .then(response => { - expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED); - done(); - }); - }); + describe('publish a package', () => { + test('should publish a package', async (done) => { + const app = await initializeServer('publish.yaml'); + return publishVersion(app, 'publish.yaml', 'foo', '1.0.0') + .expect(HTTP_STATUS.CREATED) + .then((response) => { + expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED); + done(); + }); + }); - test('should publish a new package', async (done) => { - const pkgName = 'test'; - const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0'); - const app = await initializeServer('publish.yaml'); - return supertest(app) - .put(`/${encodeURIComponent(pkgName)}`) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .send(JSON.stringify(Object.assign({}, pkgMetadata, { - _attachments: null - }))) - .set('accept', HEADERS.GZIP) - .expect(HTTP_STATUS.CREATED) - .then(response => { - expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED); - done(); - }); - }); + test('should publish a new package', async (done) => { + const pkgName = 'test'; + const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0'); + const app = await initializeServer('publish.yaml'); + return supertest(app) + .put(`/${encodeURIComponent(pkgName)}`) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .send( + JSON.stringify( + Object.assign({}, pkgMetadata, { + _attachments: null, + }) + ) + ) + .set('accept', HEADERS.GZIP) + .expect(HTTP_STATUS.CREATED) + .then((response) => { + expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED); + done(); + }); + }); - test('should publish a new package with no readme', async (done) => { - const pkgName = 'test'; - const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0'); - const app = await initializeServer('publish.yaml'); - return supertest(app) - .put(`/${encodeURIComponent(pkgName)}`) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .send(JSON.stringify(Object.assign({}, pkgMetadata, { - versions: { - ['1.0.0'] : { - readme: null - } - } - }))) - .set('accept', HEADERS.GZIP) - .expect(HTTP_STATUS.CREATED) - .then(response => { - expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED); - done(); - }); - }); + test('should publish a new package with no readme', async (done) => { + const pkgName = 'test'; + const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0'); + const app = await initializeServer('publish.yaml'); + return supertest(app) + .put(`/${encodeURIComponent(pkgName)}`) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .send( + JSON.stringify( + Object.assign({}, pkgMetadata, { + versions: { + ['1.0.0']: { + readme: null, + }, + }, + }) + ) + ) + .set('accept', HEADERS.GZIP) + .expect(HTTP_STATUS.CREATED) + .then((response) => { + expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED); + done(); + }); + }); + }); - }); + test('should fails on publish a duplicated package', async (done) => { + const app = await initializeServer('publish.yaml'); + await publishVersion(app, 'publish.yaml', 'foo', '1.0.0'); + return publishVersion(app, 'publish.yaml', 'foo', '1.0.0') + .expect(HTTP_STATUS.CONFLICT) + .then((response) => { + console.log('response.body', response.body); + expect(response.body.error).toEqual(API_ERROR.PACKAGE_EXIST); + done(); + }); + }); + describe('unpublish a package', () => { + let app; - test('should fails on publish a duplicated package', async (done) => { - const app = await initializeServer('publish.yaml'); - await publishVersion(app, 'publish.yaml', 'foo', '1.0.0'); - return publishVersion(app, 'publish.yaml', 'foo', '1.0.0') - .expect(HTTP_STATUS.CONFLICT) - .then(response => { - console.log("response.body", response.body); - expect(response.body.error).toEqual(API_ERROR.PACKAGE_EXIST); - done(); - }); - }); + beforeEach(async () => { + app = await initializeServer('publish.yaml'); + await publishVersion(app, 'publish.yaml', 'foo', '1.0.0'); + }); - describe('unpublish a package', () => { - let app; - - beforeEach(async () => { - app = await initializeServer('publish.yaml'); - await publishVersion(app, 'publish.yaml', 'foo', '1.0.0'); - }) - - test('should unpublish a package', () => { - - }) - }); - - describe('star a package', () => { - - }); + test('should unpublish a package', () => {}); + }); + describe('star a package', () => {}); }); diff --git a/packages/api/test/integration/user.spec.ts b/packages/api/test/integration/user.spec.ts index 0cfda7552..f54258be3 100644 --- a/packages/api/test/integration/user.spec.ts +++ b/packages/api/test/integration/user.spec.ts @@ -1,237 +1,216 @@ import supertest from 'supertest'; import { HTTP_STATUS, API_ERROR } from '@verdaccio/commons-api'; -import {HEADERS, HEADER_TYPE, API_MESSAGE} from '@verdaccio/dev-commons'; -import {$RequestExtend, $ResponseExtend} from "@verdaccio/dev-types"; -import {getBadRequest, getConflict, getUnauthorized} from "@verdaccio/commons-api/lib"; -import _ from "lodash"; +import { HEADERS, HEADER_TYPE, API_MESSAGE } from '@verdaccio/dev-commons'; +import { $RequestExtend, $ResponseExtend } from '@verdaccio/dev-types'; +import { getBadRequest, getConflict, getUnauthorized } from '@verdaccio/commons-api/lib'; +import _ from 'lodash'; import { initializeServer } from './_helper'; -const mockApiJWTmiddleware = jest.fn(() => - (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: 'test', groups: [], real_groups: []}; - _next(); - } -); +const mockApiJWTmiddleware = jest.fn(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: 'test', groups: [], real_groups: [] }; + _next(); +}); const mockAuthenticate = jest.fn(() => (_name, _password, callback): void => { - return callback(null, ['all']); - } -); + return callback(null, ['all']); +}); const mockAddUser = jest.fn(() => (_name, _password, callback): void => { - return callback(getConflict(API_ERROR.USERNAME_ALREADY_REGISTERED)); - } -); + return callback(getConflict(API_ERROR.USERNAME_ALREADY_REGISTERED)); +}); jest.mock('@verdaccio/auth', () => ({ - getApiToken: () => 'token', - Auth: class { - apiJWTmiddleware() { - return mockApiJWTmiddleware(); - } - allow_access (_d, f_, cb) { - cb(null, true); - } - add_user (name, password, callback) { - mockAddUser()(name, password, callback); - } - authenticate (_name, _password, callback) { - mockAuthenticate()(_name, _password, callback); - } - } + getApiToken: () => 'token', + Auth: class { + apiJWTmiddleware() { + return mockApiJWTmiddleware(); + } + allow_access(_d, f_, cb) { + cb(null, true); + } + add_user(name, password, callback) { + mockAddUser()(name, password, callback); + } + authenticate(_name, _password, callback) { + mockAuthenticate()(_name, _password, callback); + } + }, })); describe('user', () => { - const credentials = { name: 'test', password: 'test' }; + const credentials = { name: 'test', password: 'test' }; - test('should test add a new user', async (done) => { - mockApiJWTmiddleware.mockImplementationOnce(() => - (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: undefined}; - _next(); - } - ); + test('should test add a new user', async (done) => { + mockApiJWTmiddleware.mockImplementationOnce(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: undefined }; + _next(); + }); - mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => { - return callback(null, true); - } - ); - supertest(await initializeServer('user.yaml')) - .put(`/-/user/org.couchdb.user:newUser`) - .send({ - name: 'newUser', - password: 'newUser' - }) - .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { - if (err) { - return done(err); - } - expect(res.body.ok).toBeDefined(); - expect(res.body.token).toBeDefined(); - const token = res.body.token; - expect(typeof token).toBe('string'); - expect(res.body.ok).toMatch(`user 'newUser' created`); - done(); - }); - }); + mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => { + return callback(null, true); + }); + supertest(await initializeServer('user.yaml')) + .put(`/-/user/org.couchdb.user:newUser`) + .send({ + name: 'newUser', + password: 'newUser', + }) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.CREATED) + .end(function (err, res) { + if (err) { + return done(err); + } + expect(res.body.ok).toBeDefined(); + expect(res.body.token).toBeDefined(); + const token = res.body.token; + expect(typeof token).toBe('string'); + expect(res.body.ok).toMatch(`user 'newUser' created`); + done(); + }); + }); - test('should test fails on add a existing user with login', async (done) => { - mockApiJWTmiddleware.mockImplementationOnce(() => - (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: undefined}; - _next(); - } - ); - supertest(await initializeServer('user.yaml')) - .put('/-/user/org.couchdb.user:jotaNew') - .send(credentials) - .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.CONFLICT) - .end(function(err, res) { - if (err) { - return done(err); - } - expect(res.body.error).toBeDefined(); - expect(res.body.error).toMatch(API_ERROR.USERNAME_ALREADY_REGISTERED); - done(); - }); - }); + test('should test fails on add a existing user with login', async (done) => { + mockApiJWTmiddleware.mockImplementationOnce(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: undefined }; + _next(); + }); + supertest(await initializeServer('user.yaml')) + .put('/-/user/org.couchdb.user:jotaNew') + .send(credentials) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.CONFLICT) + .end(function (err, res) { + if (err) { + return done(err); + } + expect(res.body.error).toBeDefined(); + expect(res.body.error).toMatch(API_ERROR.USERNAME_ALREADY_REGISTERED); + done(); + }); + }); - test('should log in as existing user', async (done) => { - supertest(await initializeServer('user.yaml')) - .put(`/-/user/org.couchdb.user:${credentials.name}`) - .send(credentials) - .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.CREATED) - .end((err, res) => { - if (err) { - return done(err); - } + test('should log in as existing user', async (done) => { + supertest(await initializeServer('user.yaml')) + .put(`/-/user/org.couchdb.user:${credentials.name}`) + .send(credentials) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.CREATED) + .end((err, res) => { + if (err) { + return done(err); + } - expect(res.body).toBeTruthy(); - expect(res.body.ok).toMatch(`you are authenticated as \'${credentials.name}\'`); - done(); - }); - }); + expect(res.body).toBeTruthy(); + expect(res.body.ok).toMatch(`you are authenticated as \'${credentials.name}\'`); + done(); + }); + }); - test('should test fails add a new user with missing name', async (done) => { - mockApiJWTmiddleware.mockImplementationOnce(() => - (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: undefined }; - _next(); - } - ); - mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => { - return callback(getBadRequest(API_ERROR.USERNAME_PASSWORD_REQUIRED)); - } - ); - const credentialsShort = _.cloneDeep(credentials); - delete credentialsShort.name; + test('should test fails add a new user with missing name', async (done) => { + mockApiJWTmiddleware.mockImplementationOnce(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: undefined }; + _next(); + }); + mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => { + return callback(getBadRequest(API_ERROR.USERNAME_PASSWORD_REQUIRED)); + }); + const credentialsShort = _.cloneDeep(credentials); + delete credentialsShort.name; - supertest(await initializeServer('user.yaml')) - .put(`/-/user/org.couchdb.user:${credentials.name}`) - .send(credentialsShort) - .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.BAD_REQUEST) - .end(function(err, res) { - if (err) { - return done(err); - } + supertest(await initializeServer('user.yaml')) + .put(`/-/user/org.couchdb.user:${credentials.name}`) + .send(credentialsShort) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.BAD_REQUEST) + .end(function (err, res) { + if (err) { + return done(err); + } - expect(res.body.error).toBeDefined(); - expect(res.body.error).toMatch(API_ERROR.USERNAME_PASSWORD_REQUIRED); - done(); - }); - }); + expect(res.body.error).toBeDefined(); + expect(res.body.error).toMatch(API_ERROR.USERNAME_PASSWORD_REQUIRED); + done(); + }); + }); - test('should test fails add a new user with missing password', async (done) => { - mockApiJWTmiddleware.mockImplementationOnce(() => - (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: undefined}; - _next(); - } - ); - const credentialsShort = _.cloneDeep(credentials); - delete credentialsShort.password; + test('should test fails add a new user with missing password', async (done) => { + mockApiJWTmiddleware.mockImplementationOnce(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: undefined }; + _next(); + }); + const credentialsShort = _.cloneDeep(credentials); + delete credentialsShort.password; - supertest(await initializeServer('user.yaml')) - .put(`/-/user/org.couchdb.user:${credentials.name}`) - .send(credentialsShort) - .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.BAD_REQUEST) - .end(function(err, res) { - if (err) { - return done(err); - } + supertest(await initializeServer('user.yaml')) + .put(`/-/user/org.couchdb.user:${credentials.name}`) + .send(credentialsShort) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.BAD_REQUEST) + .end(function (err, res) { + if (err) { + return done(err); + } - expect(res.body.error).toBeDefined(); - // FIXME: message is not 100% accurate - // eslint-disable-next-line new-cap - expect(res.body.error).toMatch(API_ERROR.PASSWORD_SHORT()); - done(); - }); - }); + expect(res.body.error).toBeDefined(); + // FIXME: message is not 100% accurate + // eslint-disable-next-line new-cap + expect(res.body.error).toMatch(API_ERROR.PASSWORD_SHORT()); + done(); + }); + }); - test('should test fails add a new user with wrong password', async (done) => { - mockApiJWTmiddleware.mockImplementationOnce(() => - (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: 'test'}; - _next(); - } - ); - mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => { - return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD)); - } - ); - const credentialsShort = _.cloneDeep(credentials); - credentialsShort.password = 'failPassword'; + test('should test fails add a new user with wrong password', async (done) => { + mockApiJWTmiddleware.mockImplementationOnce(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: 'test' }; + _next(); + }); + mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => { + return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD)); + }); + const credentialsShort = _.cloneDeep(credentials); + credentialsShort.password = 'failPassword'; - supertest(await initializeServer('user.yaml')) - .put('/-/user/org.couchdb.user:test') - .send(credentialsShort) - .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.UNAUTHORIZED) - .end(function(err, res) { - if (err) { - return done(err); - } + supertest(await initializeServer('user.yaml')) + .put('/-/user/org.couchdb.user:test') + .send(credentialsShort) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.UNAUTHORIZED) + .end(function (err, res) { + if (err) { + return done(err); + } - expect(res.body.error).toBeDefined(); - expect(res.body.error).toMatch(API_ERROR.BAD_USERNAME_PASSWORD); - done(); - }); - }); + expect(res.body.error).toBeDefined(); + expect(res.body.error).toMatch(API_ERROR.BAD_USERNAME_PASSWORD); + done(); + }); + }); - test('should be able to logout an user', async (done) => { - mockApiJWTmiddleware.mockImplementationOnce(() => - (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: 'test'}; - _next(); - } - ); - mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => { - return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD)); - } - ); - const credentialsShort = _.cloneDeep(credentials); - credentialsShort.password = 'failPassword'; + test('should be able to logout an user', async (done) => { + mockApiJWTmiddleware.mockImplementationOnce(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: 'test' }; + _next(); + }); + mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => { + return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD)); + }); + const credentialsShort = _.cloneDeep(credentials); + credentialsShort.password = 'failPassword'; - supertest(await initializeServer('user.yaml')) - .delete('/-/user/token/someSecretToken') - .send(credentialsShort) - .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.OK) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body.ok).toMatch(API_MESSAGE.LOGGED_OUT); - done(); - }); - }); + supertest(await initializeServer('user.yaml')) + .delete('/-/user/token/someSecretToken') + .send(credentialsShort) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.OK) + .end(function (err, res) { + if (err) { + return done(err); + } + expect(res.body.ok).toMatch(API_MESSAGE.LOGGED_OUT); + done(); + }); + }); }); diff --git a/packages/api/test/integration/whoami.spec.ts b/packages/api/test/integration/whoami.spec.ts index 0435dd8d3..2f01d08fb 100644 --- a/packages/api/test/integration/whoami.spec.ts +++ b/packages/api/test/integration/whoami.spec.ts @@ -1,53 +1,50 @@ import supertest from 'supertest'; import { HTTP_STATUS } from '@verdaccio/commons-api'; -import { HEADERS} from '@verdaccio/dev-commons'; -import {$RequestExtend, $ResponseExtend} from "@verdaccio/dev-types"; -import {initializeServer } from './_helper'; +import { HEADERS } from '@verdaccio/dev-commons'; +import { $RequestExtend, $ResponseExtend } from '@verdaccio/dev-types'; +import { initializeServer } from './_helper'; -const mockApiJWTmiddleware = jest.fn(() => - (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: 'foo', groups: [], real_groups: []} - _next(); - } -); +const mockApiJWTmiddleware = jest.fn(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: 'foo', groups: [], real_groups: [] }; + _next(); +}); jest.mock('@verdaccio/auth', () => ({ - Auth: class { - apiJWTmiddleware() { - return mockApiJWTmiddleware(); - } - allow_access (_d, f_, cb) { - cb(null, true) - } - } + Auth: class { + apiJWTmiddleware() { + return mockApiJWTmiddleware(); + } + allow_access(_d, f_, cb) { + cb(null, true); + } + }, })); describe('whoami', () => { - test.skip('should test referer /whoami endpoint', async (done) => { - return supertest(await initializeServer('whoami.yaml')) - .get('/whoami') - .set('referer', 'whoami') - .expect(HTTP_STATUS.OK) - .end(done); - }); + test.skip('should test referer /whoami endpoint', async (done) => { + return supertest(await initializeServer('whoami.yaml')) + .get('/whoami') + .set('referer', 'whoami') + .expect(HTTP_STATUS.OK) + .end(done); + }); - test.skip('should test no referer /whoami endpoint', async (done) => { - return supertest(await initializeServer('whoami.yaml')) - .get('/whoami') - .expect(HTTP_STATUS.NOT_FOUND) - .end(done); - }); + test.skip('should test no referer /whoami endpoint', async (done) => { + return supertest(await initializeServer('whoami.yaml')) + .get('/whoami') + .expect(HTTP_STATUS.NOT_FOUND) + .end(done); + }); - - test('should return the logged username', async () => { - return supertest(await initializeServer('whoami.yaml')) - .get('/-/whoami') - .set('Accept', HEADERS.JSON) - .expect('Content-Type', HEADERS.JSON_CHARSET) - .expect(HTTP_STATUS.OK) - .then(response => { - expect(response.body.username).toEqual('foo'); - }); - }); + test('should return the logged username', async () => { + return supertest(await initializeServer('whoami.yaml')) + .get('/-/whoami') + .set('Accept', HEADERS.JSON) + .expect('Content-Type', HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.OK) + .then((response) => { + expect(response.body.username).toEqual('foo'); + }); + }); }); diff --git a/packages/api/test/unit/publish.spec.ts b/packages/api/test/unit/publish.spec.ts index b1b59cdca..113fb1a07 100644 --- a/packages/api/test/unit/publish.spec.ts +++ b/packages/api/test/unit/publish.spec.ts @@ -3,9 +3,7 @@ import { addVersion, uploadPackageTarball, removeTarball, unPublishPackage, publ const REVISION_MOCK = '15-e53a77096b0ee33e'; -require('@verdaccio/logger').setup([ - { type: 'stdout', format: 'pretty', level: 'info' } -]); +require('@verdaccio/logger').setup([{ type: 'stdout', format: 'pretty', level: 'info' }]); describe('Publish endpoints - add a tag', () => { let req; @@ -28,7 +26,7 @@ describe('Publish endpoints - add a tag', () => { next = jest.fn(); }); - test('should add a version', done => { + test('should add a version', (done) => { const storage = { addVersion: (packageName, version, body, tag, cb) => { expect(packageName).toEqual(req.params.package); @@ -47,7 +45,7 @@ describe('Publish endpoints - add a tag', () => { expect(next).toHaveBeenLastCalledWith({ ok: 'package published' }); }); - test('when failed to add a version', done => { + test('when failed to add a version', (done) => { const storage = { addVersion: (packageName, version, body, tag, cb) => { const error = { @@ -82,7 +80,7 @@ describe('Publish endpoints - upload package tarball', () => { pipe: jest.fn(), on: jest.fn(), }; - res = { status: jest.fn(), locals: { report_error: jest.fn() }}; + res = { status: jest.fn(), locals: { report_error: jest.fn() } }; next = jest.fn(); }); @@ -127,7 +125,7 @@ describe('Publish endpoints - delete tarball', () => { next = jest.fn(); }); - test('should delete tarball successfully', done => { + test('should delete tarball successfully', (done) => { const storage = { removeTarball(packageName, filename, revision, cb) { expect(packageName).toEqual(req.params.package); @@ -144,7 +142,7 @@ describe('Publish endpoints - delete tarball', () => { expect(next).toHaveBeenCalledWith({ ok: 'tarball removed' }); }); - test('failed while deleting the tarball', done => { + test('failed while deleting the tarball', (done) => { const error = { message: 'deletion failed', }; @@ -179,7 +177,7 @@ describe('Publish endpoints - un-publish package', () => { next = jest.fn(); }); - test('should un-publish package successfully', done => { + test('should un-publish package successfully', (done) => { const storage = { removePackage(packageName, cb) { expect(packageName).toEqual(req.params.package); @@ -194,7 +192,7 @@ describe('Publish endpoints - un-publish package', () => { expect(next).toHaveBeenCalledWith({ ok: 'package removed' }); }); - test('un-publish failed', done => { + test('un-publish failed', (done) => { const error = { message: 'un-publish failed', }; diff --git a/packages/auth/src/auth.ts b/packages/auth/src/auth.ts index c049b446f..0043289b5 100644 --- a/packages/auth/src/auth.ts +++ b/packages/auth/src/auth.ts @@ -2,27 +2,15 @@ import _ from 'lodash'; import { NextFunction } from 'express'; import { VerdaccioError, getBadRequest, getInternalError, getForbidden } from '@verdaccio/commons-api'; -import {API_ERROR, SUPPORT_ERRORS, TOKEN_BASIC, TOKEN_BEARER} from '@verdaccio/dev-commons'; +import { API_ERROR, SUPPORT_ERRORS, TOKEN_BASIC, TOKEN_BEARER } from '@verdaccio/dev-commons'; import { loadPlugin } from '@verdaccio/loaders'; import { aesEncrypt, signPayload } from '@verdaccio/utils'; -import { - getDefaultPlugins, - createAnonymousRemoteUser, - convertPayloadToBase64, - createRemoteUser, -} from '@verdaccio/utils'; +import { getDefaultPlugins, createAnonymousRemoteUser, convertPayloadToBase64, createRemoteUser } from '@verdaccio/utils'; import { getMatchedPackagesSpec } from '@verdaccio/utils'; import { Config, Logger, Callback, IPluginAuth, RemoteUser, JWTSignOptions, Security, AuthPluginPackage, AllowAccess, PackageAccess } from '@verdaccio/types'; import { $RequestExtend, $ResponseExtend, IAuth, AESPayload } from '@verdaccio/dev-types'; -import { - getMiddlewareCredentials, - getSecurity, - verifyJWTPayload, - parseBasicPayload, - parseAuthTokenHeader, - isAuthHeaderValid, - isAESLegacy } from "./utils"; +import { getMiddlewareCredentials, getSecurity, verifyJWTPayload, parseBasicPayload, parseAuthTokenHeader, isAuthHeaderValid, isAESLegacy } from './utils'; /* eslint-disable @typescript-eslint/no-var-requires */ const LoggerApi = require('@verdaccio/logger'); @@ -47,17 +35,12 @@ class Auth implements IAuth { logger: this.logger, }; - return loadPlugin>( - config, - config.auth, - pluginOptions, - (plugin: IPluginAuth): boolean => { - const { authenticate, allow_access, allow_publish } = plugin; + return loadPlugin>(config, config.auth, pluginOptions, (plugin: IPluginAuth): boolean => { + const { authenticate, allow_access, allow_publish } = plugin; - // @ts-ignore - return authenticate || allow_access || allow_publish; - } - ); + // @ts-ignore + return authenticate || allow_access || allow_publish; + }); } private _applyDefaultPlugins(): void { @@ -65,39 +48,33 @@ class Auth implements IAuth { } public changePassword(username: string, password: string, newPassword: string, cb: Callback): void { - const validPlugins = _.filter(this.plugins, plugin => _.isFunction(plugin.changePassword)); + const validPlugins = _.filter(this.plugins, (plugin) => _.isFunction(plugin.changePassword)); - if (_.isEmpty(validPlugins)) { - return cb( - getInternalError(SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE)); - } + if (_.isEmpty(validPlugins)) { + return cb(getInternalError(SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE)); + } - for (const plugin of validPlugins) { - if (_.isNil(plugin) || _.isFunction(plugin.changePassword) === false) { - this.logger.trace('auth plugin does not implement changePassword, trying next one'); - continue; - } else { - this.logger.trace({username}, 'updating password for @{username}'); - plugin.changePassword!( - username, - password, - newPassword, - (err, profile): void => { - if (err) { - this.logger.error( - {username, err}, - `An error has been produced + for (const plugin of validPlugins) { + if (_.isNil(plugin) || _.isFunction(plugin.changePassword) === false) { + this.logger.trace('auth plugin does not implement changePassword, trying next one'); + continue; + } else { + this.logger.trace({ username }, 'updating password for @{username}'); + plugin.changePassword!(username, password, newPassword, (err, profile): void => { + if (err) { + this.logger.error( + { username, err }, + `An error has been produced updating the password for @{username}. Error: @{err.message}` - ); - return cb(err); - } + ); + return cb(err); + } - this.logger.trace({username}, 'updated password for @{username} was successful'); - return cb(null, profile); - } - ); - } - } + this.logger.trace({ username }, 'updated password for @{username} was successful'); + return cb(null, profile); + }); + } + } } public authenticate(username: string, password: string, cb: Callback): void { @@ -111,7 +88,7 @@ class Auth implements IAuth { } self.logger.trace({ username }, 'authenticating @{username}'); - plugin.authenticate(username, password, function(err, groups): void { + plugin.authenticate(username, password, function (err, groups): void { if (err) { self.logger.trace({ username, err }, 'authenticating for user @{username} failed. Error: @{err.message}'); return cb(err); @@ -159,7 +136,7 @@ class Auth implements IAuth { next(); } else { // p.add_user() execution - plugin[method](user, password, function(err, ok): void { + plugin[method](user, password, function (err, ok): void { if (err) { self.logger.trace({ user, err: err.message }, 'the user @{user} could not being added. Error: @{err}'); return cb(err); @@ -191,7 +168,7 @@ class Auth implements IAuth { return next(); } - plugin.allow_access!(user, pkg, function(err, ok: boolean): void { + plugin.allow_access!(user, pkg, function (err, ok: boolean): void { if (err) { self.logger.trace({ packageName, err }, 'forbidden access for @{packageName}. Error: @{err.message}'); return callback(err); @@ -216,28 +193,24 @@ class Auth implements IAuth { this.logger.trace({ packageName }, 'allow unpublish for @{packageName} plugin does not implement allow_unpublish'); continue; } else { - plugin.allow_unpublish!( - user, - pkg, - (err, ok: boolean): void => { - if (err) { - this.logger.trace({ packageName }, 'forbidden publish for @{packageName}, it will fallback on unpublish permissions'); - return callback(err); - } - - if (_.isNil(ok) === true) { - this.logger.trace({ packageName }, 'we bypass unpublish for @{packageName}, publish will handle the access'); - // @ts-ignore - // eslint-disable-next-line - return this.allow_publish(...arguments); - } - - if (ok) { - this.logger.trace({ packageName }, 'allowed unpublish for @{packageName}'); - return callback(null, ok); - } + plugin.allow_unpublish!(user, pkg, (err, ok: boolean): void => { + if (err) { + this.logger.trace({ packageName }, 'forbidden publish for @{packageName}, it will fallback on unpublish permissions'); + return callback(err); } - ); + + if (_.isNil(ok) === true) { + this.logger.trace({ packageName }, 'we bypass unpublish for @{packageName}, publish will handle the access'); + // @ts-ignore + // eslint-disable-next-line + return this.allow_publish(...arguments); + } + + if (ok) { + this.logger.trace({ packageName }, 'allowed unpublish for @{packageName}'); + return callback(null, ok); + } + }); } } } @@ -294,7 +267,7 @@ class Auth implements IAuth { return (req: $RequestExtend, res: $ResponseExtend, _next: NextFunction): void => { req.pause(); - const next = function(err: VerdaccioError | void): void { + const next = function (err: VerdaccioError | void): void { req.resume(); // uncomment this to reject users with bad auth headers // return _next.apply(null, arguments) @@ -342,19 +315,15 @@ class Auth implements IAuth { // this should happen when client tries to login with an existing user const credentials = convertPayloadToBase64(token).toString(); const { user, password } = parseBasicPayload(credentials) as AESPayload; - this.authenticate( - user, - password, - (err, user): void => { - if (!err) { - req.remote_user = user; - next(); - } else { - req.remote_user = createAnonymousRemoteUser(); - next(err); - } + this.authenticate(user, password, (err, user): void => { + if (!err) { + req.remote_user = user; + next(); + } else { + req.remote_user = createAnonymousRemoteUser(); + next(err); } - ); + }); } else { // jwt handler const credentials: any = getMiddlewareCredentials(security, secret, authorization); @@ -373,19 +342,15 @@ class Auth implements IAuth { const credentials: any = getMiddlewareCredentials(security, secret, authorization); if (credentials) { const { user, password } = credentials; - this.authenticate( - user, - password, - (err, user): void => { - if (!err) { - req.remote_user = user; - next(); - } else { - req.remote_user = createAnonymousRemoteUser(); - next(err); - } + this.authenticate(user, password, (err, user): void => { + if (!err) { + req.remote_user = user; + next(); + } else { + req.remote_user = createAnonymousRemoteUser(); + next(err); } - ); + }); } else { // we force npm client to ask again with basic authentication return next(getBadRequest(API_ERROR.BAD_AUTH_HEADER)); diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts index 3d27f740e..308a3becf 100644 --- a/packages/auth/src/index.ts +++ b/packages/auth/src/index.ts @@ -1,2 +1,2 @@ -export { Auth } from './auth' +export { Auth } from './auth'; export * from './utils'; diff --git a/packages/auth/src/utils.ts b/packages/auth/src/utils.ts index 0bdd38438..ef6c1bf9d 100644 --- a/packages/auth/src/utils.ts +++ b/packages/auth/src/utils.ts @@ -1,127 +1,118 @@ -import {Config, RemoteUser, Security} from "@verdaccio/types"; -import {AuthMiddlewarePayload, AuthTokenHeader, BasicPayload, IAuthWebUI} from "@verdaccio/dev-types"; -import _ from "lodash"; -import {HTTP_STATUS, TOKEN_BASIC, TOKEN_BEARER} from "@verdaccio/dev-commons"; -import { - aesDecrypt, - buildUserBuffer, - convertPayloadToBase64, - createAnonymousRemoteUser, - defaultSecurity, - ErrorCode, - verifyPayload -} from "@verdaccio/utils"; +import { Config, RemoteUser, Security } from '@verdaccio/types'; +import { AuthMiddlewarePayload, AuthTokenHeader, BasicPayload, IAuthWebUI } from '@verdaccio/dev-types'; +import _ from 'lodash'; +import { HTTP_STATUS, TOKEN_BASIC, TOKEN_BEARER } from '@verdaccio/dev-commons'; +import { aesDecrypt, buildUserBuffer, convertPayloadToBase64, createAnonymousRemoteUser, defaultSecurity, ErrorCode, verifyPayload } from '@verdaccio/utils'; export function parseAuthTokenHeader(authorizationHeader: string): AuthTokenHeader { - const parts = authorizationHeader.split(' '); - const [scheme, token] = parts; + const parts = authorizationHeader.split(' '); + const [scheme, token] = parts; - return { scheme, token }; + return { scheme, token }; } export function parseAESCredentials(authorizationHeader: string, secret: string) { - const { scheme, token } = parseAuthTokenHeader(authorizationHeader); + const { scheme, token } = parseAuthTokenHeader(authorizationHeader); - // basic is deprecated and should not be enforced - if (scheme.toUpperCase() === TOKEN_BASIC.toUpperCase()) { - const credentials = convertPayloadToBase64(token).toString(); + // basic is deprecated and should not be enforced + if (scheme.toUpperCase() === TOKEN_BASIC.toUpperCase()) { + const credentials = convertPayloadToBase64(token).toString(); - return credentials; - } else if (scheme.toUpperCase() === TOKEN_BEARER.toUpperCase()) { - const tokenAsBuffer = convertPayloadToBase64(token); - const credentials = aesDecrypt(tokenAsBuffer, secret).toString('utf8'); + return credentials; + } else if (scheme.toUpperCase() === TOKEN_BEARER.toUpperCase()) { + const tokenAsBuffer = convertPayloadToBase64(token); + const credentials = aesDecrypt(tokenAsBuffer, secret).toString('utf8'); - return credentials; - } + return credentials; + } } export function getMiddlewareCredentials(security: Security, secret: string, authorizationHeader: string): AuthMiddlewarePayload { - if (isAESLegacy(security)) { - const credentials = parseAESCredentials(authorizationHeader, secret); - if (!credentials) { - return; - } + if (isAESLegacy(security)) { + const credentials = parseAESCredentials(authorizationHeader, secret); + if (!credentials) { + return; + } - const parsedCredentials = parseBasicPayload(credentials); - if (!parsedCredentials) { - return; - } + const parsedCredentials = parseBasicPayload(credentials); + if (!parsedCredentials) { + return; + } - return parsedCredentials; - } - const { scheme, token } = parseAuthTokenHeader(authorizationHeader); + return parsedCredentials; + } + const { scheme, token } = parseAuthTokenHeader(authorizationHeader); - if (_.isString(token) && scheme.toUpperCase() === TOKEN_BEARER.toUpperCase()) { - return verifyJWTPayload(token, secret); - } + if (_.isString(token) && scheme.toUpperCase() === TOKEN_BEARER.toUpperCase()) { + return verifyJWTPayload(token, secret); + } } - export function isAESLegacy(security: Security): boolean { - const { legacy, jwt } = security.api; + const { legacy, jwt } = security.api; - return _.isNil(legacy) === false && _.isNil(jwt) && legacy === true; + return _.isNil(legacy) === false && _.isNil(jwt) && legacy === true; } export async function getApiToken(auth: IAuthWebUI, config: Config, remoteUser: RemoteUser, aesPassword: string): Promise { - const security: Security = getSecurity(config); + const security: Security = getSecurity(config); - if (isAESLegacy(security)) { - // fallback all goes to AES encryption - return await new Promise((resolve): void => { - resolve(auth.aesEncrypt(buildUserBuffer(remoteUser.name as string, aesPassword)).toString('base64')); - }); - } - // i am wiling to use here _.isNil but flow does not like it yet. - const { jwt } = security.api; + if (isAESLegacy(security)) { + // fallback all goes to AES encryption + return await new Promise((resolve): void => { + resolve(auth.aesEncrypt(buildUserBuffer(remoteUser.name as string, aesPassword)).toString('base64')); + }); + } + // i am wiling to use here _.isNil but flow does not like it yet. + const { jwt } = security.api; - if (jwt?.sign) { - return await auth.jwtEncrypt(remoteUser, jwt.sign); - } - return await new Promise((resolve): void => { - resolve(auth.aesEncrypt(buildUserBuffer(remoteUser.name as string, aesPassword)).toString('base64')); - }); + if (jwt?.sign) { + return await auth.jwtEncrypt(remoteUser, jwt.sign); + } + return await new Promise((resolve): void => { + resolve(auth.aesEncrypt(buildUserBuffer(remoteUser.name as string, aesPassword)).toString('base64')); + }); } export function getSecurity(config: Config): Security { - if (_.isNil(config.security) === false) { - return _.merge(defaultSecurity, config.security); - } + if (_.isNil(config.security) === false) { + return _.merge(defaultSecurity, config.security); + } - return defaultSecurity; + return defaultSecurity; } export const expireReasons: string[] = ['JsonWebTokenError', 'TokenExpiredError']; export function verifyJWTPayload(token: string, secret: string): RemoteUser { - try { - const payload: RemoteUser = verifyPayload(token, secret); + try { + const payload: RemoteUser = verifyPayload(token, secret); - return payload; - } catch (error) { - // #168 this check should be removed as soon AES encrypt is removed. - if (expireReasons.includes(error.name)) { - // it might be possible the jwt configuration is enabled and - // old tokens fails still remains in usage, thus - // we return an anonymous user to force log in. - return createAnonymousRemoteUser(); - } - throw ErrorCode.getCode(HTTP_STATUS.UNAUTHORIZED, error.message); - } + return payload; + } catch (error) { + // #168 this check should be removed as soon AES encrypt is removed. + if (expireReasons.includes(error.name)) { + // it might be possible the jwt configuration is enabled and + // old tokens fails still remains in usage, thus + // we return an anonymous user to force log in. + return createAnonymousRemoteUser(); + } + throw ErrorCode.getCode(HTTP_STATUS.UNAUTHORIZED, error.message); + } } export function isAuthHeaderValid(authorization: string): boolean { - return authorization.split(' ').length === 2; + return authorization.split(' ').length === 2; } export function parseBasicPayload(credentials: string): BasicPayload { - const index = credentials.indexOf(':'); - if (index < 0) { - return; - } + const index = credentials.indexOf(':'); + if (index < 0) { + return; + } - const user: string = credentials.slice(0, index); - const password: string = credentials.slice(index + 1); + const user: string = credentials.slice(0, index); + const password: string = credentials.slice(index + 1); - return { user, password }; + return { user, password }; } diff --git a/packages/auth/test/auth-utils.spec.ts b/packages/auth/test/auth-utils.spec.ts index 4cf150675..aba2a7eb0 100644 --- a/packages/auth/test/auth-utils.spec.ts +++ b/packages/auth/test/auth-utils.spec.ts @@ -1,11 +1,10 @@ -import path from "path"; +import path from 'path'; import _ from 'lodash'; -import { Auth } from '../src'; -import {CHARACTER_ENCODING, TOKEN_BEARER} from '@verdaccio/dev-commons'; +import { CHARACTER_ENCODING, TOKEN_BEARER } from '@verdaccio/dev-commons'; import { configExample } from '@verdaccio/mock'; -import {Config as AppConfig } from '@verdaccio/config'; -import {setup} from '@verdaccio/logger'; +import { Config as AppConfig } from '@verdaccio/config'; +import { setup } from '@verdaccio/logger'; import { buildUserBuffer, @@ -17,17 +16,13 @@ import { parseConfigFile, createAnonymousRemoteUser, createRemoteUser, - signPayload + signPayload, } from '@verdaccio/utils'; - import { IAuth } from '@verdaccio/dev-types'; -import {Config, Security, RemoteUser} from '@verdaccio/types'; -import { - getMiddlewareCredentials, - getApiToken, - verifyJWTPayload, - getSecurity } from '../src' +import { Config, Security, RemoteUser } from '@verdaccio/types'; +import { Auth } from '../src'; +import { getMiddlewareCredentials, getApiToken, verifyJWTPayload, getSecurity } from '../src'; setup([]); @@ -38,7 +33,6 @@ const parseConfigurationFile = (conf) => { return path.join(__dirname, `./partials/config/${format}/security/${name}.${format}`); }; - describe('Auth utilities', () => { jest.setTimeout(20000); @@ -49,7 +43,7 @@ describe('Auth utilities', () => { function getConfig(configFileName: string, secret: string) { const conf = parseConfigFile(parseConfigurationSecurityFile(configFileName)); // @ts-ignore - const secConf= _.merge(configExample(), conf); + const secConf = _.merge(configExample(), conf); secConf.secret = secret; const config: Config = new AppConfig(secConf); @@ -62,7 +56,8 @@ describe('Auth utilities', () => { password: string, secret = '12345', methodToSpy: string, - methodNotBeenCalled: string): Promise { + methodNotBeenCalled: string + ): Promise { const config: Config = getConfig(configFileName, secret); const auth: IAuth = new Auth(config); // @ts-ignore @@ -72,7 +67,7 @@ describe('Auth utilities', () => { const user: RemoteUser = { name: username, real_groups: [], - groups: [] + groups: [], }; const token = await getApiToken(auth, config, user, password); expect(spy).toHaveBeenCalled(); @@ -100,56 +95,49 @@ describe('Auth utilities', () => { describe('getApiToken test', () => { test('should sign token with aes and security missing', async () => { - const token = await signCredentials('security-missing', - 'test', 'test', '1234567', 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials('security-missing', 'test', 'test', '1234567', 'aesEncrypt', 'jwtEncrypt'); verifyAES(token, 'test', 'test', '1234567'); expect(_.isString(token)).toBeTruthy(); }); test('should sign token with aes and security empty', async () => { - const token = await signCredentials('security-empty', - 'test', 'test', '123456', 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials('security-empty', 'test', 'test', '123456', 'aesEncrypt', 'jwtEncrypt'); verifyAES(token, 'test', 'test', '123456'); expect(_.isString(token)).toBeTruthy(); }); test('should sign token with aes', async () => { - const token = await signCredentials('security-basic', - 'test', 'test', '123456', 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials('security-basic', 'test', 'test', '123456', 'aesEncrypt', 'jwtEncrypt'); verifyAES(token, 'test', 'test', '123456'); expect(_.isString(token)).toBeTruthy(); }); test('should sign token with legacy and jwt disabled', async () => { - const token = await signCredentials('security-no-legacy', - 'test', 'test', 'x8T#ZCx=2t', 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials('security-no-legacy', 'test', 'test', 'x8T#ZCx=2t', 'aesEncrypt', 'jwtEncrypt'); expect(_.isString(token)).toBeTruthy(); verifyAES(token, 'test', 'test', 'x8T#ZCx=2t'); }); test('should sign token with legacy enabled and jwt enabled', async () => { - const token = await signCredentials('security-jwt-legacy-enabled', - 'test', 'test', 'secret', 'jwtEncrypt', 'aesEncrypt'); + const token = await signCredentials('security-jwt-legacy-enabled', 'test', 'test', 'secret', 'jwtEncrypt', 'aesEncrypt'); verifyJWT(token, 'test', 'test', 'secret'); expect(_.isString(token)).toBeTruthy(); }); test('should sign token with jwt enabled', async () => { - const token = await signCredentials('security-jwt', - 'test', 'test', 'secret', 'jwtEncrypt', 'aesEncrypt'); + const token = await signCredentials('security-jwt', 'test', 'test', 'secret', 'jwtEncrypt', 'aesEncrypt'); expect(_.isString(token)).toBeTruthy(); verifyJWT(token, 'test', 'test', 'secret'); }); test('should sign with jwt whether legacy is disabled', async () => { - const token = await signCredentials('security-legacy-disabled', - 'test', 'test', 'secret', 'jwtEncrypt', 'aesEncrypt'); + const token = await signCredentials('security-legacy-disabled', 'test', 'test', 'secret', 'jwtEncrypt', 'aesEncrypt'); expect(_.isString(token)).toBeTruthy(); verifyJWT(token, 'test', 'test', 'secret'); @@ -158,7 +146,7 @@ describe('Auth utilities', () => { describe('getAuthenticatedMessage test', () => { test('should sign token with jwt enabled', () => { - expect(getAuthenticatedMessage('test')).toBe('you are authenticated as \'test\''); + expect(getAuthenticatedMessage('test')).toBe("you are authenticated as 'test'"); }); }); @@ -168,8 +156,7 @@ describe('Auth utilities', () => { const secret = 'secret'; const user = 'test'; const pass = 'test'; - const token = await signCredentials('security-legacy', - user, pass, secret, 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials('security-legacy', user, pass, secret, 'aesEncrypt', 'jwtEncrypt'); const config: Config = getConfig('security-legacy', secret); const security: Security = getSecurity(config); const credentials = getMiddlewareCredentials(security, secret, `Bearer ${token}`); @@ -197,8 +184,7 @@ describe('Auth utilities', () => { test.concurrent('should return empty credential wrong secret key', async () => { const secret = 'secret'; - const token = await signCredentials('security-legacy', - 'test', 'test', secret, 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials('security-legacy', 'test', 'test', secret, 'aesEncrypt', 'jwtEncrypt'); const config: Config = getConfig('security-legacy', secret); const security: Security = getSecurity(config); const credentials = getMiddlewareCredentials(security, 'BAD_SECRET', buildToken(TOKEN_BEARER, token)); @@ -207,8 +193,7 @@ describe('Auth utilities', () => { test.concurrent('should return empty credential wrong scheme', async () => { const secret = 'secret'; - const token = await signCredentials('security-legacy', - 'test', 'test', secret, 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials('security-legacy', 'test', 'test', secret, 'aesEncrypt', 'jwtEncrypt'); const config: Config = getConfig('security-legacy', secret); const security: Security = getSecurity(config); const credentials = getMiddlewareCredentials(security, secret, buildToken('BAD_SCHEME', token)); @@ -267,8 +252,7 @@ describe('Auth utilities', () => { const secret = 'secret'; const user = 'test'; const config: Config = getConfig('security-jwt', secret); - const token = await signCredentials('security-jwt', - user, 'secretTest', secret, 'jwtEncrypt', 'aesEncrypt'); + const token = await signCredentials('security-jwt', user, 'secretTest', secret, 'jwtEncrypt', 'aesEncrypt'); const security: Security = getSecurity(config); const credentials = getMiddlewareCredentials(security, secret, buildToken(TOKEN_BEARER, token)); expect(credentials).toBeDefined(); diff --git a/packages/auth/test/auth.spec.ts b/packages/auth/test/auth.spec.ts index 62dda5ee9..bc6a97358 100644 --- a/packages/auth/test/auth.spec.ts +++ b/packages/auth/test/auth.spec.ts @@ -29,18 +29,16 @@ describe('AuthTest', () => { expect(auth).toBeDefined(); const callback = jest.fn(); - const groups = [ "test" ]; + const groups = ['test']; auth.authenticate('foo', 'bar', callback); expect(callback).toHaveBeenCalledTimes(1); - expect(callback).toHaveBeenCalledWith(null, - {"groups": - [ - "test", ROLES.$ALL, ROLES.$AUTH, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_AUTH, ROLES.ALL], - "name": 'foo', - "real_groups": groups - }); + expect(callback).toHaveBeenCalledWith(null, { + groups: ['test', ROLES.$ALL, ROLES.$AUTH, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_AUTH, ROLES.ALL], + name: 'foo', + real_groups: groups, + }); }); test('should be a fail on login', () => { @@ -71,7 +69,7 @@ describe('AuthTest', () => { let index = 0; // as defined by https://developer.mozilla.org/en-US/docs/Glossary/Falsy - for (const value of [ false, 0, "", null, undefined, NaN ]) { + for (const value of [false, 0, '', null, undefined, NaN]) { // @ts-ignore auth.authenticate(null, value, callback); const call = callback.mock.calls[index++]; @@ -88,8 +86,8 @@ describe('AuthTest', () => { const callback = jest.fn(); - for (const value of [ true, 1, "test", { } ]) { - expect(function ( ) { + for (const value of [true, 1, 'test', {}]) { + expect(function () { // @ts-ignore auth.authenticate(null, value, callback); }).toThrow(TypeError); @@ -104,7 +102,7 @@ describe('AuthTest', () => { expect(auth).toBeDefined(); const callback = jest.fn(); - const value = [ ]; + const value = []; // @ts-ignore auth.authenticate(null, value, callback); @@ -122,7 +120,7 @@ describe('AuthTest', () => { const callback = jest.fn(); let index = 0; - for (const value of [ [ "" ], [ "1" ], [ "0" ], ["000"] ]) { + for (const value of [[''], ['1'], ['0'], ['000']]) { // @ts-ignore auth.authenticate(null, value, callback); const call = callback.mock.calls[index++]; @@ -131,5 +129,5 @@ describe('AuthTest', () => { } }); }); - }) + }); }); diff --git a/packages/auth/test/helper/plugin.ts b/packages/auth/test/helper/plugin.ts index 608256f9f..00d61e5d4 100644 --- a/packages/auth/test/helper/plugin.ts +++ b/packages/auth/test/helper/plugin.ts @@ -1,20 +1,20 @@ import path from 'path'; -import { configExample as config }from '@verdaccio/mock'; +import { configExample as config } from '@verdaccio/mock'; export const authProfileConf = config({ auth: { - [`${path.join(__dirname, '../partials/plugin/authenticate.success')}`]: { } - } + [`${path.join(__dirname, '../partials/plugin/authenticate.success')}`]: {}, + }, }); export const authPluginFailureConf = config({ auth: { - [`${path.join(__dirname, '../partials/plugin/authenticate.fail')}`]: { } - } + [`${path.join(__dirname, '../partials/plugin/authenticate.fail')}`]: {}, + }, }); export const authPluginPassThrougConf = config({ auth: { - [`${path.join(__dirname, '../partials/plugin/authenticate.passthroug')}`]: { } - } + [`${path.join(__dirname, '../partials/plugin/authenticate.passthroug')}`]: {}, + }, }); diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 52ce0f2c7..6b9c40e18 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -6,14 +6,14 @@ import { bgYellow, bgRed } from 'kleur'; import { setup, logger } from '@verdaccio/logger'; -import infoCommand from "./commands/info"; -import initProgram from "./commands/init"; -import {isVersionValid, MIN_NODE_VERSION} from "./utils"; +import infoCommand from './commands/info'; +import initProgram from './commands/init'; +import { isVersionValid, MIN_NODE_VERSION } from './utils'; const isRootUser = process.getuid && process.getuid() === 0; if (isRootUser) { - global.console.warn(bgYellow().red('*** WARNING: Verdaccio doesn\'t need superuser privileges. Don\'t run it under root! ***')); + global.console.warn(bgYellow().red("*** WARNING: Verdaccio doesn't need superuser privileges. Don't run it under root! ***")); } if (isVersionValid()) { @@ -38,20 +38,22 @@ const isHelp = commander.args.length !== 0; if (commander.info) { infoCommand(); -} else if (fallbackConfig) { +} else if (fallbackConfig) { // handling "verdaccio [config]" case if "-c" is missing in command line commander.config = commander.args.pop(); - initProgram(commander, pkgVersion, pkgName); + initProgram(commander, pkgVersion, pkgName); } else if (isHelp) { commander.help(); } else { - initProgram(commander, pkgVersion, pkgName); + initProgram(commander, pkgVersion, pkgName); } -process.on('uncaughtException', function(err) { - logger.fatal( { - err: err, - }, - 'uncaught exception, please report (https://github.com/verdaccio/verdaccio/issues) this: \n@{err.stack}' ); +process.on('uncaughtException', function (err) { + logger.fatal( + { + err: err, + }, + 'uncaught exception, please report (https://github.com/verdaccio/verdaccio/issues) this: \n@{err.stack}' + ); process.exit(255); }); diff --git a/packages/cli/src/commands/info.ts b/packages/cli/src/commands/info.ts index 9fa17bb40..520d9f056 100644 --- a/packages/cli/src/commands/info.ts +++ b/packages/cli/src/commands/info.ts @@ -1,18 +1,18 @@ import envinfo from 'envinfo'; export default function infoCommand() { - // eslint-disable-next-line no-console - console.log('\nEnvironment Info:'); - (async () => { - const data = await envinfo.run({ - System: ['OS', 'CPU'], - Binaries: ['Node', 'Yarn', 'npm'], - Virtualization: ['Docker'], - Browsers: ['Chrome', 'Edge', 'Firefox', 'Safari'], - npmGlobalPackages: ['verdaccio'], - }); - // eslint-disable-next-line no-console - console.log(data); - process.exit(0); - })(); + // eslint-disable-next-line no-console + console.log('\nEnvironment Info:'); + (async () => { + const data = await envinfo.run({ + System: ['OS', 'CPU'], + Binaries: ['Node', 'Yarn', 'npm'], + Virtualization: ['Docker'], + Browsers: ['Chrome', 'Edge', 'Firefox', 'Safari'], + npmGlobalPackages: ['verdaccio'], + }); + // eslint-disable-next-line no-console + console.log(data); + process.exit(0); + })(); } diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index a6f1c8ad7..95159ecdf 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -1,44 +1,44 @@ -import path from "path"; +import path from 'path'; import _ from 'lodash'; -import { parseConfigFile} from "@verdaccio/utils"; -import { findConfigFile } from "@verdaccio/config"; +import { parseConfigFile } from '@verdaccio/utils'; +import { findConfigFile } from '@verdaccio/config'; import { logger, createLogger } from '@verdaccio/logger'; -import {startVerdaccio, listenDefaultCallback} from "@verdaccio/node-api"; +import { startVerdaccio, listenDefaultCallback } from '@verdaccio/node-api'; export const DEFAULT_PROCESS_NAME: string = 'verdaccio'; -export default function initProgram(commander, pkgVersion, pkgName) { - // FIXME: we need to log before the setup is being applied - // const initLogger = createLogger(); - const cliListener = commander.listen; - let configPathLocation; - let verdaccioConfiguration; - try { - configPathLocation = findConfigFile(commander.config); - verdaccioConfiguration = parseConfigFile(configPathLocation); - const { web, https, self_path } = verdaccioConfiguration; +export default function initProgram(commander, pkgVersion, pkgName) { + // FIXME: we need to log before the setup is being applied + // const initLogger = createLogger(); + const cliListener = commander.listen; + let configPathLocation; + let verdaccioConfiguration; + try { + configPathLocation = findConfigFile(commander.config); + verdaccioConfiguration = parseConfigFile(configPathLocation); + const { web, https, self_path } = verdaccioConfiguration; - process.title = web?.title || DEFAULT_PROCESS_NAME; + process.title = web?.title || DEFAULT_PROCESS_NAME; - // note: self_path is only being used by @verdaccio/storage , not really useful and migth be removed soon - if (!self_path) { - verdaccioConfiguration = _.assign({}, verdaccioConfiguration, { - self_path: path.resolve(configPathLocation) - }); - } + // note: self_path is only being used by @verdaccio/storage , not really useful and migth be removed soon + if (!self_path) { + verdaccioConfiguration = _.assign({}, verdaccioConfiguration, { + self_path: path.resolve(configPathLocation), + }); + } - if (!https) { - verdaccioConfiguration = _.assign({}, verdaccioConfiguration, { - https: {enable: false} - }); - } + if (!https) { + verdaccioConfiguration = _.assign({}, verdaccioConfiguration, { + https: { enable: false }, + }); + } - // initLogger.warn({file: configPathLocation}, 'config file - @{file}'); + // initLogger.warn({file: configPathLocation}, 'config file - @{file}'); - startVerdaccio(verdaccioConfiguration, cliListener, configPathLocation, pkgVersion, pkgName, listenDefaultCallback); - } catch (err) { - // initLogger.fatal({file: configPathLocation, err: err}, 'cannot open config file @{file}: @{!err.message}'); - process.exit(1); - } + startVerdaccio(verdaccioConfiguration, cliListener, configPathLocation, pkgVersion, pkgName, listenDefaultCallback); + } catch (err) { + // initLogger.fatal({file: configPathLocation, err: err}, 'cannot open config file @{file}: @{!err.message}'); + process.exit(1); + } } diff --git a/packages/cli/src/utils.ts b/packages/cli/src/utils.ts index c4d12d663..86ea71db9 100644 --- a/packages/cli/src/utils.ts +++ b/packages/cli/src/utils.ts @@ -1,5 +1,5 @@ -import semver from "semver"; +import semver from 'semver'; export const MIN_NODE_VERSION = '6.9.0'; -export const isVersionValid = () => semver.satisfies(process.version, `>=${MIN_NODE_VERSION}`) === false +export const isVersionValid = () => semver.satisfies(process.version, `>=${MIN_NODE_VERSION}`) === false; diff --git a/packages/cli/test/cli-test.spec.ts b/packages/cli/test/cli-test.spec.ts index d07cd0e06..f37b634e3 100644 --- a/packages/cli/test/cli-test.spec.ts +++ b/packages/cli/test/cli-test.spec.ts @@ -1,3 +1,3 @@ describe('cli test', () => { - test.todo('write some test for this module'); + test.todo('write some test for this module'); }); diff --git a/packages/commons/src/helpers/pkg.ts b/packages/commons/src/helpers/pkg.ts index d17fd45b7..e1bb2c273 100644 --- a/packages/commons/src/helpers/pkg.ts +++ b/packages/commons/src/helpers/pkg.ts @@ -1,58 +1,57 @@ -import { Package } from "@verdaccio/types"; +import { Package } from '@verdaccio/types'; export interface DistTags { - [key: string]: string; + [key: string]: string; } -export function generatePackageMetadata(pkgName: string, version = '1.0.0', distTags: DistTags = {['latest']: version}): Package { - // @ts-ignore - return { - "_id": pkgName, - "name": pkgName, - "dist-tags": { - ...distTags - }, - "versions": { - [version]: { - "name": pkgName, - "version": version, - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - - ], - "author": { - "name": "User NPM", - "email": "user@domain.com" - }, - "license": "ISC", - "dependencies": { - "verdaccio": "^2.7.2" - }, - "readme": "# test", - "readmeFilename": "README.md", - "_id": `${pkgName}@${version}`, - "_npmVersion": "5.5.1", - "_npmUser": { - 'name': 'foo', - }, - "dist": { - "integrity": "sha512-6gHiERpiDgtb3hjqpQH5\/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==", - "shasum": "2c03764f651a9f016ca0b7620421457b619151b9", // pragma: allowlist secret - "tarball": `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz` - } - } - }, - "readme": "# test", - "_attachments": { - [`${pkgName}-${version}.tgz`]: { - "content_type": "application\/octet-stream", - "data": "H4sIAAAAAAAAE+2W32vbMBDH85y\/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo\/\/79KPeQsnIw5KUDX\/9IOvurLuz\/DHSjK\/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1aW8eML+Vv10m9oF\/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0ScCdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI\/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yoEHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS\/pLQe+D+FIv\/agIWI6GX66kFuIhT+1gDjrp\/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0\/jWiAK8OcMjt8MW3OlfQppcuhhQ6k+2OgkK2Q8DssFPi\/IHpU9fz3\/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6\/f88f\/Pu47zomiPk2Lv\/dOv8h+P\/34\/D\/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=", - "length": 512 - } - } - } +export function generatePackageMetadata(pkgName: string, version = '1.0.0', distTags: DistTags = { ['latest']: version }): Package { + // @ts-ignore + return { + _id: pkgName, + name: pkgName, + 'dist-tags': { + ...distTags, + }, + versions: { + [version]: { + name: pkgName, + version: version, + description: '', + main: 'index.js', + scripts: { + test: 'echo "Error: no test specified" && exit 1', + }, + keywords: [], + author: { + name: 'User NPM', + email: 'user@domain.com', + }, + license: 'ISC', + dependencies: { + verdaccio: '^2.7.2', + }, + readme: '# test', + readmeFilename: 'README.md', + _id: `${pkgName}@${version}`, + _npmVersion: '5.5.1', + _npmUser: { + name: 'foo', + }, + dist: { + integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + shasum: '2c03764f651a9f016ca0b7620421457b619151b9', // pragma: allowlist secret + tarball: `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz`, + }, + }, + }, + readme: '# test', + _attachments: { + [`${pkgName}-${version}.tgz`]: { + content_type: 'application/octet-stream', + data: + 'H4sIAAAAAAAAE+2W32vbMBDH85y/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo//79KPeQsnIw5KUDX/9IOvurLuz/DHSjK/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1aW8eML+Vv10m9oF/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0ScCdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yoEHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS/pLQe+D+FIv/agIWI6GX66kFuIhT+1gDjrp/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0/jWiAK8OcMjt8MW3OlfQppcuhhQ6k+2OgkK2Q8DssFPi/IHpU9fz3/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6/f88f/Pu47zomiPk2Lv/dOv8h+P/34/D/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=', + length: 512, + }, + }, + }; } diff --git a/packages/config/src/config-path.ts b/packages/config/src/config-path.ts index fc2919b40..f5166be0f 100644 --- a/packages/config/src/config-path.ts +++ b/packages/config/src/config-path.ts @@ -14,12 +14,12 @@ const WIN = 'win'; const WIN32 = 'win32'; // eslint-disable-next-line const pkgJSON = { - name: 'verdaccio' + name: 'verdaccio', }; export type SetupDirectory = { path: string; - type: string + type: string; }; /** @@ -84,13 +84,16 @@ function updateStorageLinks(configLocation, defaultConfig): string { } function getConfigPaths(): 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[]); + const listPaths: SetupDirectory[] = [getXDGDirectory(), getWindowsDirectory(), getRelativeDefaultDirectory(), getOldDirectory()].reduce(function ( + acc, + currentValue: any + ): SetupDirectory[] { + if (_.isUndefined(currentValue) === false) { + acc.push(currentValue); + } + return acc; + }, + [] as SetupDirectory[]); return listPaths; } diff --git a/packages/config/src/config.ts b/packages/config/src/config.ts index 61f778bf7..f89abb08d 100644 --- a/packages/config/src/config.ts +++ b/packages/config/src/config.ts @@ -8,7 +8,7 @@ import { uplinkSanityCheck, generateRandomHexString, getUserAgent, - isObject + isObject, } from '@verdaccio/utils'; import { APP_ERROR } from '@verdaccio/dev-commons'; @@ -61,7 +61,7 @@ class Config implements AppConfig { assert(_.isObject(config), APP_ERROR.CONFIG_NOT_VALID); // sanity check for strategic config properties - strategicConfigProps.forEach(function(x): void { + strategicConfigProps.forEach(function (x): void { if (self[x] == null) { self[x] = {}; } @@ -79,13 +79,11 @@ class Config implements AppConfig { this.packages = normalisePackageAccess(self.packages); // loading these from ENV if aren't in config - allowedEnvConfig.forEach( - (envConf): void => { - if (!(envConf in self)) { - self[envConf] = process.env[envConf] || process.env[envConf.toUpperCase()]; - } + allowedEnvConfig.forEach((envConf): void => { + if (!(envConf in self)) { + self[envConf] = process.env[envConf] || process.env[envConf.toUpperCase()]; } - ); + }); // unique identifier of self server (or a cluster), used to avoid loops // @ts-ignore diff --git a/packages/config/src/index.ts b/packages/config/src/index.ts index 6f216aca0..f2f9e9e4f 100644 --- a/packages/config/src/index.ts +++ b/packages/config/src/index.ts @@ -1,2 +1,2 @@ -export * from './config' -export * from './config-path' +export * from './config'; +export * from './config-path'; diff --git a/packages/config/test/config.spec.ts b/packages/config/test/config.spec.ts index 0137cfc5e..4879e057d 100644 --- a/packages/config/test/config.spec.ts +++ b/packages/config/test/config.spec.ts @@ -1,11 +1,11 @@ import path from 'path'; import _ from 'lodash'; -import { Config, readDefaultConfig } from '../src'; import { setup } from '@verdaccio/logger'; -import {DEFAULT_REGISTRY, DEFAULT_UPLINK, ROLES, WEB_TITLE} from '@verdaccio/dev-commons'; +import { DEFAULT_REGISTRY, DEFAULT_UPLINK, ROLES, WEB_TITLE } from '@verdaccio/dev-commons'; -import {parseConfigFile} from '@verdaccio/utils'; +import { parseConfigFile } from '@verdaccio/utils'; +import { Config, readDefaultConfig } from '../src'; setup([]); @@ -45,7 +45,7 @@ const checkDefaultConfPackages = (config) => { expect(config.packages['**'].publish).toBeDefined(); expect(config.packages['**'].publish).toContainEqual(ROLES.$AUTH); expect(config.packages['**'].proxy).toBeDefined(); - expect(config.packages['**'].proxy,).toContainEqual(DEFAULT_UPLINK); + expect(config.packages['**'].proxy).toContainEqual(DEFAULT_UPLINK); // uplinks expect(config.uplinks[DEFAULT_UPLINK]).toBeDefined(); expect(config.uplinks[DEFAULT_UPLINK].url).toEqual(DEFAULT_REGISTRY); @@ -70,7 +70,7 @@ const checkDefaultConfPackages = (config) => { }; describe('Config file', () => { - beforeAll(function() { + beforeAll(function () { /* eslint no-invalid-this: 0 */ // @ts-ignore this.config = new Config(parseConfigFile(resolveConf('default'))); @@ -96,9 +96,5 @@ describe('Config file', () => { }); }); - describe('Config file', () => { - - }); - + describe('Config file', () => {}); }); - diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts index 71b6acdbd..7dd6766f3 100644 --- a/packages/hooks/src/index.ts +++ b/packages/hooks/src/index.ts @@ -1 +1 @@ -export {handleNotify, notify, sendNotification } from './notify'; +export { handleNotify, notify, sendNotification } from './notify'; diff --git a/packages/hooks/src/notify-request.ts b/packages/hooks/src/notify-request.ts index 6bd49c609..1b8f37d7c 100644 --- a/packages/hooks/src/notify-request.ts +++ b/packages/hooks/src/notify-request.ts @@ -5,21 +5,19 @@ import { logger } from '@verdaccio/logger'; import { HTTP_STATUS } from '@verdaccio/commons-api'; export function notifyRequest(options: RequiredUriUrl, content): Promise { - return new Promise( - (resolve, reject): void => { - request(options, function(err, response, body): void { - if (err || response.statusCode >= HTTP_STATUS.BAD_REQUEST) { - const errorMessage = isNil(err) ? response.body : err.message; - logger.error({ errorMessage }, 'notify service has thrown an error: @{errorMessage}'); - reject(errorMessage); - } - logger.info({ content }, 'A notification has been shipped: @{content}'); - if (isNil(body) === false) { - logger.debug({ body }, ' body: @{body}'); - resolve(body); - } - reject(Error('body is missing')); - }); - } - ); + return new Promise((resolve, reject): void => { + request(options, function (err, response, body): void { + if (err || response.statusCode >= HTTP_STATUS.BAD_REQUEST) { + const errorMessage = isNil(err) ? response.body : err.message; + logger.error({ errorMessage }, 'notify service has thrown an error: @{errorMessage}'); + reject(errorMessage); + } + logger.info({ content }, 'A notification has been shipped: @{content}'); + if (isNil(body) === false) { + logger.debug({ body }, ' body: @{body}'); + resolve(body); + } + reject(Error('body is missing')); + }); + }); } diff --git a/packages/hooks/src/notify.ts b/packages/hooks/src/notify.ts index 71f5701ac..32383b86b 100644 --- a/packages/hooks/src/notify.ts +++ b/packages/hooks/src/notify.ts @@ -7,12 +7,7 @@ import { notifyRequest } from './notify-request'; type TemplateMetadata = Package & { publishedPackage: string }; -export function handleNotify( - metadata: Package, - notifyEntry, - remoteUser: RemoteUser, - publishedPackage: string -): Promise | void { +export function handleNotify(metadata: Package, notifyEntry, remoteUser: RemoteUser, publishedPackage: string): Promise | void { let regex; if (metadata.name && notifyEntry.packagePattern) { regex = new RegExp(notifyEntry.packagePattern, notifyEntry.packagePatternFlags || ''); @@ -21,7 +16,7 @@ export function handleNotify( } } - const template = Handlebars.compile(notifyEntry.content); + const template: HandlebarsTemplateDelegate = Handlebars.compile(notifyEntry.content); // don't override 'publisher' if package.json already has that /* eslint no-unused-vars: 0 */ /* eslint @typescript-eslint/no-unused-vars: 0 */ @@ -35,7 +30,7 @@ export function handleNotify( const options: OptionsWithUrl = { body: content, - url: '' + url: '', }; // provides fallback support, it's accept an Object {} and Array of {} @@ -65,34 +60,17 @@ export function handleNotify( return notifyRequest(options, content); } -export function sendNotification( - metadata: Package, - notify: any, - remoteUser: RemoteUser, - publishedPackage: string -): Promise { +export function sendNotification(metadata: Package, notify: Notification, remoteUser: RemoteUser, publishedPackage: string): Promise { return handleNotify(metadata, notify, remoteUser, publishedPackage) as Promise; } -export function notify( - metadata: Package, - config: Config, - remoteUser: RemoteUser, - publishedPackage: string -): Promise | void { +export function notify(metadata: Package, config: Config, remoteUser: RemoteUser, publishedPackage: string): Promise | 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 Notification, 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(); diff --git a/packages/hooks/test/notify.spec.ts b/packages/hooks/test/notify.spec.ts index 464c06b9e..e72616f93 100644 --- a/packages/hooks/test/notify.spec.ts +++ b/packages/hooks/test/notify.spec.ts @@ -1,14 +1,14 @@ -import {parseConfigFile} from '@verdaccio/utils'; +import { parseConfigFile } from '@verdaccio/utils'; import { setup } from '@verdaccio/logger'; -import {notify} from '../src'; -import {notifyRequest} from '../src/notify-request'; -import {parseConfigurationFile} from './__helper'; +import { notify } from '../src'; +import { notifyRequest } from '../src/notify-request'; +import { parseConfigurationFile } from './__helper'; setup([]); jest.mock('../src/notify-request', () => ({ - notifyRequest: jest.fn((options, content) => Promise.resolve([options, content])) + notifyRequest: jest.fn((options, content) => Promise.resolve([options, content])), })); const parseConfigurationNotifyFile = (name) => { @@ -20,24 +20,23 @@ const packagePatternNotificationConfig = parseConfigFile(parseConfigurationNotif const multiNotificationConfig = parseConfigFile(parseConfigurationNotifyFile('multiple.notify')); describe('Notifications:: Notify', () => { - beforeEach(() => { jest.clearAllMocks(); }); // FUTURE: we should add some sort of health check of all props, (not implemented yet) - test("should not fails if config is not provided", async () => { + test('should not fails if config is not provided', async () => { // @ts-ignore await notify({}, {}); expect(notifyRequest).toHaveBeenCalledTimes(0); }); - test("should send notification", async () => { + test('should send notification', async () => { const name = 'package'; // @ts-ignore - const response = await notify({name}, singleNotificationConfig, { name: 'foo'}, 'bar'); + const response = await notify({ name }, singleNotificationConfig, { name: 'foo' }, 'bar'); const [options, content] = response; expect(options.headers).toBeDefined(); @@ -48,39 +47,36 @@ describe('Notifications:: Notify', () => { expect(notifyRequest).toHaveBeenCalledTimes(1); }); - test("should send single header notification", async () => { + test('should send single header notification', async () => { // @ts-ignore - await notify({}, singleHeaderNotificationConfig, { name: 'foo'}, 'bar'); + await notify({}, singleHeaderNotificationConfig, { name: 'foo' }, 'bar'); expect(notifyRequest).toHaveBeenCalledTimes(1); }); - test("should send multiple notification", async () => { + test('should send multiple notification', async () => { // @ts-ignore - await notify({name}, multiNotificationConfig, { name: 'foo'}, 'bar'); + await notify({ name }, multiNotificationConfig, { name: 'foo' }, 'bar'); expect(notifyRequest).toHaveBeenCalled(); expect(notifyRequest).toHaveBeenCalledTimes(3); }); describe('packagePatternFlags', () => { - test("should send single notification with packagePatternFlags", async () => { + test('should send single notification with packagePatternFlags', async () => { const name = 'package'; // @ts-ignore - await notify({name}, packagePatternNotificationConfig, { name: 'foo'}, 'bar'); - + await notify({ name }, packagePatternNotificationConfig, { name: 'foo' }, 'bar'); expect(notifyRequest).toHaveBeenCalledTimes(1); }); - test("should not match on send single notification with packagePatternFlags", async () => { + test('should not match on send single notification with packagePatternFlags', async () => { const name = 'no-mach-name'; // @ts-ignore - await notify({name}, packagePatternNotificationConfig, { name: 'foo'}, 'bar'); + await notify({ name }, packagePatternNotificationConfig, { name: 'foo' }, 'bar'); expect(notifyRequest).toHaveBeenCalledTimes(0); }); - }) - - + }); }); diff --git a/packages/loaders/src/plugin-loader.ts b/packages/loaders/src/plugin-loader.ts index ab99a2fd6..c833c926c 100644 --- a/packages/loaders/src/plugin-loader.ts +++ b/packages/loaders/src/plugin-loader.ts @@ -46,13 +46,7 @@ function isES6(plugin): boolean { * @param {*} sanityCheck callback that check the shape that should fulfill the plugin * @return {Array} list of plugins */ -export function loadPlugin>( - config: Config, - pluginConfigs: any = {}, - params: any, - sanityCheck: any, - prefix: string = 'verdaccio' -): any[] { +export function loadPlugin>(config: Config, pluginConfigs: any = {}, params: any, sanityCheck: any, prefix: string = 'verdaccio'): any[] { return Object.keys(pluginConfigs).map( (pluginId: string): IPlugin => { let plugin; @@ -102,17 +96,17 @@ export function loadPlugin>( } if (!isValid(plugin)) { - logger.error({ content: pluginId }, "@{prefix}-@{content} plugin does not have the right code structure"); + 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}"); - } + 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)) { diff --git a/packages/loaders/test/plugin_loader.spec.ts b/packages/loaders/test/plugin_loader.spec.ts index a90e8398c..f64772db2 100644 --- a/packages/loaders/test/plugin_loader.spec.ts +++ b/packages/loaders/test/plugin_loader.spec.ts @@ -1,5 +1,5 @@ import path from 'path'; -import { setup } from '@verdaccio/logger'; +import { setup } from '@verdaccio/logger'; import { loadPlugin } from '../src/plugin-loader'; @@ -7,13 +7,13 @@ setup([]); describe('plugin loader', () => { const relativePath = path.join(__dirname, './partials/test-plugin-storage'); - const buildConf = name => { + const buildConf = (name) => { return { self_path: path.join(__dirname, './'), max_users: 0, auth: { - [`${relativePath}/${name}`]: {} - } + [`${relativePath}/${name}`]: {}, + }, }; }; @@ -45,7 +45,7 @@ describe('plugin loader', () => { loadPlugin(_config, _config.auth, {}, function (p) { return p.authenticate || p.allow_access || p.allow_publish; }); - } catch(e) { + } catch (e) { expect(e.message).toEqual(`"${relativePath}/invalid-plugin" plugin does not have the right code structure`); } }); @@ -57,7 +57,7 @@ describe('plugin loader', () => { loadPlugin(_config, _config.auth, {}, function (plugin) { return plugin.authenticate || plugin.allow_access || plugin.allow_publish; }); - } catch(err) { + } catch (err) { expect(err.message).toEqual(`sanity check has failed, "${relativePath}/invalid-plugin-sanity" is not a valid plugin`); } }); @@ -69,7 +69,7 @@ describe('plugin loader', () => { loadPlugin(_config, _config.auth, {}, function (plugin) { return plugin.authenticate || plugin.allow_access || plugin.allow_publish; }); - } catch(e) { + } catch (e) { expect(e.message).toMatch('plugin not found'); expect(e.message).toMatch('/partials/test-plugin-storage/invalid-package'); } @@ -78,5 +78,4 @@ describe('plugin loader', () => { test.todo('test middleware plugins'); test.todo('test storage plugins'); }); - }); diff --git a/packages/logger-prettify/src/formatter.ts b/packages/logger-prettify/src/formatter.ts index f1023b1c2..d38b3380e 100644 --- a/packages/logger-prettify/src/formatter.ts +++ b/packages/logger-prettify/src/formatter.ts @@ -3,9 +3,9 @@ import { inspect } from 'util'; import { white, red, green } from 'kleur'; import padLeft from 'pad-left'; -import {calculateLevel, LevelCode, levelsColors, subSystemLevels} from "./levels"; -import {formatLoggingDate, isObject, pad} from './utils'; -import {PrettyOptionsExtended} from "./types"; +import { calculateLevel, LevelCode, levelsColors, subSystemLevels } from './levels'; +import { formatLoggingDate, isObject, pad } from './utils'; +import { PrettyOptionsExtended } from './types'; let LEVEL_VALUE_MAX = 0; for (const l in levelsColors) { @@ -19,13 +19,12 @@ export interface ObjectTemplate { msg: string; sub?: string; [key: string]: string | number | object | null | void; -}; +} export function fillInMsgTemplate(msg, templateOptions: ObjectTemplate, colors): string { 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) { @@ -50,7 +49,7 @@ export function fillInMsgTemplate(msg, templateOptions: ObjectTemplate, colors): } return green(str); } - + // object, showHidden, depth, colors return inspect(str, undefined, null, colors); }); @@ -65,17 +64,14 @@ function getMessage(debugLevel, msg, sub, templateObjects, hasColors) { if (hasColors) { const logString = `${levelsColors[debugLevel](pad(debugLevel, LEVEL_VALUE_MAX))}${white(`${subSystemType} ${finalMessage}`)}`; - return padLeft(logString, logString.length + CUSTOM_PAD_LENGTH , ' '); + return padLeft(logString, logString.length + CUSTOM_PAD_LENGTH, ' '); } const logString = `${pad(debugLevel, LEVEL_VALUE_MAX)}${subSystemType} ${finalMessage}`; - return padLeft(logString, logString.length + CUSTOM_PAD_LENGTH , ' '); + return padLeft(logString, logString.length + CUSTOM_PAD_LENGTH, ' '); } -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); diff --git a/packages/logger-prettify/src/index.ts b/packages/logger-prettify/src/index.ts index 5c4be0780..37ae40e80 100644 --- a/packages/logger-prettify/src/index.ts +++ b/packages/logger-prettify/src/index.ts @@ -1,5 +1,5 @@ -import { printMessage } from "./formatter"; -import {PrettyOptionsExtended} from "./types"; +import { printMessage } from './formatter'; +import { PrettyOptionsExtended } from './types'; export type PrettyFactory = (param) => string; @@ -8,11 +8,11 @@ export type PrettyFactory = (param) => string; { messageKey: 'msg', levelFirst: true, prettyStamp: false } */ -module.exports = function prettyFactory (options: PrettyOptionsExtended): PrettyFactory { - // the break line must happens in the prettify component - const breakLike = '\n'; - return (inputData): string => { - // FIXME: review colors by default is true - return printMessage(inputData, options, true) + breakLike; - }; +module.exports = function prettyFactory(options: PrettyOptionsExtended): PrettyFactory { + // the break line must happens in the prettify component + const breakLike = '\n'; + return (inputData): string => { + // FIXME: review colors by default is true + return printMessage(inputData, options, true) + breakLike; + }; }; diff --git a/packages/logger-prettify/src/levels.ts b/packages/logger-prettify/src/levels.ts index 0b260f190..7f672fb6c 100644 --- a/packages/logger-prettify/src/levels.ts +++ b/packages/logger-prettify/src/levels.ts @@ -5,52 +5,52 @@ export type LogLevel = 'trace' | 'debug' | 'info' | 'http' | 'warn' | 'error' | export type LevelCode = number; export function calculateLevel(levelCode: LevelCode): LogLevel { - switch (true) { - case levelCode < 15: - return 'trace'; - case levelCode < 25: - return 'debug'; - case levelCode < 35: - return 'info'; - case levelCode == 35: - return 'http'; - case levelCode < 45: - return 'warn'; - case levelCode < 55: - return 'error'; - default: - return 'fatal'; - } + switch (true) { + case levelCode < 15: + return 'trace'; + case levelCode < 25: + return 'debug'; + case levelCode < 35: + return 'info'; + case levelCode == 35: + return 'http'; + case levelCode < 45: + return 'warn'; + case levelCode < 55: + return 'error'; + 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 = '---' + LEFT = '<--', + RIGHT = '-->', + EQUAL = '-=-', + NEUTRAL = '---', } export const subSystemLevels = { - color: { - 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, - }, + color: { + 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, + }, }; diff --git a/packages/logger-prettify/src/types.ts b/packages/logger-prettify/src/types.ts index afd004a18..e41d4b765 100644 --- a/packages/logger-prettify/src/types.ts +++ b/packages/logger-prettify/src/types.ts @@ -1,5 +1,5 @@ -import {PrettyOptions} from "pino"; +import { PrettyOptions } from 'pino'; -export interface PrettyOptionsExtended extends PrettyOptions { - prettyStamp: boolean; +export interface PrettyOptionsExtended extends PrettyOptions { + prettyStamp: boolean; } diff --git a/packages/logger-prettify/src/utils.ts b/packages/logger-prettify/src/utils.ts index 138c7e00a..2c40aadc1 100644 --- a/packages/logger-prettify/src/utils.ts +++ b/packages/logger-prettify/src/utils.ts @@ -5,15 +5,15 @@ import dayjs from 'dayjs'; 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 pad(str: string, max: number): string { - return padRight(str, max, ' '); + return padRight(str, max, ' '); } 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}`; } diff --git a/packages/logger-prettify/test/formatter.spec.ts b/packages/logger-prettify/test/formatter.spec.ts index 42ebbddca..857774244 100644 --- a/packages/logger-prettify/test/formatter.spec.ts +++ b/packages/logger-prettify/test/formatter.spec.ts @@ -1,213 +1,217 @@ -import {printMessage} from "../src/formatter"; -import {LevelCode} from "../src/levels"; +import { printMessage } from '../src/formatter'; +import { LevelCode } from '../src/levels'; jest.mock('dayjs', () => ({ - __esModule: true, - default: () => ({ - format: () => 'formatted-date' - }) + __esModule: true, + default: () => ({ + format: () => 'formatted-date', + }), })); describe('formatter', () => { - const prettyfierOptions = {messageKey: 'msg', levelFirst: true, prettyStamp: false}; - describe('printMessage', () => { - test('should display config file', () => { - const log = { - level: 40, - time: 1585410824129, - v: 1, - pid: 27029, - hostname: 'localhost', - file: '/Users/user/.config/verdaccio/config/config.yaml', - msg: 'config file - @{file}' - }; + const prettyfierOptions = { messageKey: 'msg', levelFirst: true, prettyStamp: false }; + describe('printMessage', () => { + test('should display config file', () => { + const log = { + level: 40, + time: 1585410824129, + v: 1, + pid: 27029, + hostname: 'localhost', + file: '/Users/user/.config/verdaccio/config/config.yaml', + msg: 'config file - @{file}', + }; - expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); - }); + expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); + }); - test('should display trace level', () => { - const log = { - level: 10, - foo: 'foo', - msg: '[trace] - @{foo}' - }; + test('should display trace level', () => { + const log = { + level: 10, + foo: 'foo', + msg: '[trace] - @{foo}', + }; - expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); - }); + expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); + }); - test('should display trace level with pretty stamp', () => { - const log = { - level: 10, - foo: 'foo', - time: 1585411248203, - msg: '[trace] - @{foo}' - }; + test('should display trace level with pretty stamp', () => { + const log = { + level: 10, + foo: 'foo', + time: 1585411248203, + msg: '[trace] - @{foo}', + }; - expect(printMessage(log, Object.assign({}, prettyfierOptions, { - prettyStamp: true - }))).toMatchSnapshot(); - }); + expect( + printMessage( + log, + Object.assign({}, prettyfierOptions, { + prettyStamp: true, + }) + ) + ).toMatchSnapshot(); + }); - test('should display a bytes request', () => { - const log = { - level: 35, - time: 1585411248203, - v: 1, - pid: 27029, - hostname: 'macbook-touch', - sub: 'in', - request: {method: 'GET', url: '/verdaccio'}, - user: null, - remoteIP: '127.0.0.1', - status: 200, - error: undefined, - bytes: {in: 0, out: 150186}, - msg: "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}', bytes: @{bytes.in}/@{bytes.out}" - }; + test('should display a bytes request', () => { + const log = { + level: 35, + time: 1585411248203, + v: 1, + pid: 27029, + hostname: 'macbook-touch', + sub: 'in', + request: { method: 'GET', url: '/verdaccio' }, + user: null, + remoteIP: '127.0.0.1', + status: 200, + error: undefined, + bytes: { in: 0, out: 150186 }, + msg: "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}', bytes: @{bytes.in}/@{bytes.out}", + }; - expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); - }); + expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); + }); - test('should display an error request', () => { - const log = { - level: 54, - time: 1585416029123, - v: 1, - pid: 30032, - hostname: 'macbook-touch', - sub: 'out', - err: { - type: 'Error', - message: 'getaddrinfo ENOTFOUND registry.fake.org', - stack: 'Error: getaddrinfo ENOTFOUND registry.fake.org\n' + - ' at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:60:26)', - errno: -3008, - code: 'ENOTFOUND', - syscall: 'getaddrinfo', - hostname: 'registry.fake.org' - }, - request: {method: 'GET', url: 'https://registry.fake.org/aaa'}, - status: 'ERR', - error: 'getaddrinfo ENOTFOUND registry.fake.org', - bytes: {in: 0, out: 0}, - msg: "@{!status}, req: '@{request.method} @{request.url}', error: @{!error}" - }; + test('should display an error request', () => { + const log = { + level: 54, + time: 1585416029123, + v: 1, + pid: 30032, + hostname: 'macbook-touch', + sub: 'out', + err: { + type: 'Error', + message: 'getaddrinfo ENOTFOUND registry.fake.org', + stack: 'Error: getaddrinfo ENOTFOUND registry.fake.org\n' + ' at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:60:26)', + errno: -3008, + code: 'ENOTFOUND', + syscall: 'getaddrinfo', + hostname: 'registry.fake.org', + }, + request: { method: 'GET', url: 'https://registry.fake.org/aaa' }, + status: 'ERR', + error: 'getaddrinfo ENOTFOUND registry.fake.org', + bytes: { in: 0, out: 0 }, + msg: "@{!status}, req: '@{request.method} @{request.url}', error: @{!error}", + }; - expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); - }); + expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); + }); - test('should display an fatal request', () => { - const log = { - level: 60, - time: 1585416029123, - v: 1, - pid: 30032, - hostname: 'macbook-touch', - sub: 'out', - err: { - type: 'Error', - message: 'fatal error', - stack: '....', - errno: -3008, - code: 'ENOTFOUND', - }, - request: {method: 'GET', url: 'https://registry.fake.org/aaa'}, - status: 'ERR', - error: 'fatal error', - bytes: {in: 0, out: 0}, - msg: "@{!status}, req: '@{request.method} @{request.url}', error: @{!error}" - }; + test('should display an fatal request', () => { + const log = { + level: 60, + time: 1585416029123, + v: 1, + pid: 30032, + hostname: 'macbook-touch', + sub: 'out', + err: { + type: 'Error', + message: 'fatal error', + stack: '....', + errno: -3008, + code: 'ENOTFOUND', + }, + request: { method: 'GET', url: 'https://registry.fake.org/aaa' }, + status: 'ERR', + error: 'fatal error', + bytes: { in: 0, out: 0 }, + msg: "@{!status}, req: '@{request.method} @{request.url}', error: @{!error}", + }; - expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); - }); + expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); + }); - test('should display a streaming request', () => { - const log = { - level: 35, - time: 1585411247920, - v: 1, - pid: 27029, - hostname: 'macbook-touch', - sub: 'out', - request: {method: 'GET', url: 'https://registry.npmjs.org/verdaccio'}, - status: 304, - msg: "@{!status}, req: '@{request.method} @{request.url}' (streaming)" - }; + test('should display a streaming request', () => { + const log = { + level: 35, + time: 1585411247920, + v: 1, + pid: 27029, + hostname: 'macbook-touch', + sub: 'out', + request: { method: 'GET', url: 'https://registry.npmjs.org/verdaccio' }, + status: 304, + msg: "@{!status}, req: '@{request.method} @{request.url}' (streaming)", + }; - expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); - }); + expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); + }); - test('should display version and http address', () => { - const log = { - level: 40, - time: 1585410824322, - v: 1, - pid: 27029, - hostname: 'macbook-touch', - addr: 'http://localhost:4873/', - version: 'verdaccio/5.0.0', - msg: 'http address - @{addr} - @{version}' - }; + test('should display version and http address', () => { + const log = { + level: 40, + time: 1585410824322, + v: 1, + pid: 27029, + hostname: 'macbook-touch', + addr: 'http://localhost:4873/', + version: 'verdaccio/5.0.0', + msg: 'http address - @{addr} - @{version}', + }; - expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); - }); + expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); + }); - test('should display custom log message', () => { - const level: LevelCode = 15; - const log = { - level, - something: 'foo', - msg: 'custom - @{something} - @{missingParam}' - }; + test('should display custom log message', () => { + const level: LevelCode = 15; + const log = { + level, + something: 'foo', + msg: 'custom - @{something} - @{missingParam}', + }; - expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); - }); + expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); + }); - // test('should handle undefined object', () => { - // const log = { - // level: 15, - // something: 'foo', - // msg: 'custom - @{something} - @{missingParam}' - // }; - // - // expect(printMessage(undefined, undefined, undefined)).toMatchSnapshot(); - // }); + // test('should handle undefined object', () => { + // const log = { + // level: 15, + // something: 'foo', + // msg: 'custom - @{something} - @{missingParam}' + // }; + // + // expect(printMessage(undefined, undefined, undefined)).toMatchSnapshot(); + // }); - test('should display a resource request', () => { - const log = { - level: 30, - time: 1585411247622, - v: 1, - pid: 27029, - hostname: 'macbook-touch', - sub: 'in', - req: { - id: undefined, - method: 'GET', - url: '/verdaccio', - headers: { - connection: 'keep-alive', - 'user-agent': 'npm/6.13.2 node/v13.1.0 darwin x64', - 'npm-in-ci': 'false', - 'npm-scope': '', - 'npm-session': 'afebb4748178bd4b', - referer: 'view verdaccio', - 'pacote-req-type': 'packument', - 'pacote-pkg-id': 'registry:verdaccio', - accept: 'application/json', - authorization: '', - 'if-none-match': '"fd6440ba2ad24681077664d8f969e5c3"', - 'accept-encoding': 'gzip,deflate', - host: 'localhost:4873' - }, - remoteAddress: '127.0.0.1', - remotePort: 57968, - }, - ip: '127.0.0.1', - msg: "@{ip} requested '@{req.method} @{req.url}'" - }; + test('should display a resource request', () => { + const log = { + level: 30, + time: 1585411247622, + v: 1, + pid: 27029, + hostname: 'macbook-touch', + sub: 'in', + req: { + id: undefined, + method: 'GET', + url: '/verdaccio', + headers: { + connection: 'keep-alive', + 'user-agent': 'npm/6.13.2 node/v13.1.0 darwin x64', + 'npm-in-ci': 'false', + 'npm-scope': '', + 'npm-session': 'afebb4748178bd4b', + referer: 'view verdaccio', + 'pacote-req-type': 'packument', + 'pacote-pkg-id': 'registry:verdaccio', + accept: 'application/json', + authorization: '', + 'if-none-match': '"fd6440ba2ad24681077664d8f969e5c3"', + 'accept-encoding': 'gzip,deflate', + host: 'localhost:4873', + }, + remoteAddress: '127.0.0.1', + remotePort: 57968, + }, + ip: '127.0.0.1', + msg: "@{ip} requested '@{req.method} @{req.url}'", + }; - expect(printMessage(log, prettyfierOptions, false)).toMatchSnapshot(); - }); - }); + expect(printMessage(log, prettyfierOptions, false)).toMatchSnapshot(); + }); + }); }); diff --git a/packages/logger-prettify/test/index.spec.ts b/packages/logger-prettify/test/index.spec.ts index 6ba7677ad..8d9be8180 100644 --- a/packages/logger-prettify/test/index.spec.ts +++ b/packages/logger-prettify/test/index.spec.ts @@ -1,18 +1,18 @@ import * as factory from '../src'; describe('prettyFactory', () => { - const prettyfierOptions = { messageKey: 'msg', levelFirst: true, prettyStamp: false }; - test('should return a function', () => { - expect(typeof factory['default']({})).toEqual('function') - }); + const prettyfierOptions = { messageKey: 'msg', levelFirst: true, prettyStamp: false }; + test('should return a function', () => { + expect(typeof factory['default']({})).toEqual('function'); + }); - test('should return a function', () => { - const log = { - level: 10, - foo: 'foo', - msg: '[trace] - @{foo}' - }; + test('should return a function', () => { + const log = { + level: 10, + foo: 'foo', + msg: '[trace] - @{foo}', + }; - expect(factory['default'](prettyfierOptions)(log)).toMatchSnapshot(); - }); + expect(factory['default'](prettyfierOptions)(log)).toMatchSnapshot(); + }); }); diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index f1c958568..a02d77261 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -1,2 +1 @@ export { setup, createLogger, logger } from './logger'; - diff --git a/packages/logger/src/logger.ts b/packages/logger/src/logger.ts index ad95018ca..6a9a5fa73 100644 --- a/packages/logger/src/logger.ts +++ b/packages/logger/src/logger.ts @@ -6,112 +6,112 @@ const DEFAULT_LOG_FORMAT = 'pretty'; export let logger; function getPrettifier() { - // TODO: this module can be loaded dynamically and allow custom formatting - return require('@verdaccio/logger-prettify'); + // TODO: this module can be loaded dynamically and allow custom formatting + return require('@verdaccio/logger-prettify'); } export type LogPlugin = { - dest: string; - options?: any[]; + dest: string; + options?: any[]; }; export type LogType = 'file' | 'stdout'; export type LogFormat = 'json' | 'pretty-timestamped' | 'pretty'; -export function createLogger(options = {}, - destination = pino.destination(1), - format: LogFormat = DEFAULT_LOG_FORMAT, - prettyPrintOptions = {}) { - if (_.isNil(format)) { - format = DEFAULT_LOG_FORMAT; - } +export function createLogger(options = {}, destination = pino.destination(1), format: LogFormat = DEFAULT_LOG_FORMAT, prettyPrintOptions = {}) { + if (_.isNil(format)) { + format = DEFAULT_LOG_FORMAT; + } - let pinoConfig = { - ...options, - customLevels: { - http: 35 - }, - serializers: { - err: pino.stdSerializers.err, - req: pino.stdSerializers.req, - res: pino.stdSerializers.res - }, - }; + let pinoConfig = { + ...options, + customLevels: { + http: 35, + }, + serializers: { + err: pino.stdSerializers.err, + req: pino.stdSerializers.req, + res: pino.stdSerializers.res, + }, + }; - if (format === DEFAULT_LOG_FORMAT || format !== 'json') { - pinoConfig = Object.assign({}, pinoConfig, { - prettyPrint: { - levelFirst: true, - prettyStamp: format === 'pretty-timestamped', - ...prettyPrintOptions - }, - prettifier: getPrettifier(), - } - ) - } + if (format === DEFAULT_LOG_FORMAT || format !== 'json') { + pinoConfig = Object.assign({}, pinoConfig, { + prettyPrint: { + levelFirst: true, + prettyStamp: format === 'pretty-timestamped', + ...prettyPrintOptions, + }, + prettifier: getPrettifier(), + }); + } - return pino(pinoConfig, destination); + return pino(pinoConfig, destination); } export function getLogger() { - if (_.isNil(logger)) { - console.warn('logger is not defined'); - return; - } + if (_.isNil(logger)) { + console.warn('logger is not defined'); + return; + } - return logger; + return logger; } const DEFAULT_LOGGER_CONF: LoggerConfigItem = { - type: 'stdout', - format: 'pretty', - level: 'http' + type: 'stdout', + format: 'pretty', + level: 'http', }; export type LoggerConfigItem = { - type?: LogType; - plugin?: LogPlugin; - format?: LogFormat; - path?: string; - level?: string; -} + type?: LogType; + plugin?: LogPlugin; + format?: LogFormat; + path?: string; + level?: string; +}; export type LoggerConfig = LoggerConfigItem[]; export function setup(options: LoggerConfig | LoggerConfigItem = [DEFAULT_LOGGER_CONF]) { - const isLegacyConf = _.isArray(options); - if (isLegacyConf) { - // FIXME: re-enable later - // console.warn("DEPRECATE: logs does not have multi-stream support anymore, please upgrade your logger configuration"); - } + const isLegacyConf = _.isArray(options); + if (isLegacyConf) { + // FIXME: re-enable later + // console.warn("DEPRECATE: logs does not have multi-stream support anymore, please upgrade your logger configuration"); + } - // backward compatible, pick only the first option - let loggerConfig = isLegacyConf ? options[0] : options; - if (!loggerConfig?.level) { - loggerConfig = Object.assign({}, loggerConfig, { - level: 'http' - }) - } + // backward compatible, pick only the first option + let loggerConfig = isLegacyConf ? options[0] : options; + if (!loggerConfig?.level) { + loggerConfig = Object.assign({}, loggerConfig, { + level: 'http', + }); + } - const pinoConfig = { level: loggerConfig.level }; - if (loggerConfig.type === 'file') { - logger = createLogger(pinoConfig, - pino.destination(loggerConfig.path), - loggerConfig.format); - } else if(loggerConfig.type === 'rotating-file') { - throw new Error('rotating-file type is not longer supported, consider use [logrotate] instead'); - } else { - logger = createLogger(pinoConfig, pino.destination(1), loggerConfig.format); - } + const pinoConfig = { level: loggerConfig.level }; + if (loggerConfig.type === 'file') { + logger = createLogger(pinoConfig, pino.destination(loggerConfig.path), loggerConfig.format); + } else if (loggerConfig.type === 'rotating-file') { + throw new Error('rotating-file type is not longer supported, consider use [logrotate] instead'); + } else { + logger = createLogger(pinoConfig, pino.destination(1), loggerConfig.format); + } - process.on('uncaughtException', pino.final(logger, (err, finalLogger) => { - finalLogger.fatal(err, 'uncaughtException'); - process.exit(1); - })); + process.on( + 'uncaughtException', + pino.final(logger, (err, finalLogger) => { + finalLogger.fatal(err, 'uncaughtException'); + process.exit(1); + }) + ); - // @ts-ignore - process.on('unhandledRejection', pino.final(logger, (err, finalLogger) => { - finalLogger.fatal(err, 'uncaughtException'); - process.exit(1); - })); + // @ts-ignore + process.on( + 'unhandledRejection', + pino.final(logger, (err, finalLogger) => { + finalLogger.fatal(err, 'uncaughtException'); + process.exit(1); + }) + ); } diff --git a/packages/logger/test/logger.spec.ts b/packages/logger/test/logger.spec.ts index c935253d1..4300a0fdc 100644 --- a/packages/logger/test/logger.spec.ts +++ b/packages/logger/test/logger.spec.ts @@ -1,15 +1,16 @@ -import { logger, setup } from "../src"; - +import { logger, setup } from '../src'; describe('logger', () => { - test('dsadasd', () => { - const spyOn = jest.spyOn( process.stdout, 'write'); - setup([{ - level: 'info' - }]); + test('dsadasd', () => { + const spyOn = jest.spyOn(process.stdout, 'write'); + setup([ + { + level: 'info', + }, + ]); - logger.info({packageName: 'test'} , `publishing or updating a new version for @{packageName}`); + logger.info({ packageName: 'test' }, `publishing or updating a new version for @{packageName}`); - // expect(spyOn).toHaveBeenCalledTimes(2); - }); + // expect(spyOn).toHaveBeenCalledTimes(2); + }); }); diff --git a/packages/middleware/src/middleware.ts b/packages/middleware/src/middleware.ts index f34b2a2fc..fe11df23c 100644 --- a/packages/middleware/src/middleware.ts +++ b/packages/middleware/src/middleware.ts @@ -1,4 +1,3 @@ - import _ from 'lodash'; import { @@ -7,17 +6,17 @@ import { getVersionFromTarball, isObject, stringToMD5, - ErrorCode + ErrorCode, } from '@verdaccio/utils'; import { API_ERROR, HEADER_TYPE, HEADERS, HTTP_STATUS, TOKEN_BASIC, TOKEN_BEARER } from '@verdaccio/dev-commons'; import { $ResponseExtend, $RequestExtend, $NextFunctionVer, IAuth } from '@verdaccio/dev-types'; import { Config, Package, RemoteUser } from '@verdaccio/types'; import { logger } from '@verdaccio/logger'; import { VerdaccioError } from '@verdaccio/commons-api'; -import {HttpError} from "http-errors"; +import { HttpError } from 'http-errors'; export function match(regexp: RegExp): any { - return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer, value: string): void { + return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer, value: string): void { if (regexp.exec(value)) { next(); } else { @@ -65,7 +64,7 @@ export function validatePackage(req: $RequestExtend, res: $ResponseExtend, next: } export function media(expect: string | null): any { - return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { if (req.headers[HEADER_TYPE.CONTENT_TYPE] !== expect) { next(ErrorCode.getCode(HTTP_STATUS.UNSUPPORTED_MEDIA, 'wrong content-type, expect: ' + expect + ', got: ' + req.headers[HEADER_TYPE.CONTENT_TYPE])); } else { @@ -90,7 +89,7 @@ export function expectJson(req: $RequestExtend, res: $ResponseExtend, next: $Nex } export function antiLoop(config: Config): Function { - return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { if (req.headers.via != null) { const arr = req.headers.via.split(','); @@ -106,14 +105,14 @@ export function antiLoop(config: Config): Function { } export function allow(auth: IAuth): Function { - return function(action: string): Function { - return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + return function (action: string): Function { + return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { req.pause(); const packageName = req.params.scope ? `@${req.params.scope}/${req.params.package}` : req.params.package; const packageVersion = req.params.filename ? getVersionFromTarball(req.params.filename) : undefined; const remote: RemoteUser = req.remote_user; logger.trace({ action, user: remote?.name }, `[middleware/allow][@{action}] allow for @{user}`); - auth['allow_' + action]({ packageName, packageVersion }, remote, function(error, allowed): void { + auth['allow_' + action]({ packageName, packageVersion }, remote, function (error, allowed): void { req.resume(); if (error) { next(error); @@ -210,7 +209,7 @@ export function log(req: $RequestExtend, res: $ResponseExtend, next: $NextFuncti } let bytesin = 0; - req.on('data', function(chunk): void { + req.on('data', function (chunk): void { bytesin += chunk.length; }); @@ -218,14 +217,14 @@ export function log(req: $RequestExtend, res: $ResponseExtend, next: $NextFuncti const _write = res.write; // FIXME: res.write should return boolean // @ts-ignore - res.write = function(buf): boolean { + res.write = function (buf): boolean { bytesout += buf.length; /* eslint prefer-rest-params: "off" */ // @ts-ignore _write.apply(res, arguments); }; - const log = function(): void { + const log = function (): void { const forwardedFor = req.headers['x-forwarded-for']; const remoteAddress = req.connection.remoteAddress; const remoteIP = forwardedFor ? `${forwardedFor} via ${remoteAddress}` : remoteAddress; @@ -258,12 +257,12 @@ export function log(req: $RequestExtend, res: $ResponseExtend, next: $NextFuncti req.originalUrl = req.url; }; - req.on('close', function(): void { + req.on('close', function (): void { log(); }); const _end = res.end; - res.end = function(buf): void { + res.end = function (buf): void { if (buf) { bytesout += buf.length; } @@ -296,7 +295,7 @@ export function handleError(err: HttpError, req: $RequestExtend, res: $ResponseE export function errorReportingMiddleware(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { res.locals.report_error = res.locals.report_error || - function(err: VerdaccioError): void { + function (err: VerdaccioError): void { if (err.status && err.status >= HTTP_STATUS.BAD_REQUEST && err.status < 600) { if (_.isNil(res.headersSent) === false) { res.status(err.status); diff --git a/packages/mock/src/config.ts b/packages/mock/src/config.ts index a555b2487..ab49479c8 100644 --- a/packages/mock/src/config.ts +++ b/packages/mock/src/config.ts @@ -1,21 +1,16 @@ - import path from 'path'; import _ from 'lodash'; -import {parseConfigFile} from '@verdaccio/utils'; +import { parseConfigFile } from '@verdaccio/utils'; /** * Override the default.yaml configuration file with any new config provided. */ function configExample(externalConfig, configFile: string = 'default.yaml', location: string = '') { - const locationFile = location ? path.join(location, configFile) : - path.join(__dirname, `./config/yaml/${configFile}`); + const locationFile = location ? path.join(location, configFile) : path.join(__dirname, `./config/yaml/${configFile}`); const config = parseConfigFile(locationFile); return _.assign({}, _.cloneDeep(config), externalConfig); } - -export { - configExample -} +export { configExample }; diff --git a/packages/mock/src/constants.ts b/packages/mock/src/constants.ts index d038a04b8..e07509581 100644 --- a/packages/mock/src/constants.ts +++ b/packages/mock/src/constants.ts @@ -1,7 +1,7 @@ export const DOMAIN_SERVERS = '0.0.0.0'; export const CREDENTIALS = { - user: 'test', - password: 'test' + user: 'test', + password: 'test', }; export const TARBALL = 'tarball-blahblah-file.name'; diff --git a/packages/mock/src/mock-api.ts b/packages/mock/src/mock-api.ts index cade57176..f5eb4445a 100644 --- a/packages/mock/src/mock-api.ts +++ b/packages/mock/src/mock-api.ts @@ -1,9 +1,9 @@ import _ from 'lodash'; import request from 'supertest'; -import {DIST_TAGS, LATEST, HEADER_TYPE, HEADERS, HTTP_STATUS, TOKEN_BEARER} from '@verdaccio/dev-commons'; -import {buildToken, encodeScopedUri} from '@verdaccio/utils'; -import {generateRandomHexString} from "@verdaccio/utils"; +import { DIST_TAGS, LATEST, HEADER_TYPE, HEADERS, HTTP_STATUS, TOKEN_BEARER } from '@verdaccio/dev-commons'; +import { buildToken, encodeScopedUri } from '@verdaccio/utils'; +import { generateRandomHexString } from '@verdaccio/utils'; import { Package } from '@verdaccio/types'; // API Helpers @@ -29,57 +29,43 @@ export function getTaggedVersionFromPackage(pkg, pkgName, tag: string = LATEST, return latestPkg; } - -export function putPackage( - request: any, - pkgName: string, - publishMetadata: Package, - token?: string): Promise { +export function putPackage(request: any, pkgName: string, publishMetadata: Package, token?: string): Promise { return new Promise((resolve) => { - const put = request.put(pkgName) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .send(JSON.stringify(publishMetadata)); + const put = request.put(pkgName).set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON).send(JSON.stringify(publishMetadata)); - if (_.isEmpty(token) === false ) { - expect(token).toBeDefined(); - put.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token as string)) + if (_.isEmpty(token) === false) { + expect(token).toBeDefined(); + put.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token as string)); } - put.set('accept', 'gzip') - .set('accept-encoding', HEADERS.JSON) - .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { - resolve([err, res]); - }); - }); -} - -export function deletePackage( - request: any, - pkgName: string, - token?: string -): Promise { - return new Promise((resolve) => { - const del = request.put(`/${encodeScopedUri(pkgName)}/-rev/${generateRandomHexString(8)}`) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); - - if (_.isNil(token) === false ) { - del.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token as string)) - } - - del.set('accept-encoding', HEADERS.JSON) + put + .set('accept', 'gzip') + .set('accept-encoding', HEADERS.JSON) .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { + .end(function (err, res) { resolve([err, res]); }); }); } -export function getPackage( - request: any, - token: string, - pkgName: string, - statusCode: number = HTTP_STATUS.OK): Promise { +export function deletePackage(request: any, pkgName: string, token?: string): Promise { + return new Promise((resolve) => { + const del = request.put(`/${encodeScopedUri(pkgName)}/-rev/${generateRandomHexString(8)}`).set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); + + if (_.isNil(token) === false) { + del.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token as string)); + } + + del + .set('accept-encoding', HEADERS.JSON) + .expect(HTTP_STATUS.CREATED) + .end(function (err, res) { + resolve([err, res]); + }); + }); +} + +export function getPackage(request: any, token: string, pkgName: string, statusCode: number = HTTP_STATUS.OK): Promise { return new Promise((resolve) => { const getRequest = request.get(`/${pkgName}`); @@ -90,39 +76,36 @@ export function getPackage( getRequest .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(statusCode) - .end(function(err, res) { + .end(function (err, res) { resolve([err, res]); }); }); } -export function loginUserToken(request: any, - user: string, - credentials: any, - token: string, - statusCode: number = HTTP_STATUS.CREATED): Promise { +export function loginUserToken(request: any, user: string, credentials: any, token: string, statusCode: number = HTTP_STATUS.CREATED): Promise { // $FlowFixMe return new Promise((resolve) => { - request.put(`/-/user/org.couchdb.user:${user}`) + request + .put(`/-/user/org.couchdb.user:${user}`) .send(credentials) .set('authorization', buildToken(TOKEN_BEARER, token)) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(statusCode) - .end(function(err, res) { + .end(function (err, res) { return resolve([err, res]); }); }); } -export function addUser(request: any, user: string, credentials: any, - statusCode: number = HTTP_STATUS.CREATED): Promise { +export function addUser(request: any, user: string, credentials: any, statusCode: number = HTTP_STATUS.CREATED): Promise { // $FlowFixMe return new Promise((resolve) => { - request.put(`/-/user/org.couchdb.user:${user}`) + request + .put(`/-/user/org.couchdb.user:${user}`) .send(credentials) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(statusCode) - .end(function(err, res) { + .end(function (err, res) { return resolve([err, res]); }); }); @@ -133,7 +116,7 @@ export async function getNewToken(request: any, credentials: any): Promise { const [err, res] = await addUser(request, credentials.name, credentials); expect(err).toBeNull(); - const {token, ok} = res.body; + const { token, ok } = res.body; expect(ok).toBeDefined(); expect(token).toBeDefined(); expect(typeof token).toBe('string'); @@ -141,28 +124,30 @@ export async function getNewToken(request: any, credentials: any): Promise { +export function getProfile(request: any, token: string, statusCode: number = HTTP_STATUS.OK): Promise { // $FlowFixMe return new Promise((resolve) => { - request.get(`/-/npm/v1/user`) + request + .get(`/-/npm/v1/user`) .set('authorization', buildToken(TOKEN_BEARER, token)) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(statusCode) - .end(function(err, res) { + .end(function (err, res) { return resolve([err, res]); }); }); } -export function postProfile(request: any, body: any, token: string, statusCode: number = HTTP_STATUS.OK): Promise { +export function postProfile(request: any, body: any, token: string, statusCode: number = HTTP_STATUS.OK): Promise { // $FlowFixMe return new Promise((resolve) => { - request.post(`/-/npm/v1/user`) + request + .post(`/-/npm/v1/user`) .send(body) .set(HEADERS.AUTHORIZATION, `Bearer ${token}`) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(statusCode) - .end(function(err, res) { + .end(function (err, res) { return resolve([err, res]); }); }); @@ -170,7 +155,7 @@ export function postProfile(request: any, body: any, token: string, statusCode: export async function fetchPackageByVersionAndTag(app, encodedPkgName, pkgName, version, tag = 'latest') { // we retrieve the package to verify - const [err, resp]= await getPackage(request(app), '', encodedPkgName); + const [err, resp] = await getPackage(request(app), '', encodedPkgName); expect(err).toBeNull(); @@ -179,13 +164,13 @@ export async function fetchPackageByVersionAndTag(app, encodedPkgName, pkgName, } export async function isExistPackage(app, packageName) { - const [err]= await getPackage(request(app), '', encodeScopedUri(packageName), HTTP_STATUS.OK); + const [err] = await getPackage(request(app), '', encodeScopedUri(packageName), HTTP_STATUS.OK); return _.isNull(err); } export async function verifyPackageVersionDoesExist(app, packageName, version, token?: string) { - const [, res]= await getPackage(request(app), token as string, encodeScopedUri(packageName), HTTP_STATUS.OK); + const [, res] = await getPackage(request(app), token as string, encodeScopedUri(packageName), HTTP_STATUS.OK); const { versions } = res.body; const versionsKeys = Object.keys(versions); diff --git a/packages/mock/src/mock.ts b/packages/mock/src/mock.ts index e54ccb457..52c338590 100644 --- a/packages/mock/src/mock.ts +++ b/packages/mock/src/mock.ts @@ -2,12 +2,11 @@ import path from 'path'; import fs from 'fs'; import os from 'os'; import * as fsExtra from 'fs-extra'; -import {DOMAIN_SERVERS} from './constants'; +import { DOMAIN_SERVERS } from './constants'; import VerdaccioProcess from './server_process'; -import {VerdaccioConfig} from './verdaccio-server'; +import { VerdaccioConfig } from './verdaccio-server'; import Server from './server'; -import {IServerBridge} from './types'; - +import { IServerBridge } from './types'; /** * Fork a Verdaccio process with a custom configuration. @@ -57,7 +56,7 @@ export function mockServer(port: number, options: MockRegistryOptions = {}) { // console.log("-->tempRoot", tempRoot); // default locations - const configPath = path.join(__dirname, './config/yaml', '/mock-server-test.yaml'); + const configPath = path.join(__dirname, './config/yaml', '/mock-server-test.yaml'); const mockStorePath = path.join(__dirname, '/fixtures/mock-store'); // default options @@ -67,7 +66,7 @@ export function mockServer(port: number, options: MockRegistryOptions = {}) { storePath: mockStorePath, rootFolder: tempRoot, silence: true, - debug: false + debug: false, }; // mix external options @@ -93,6 +92,6 @@ export interface MockRegistryOptions { configPath?: string; port?: number; storePath?: string; - silence?: boolean + silence?: boolean; debug?: boolean; } diff --git a/packages/mock/src/request.ts b/packages/mock/src/request.ts index ffedc09e5..d29a71e1e 100644 --- a/packages/mock/src/request.ts +++ b/packages/mock/src/request.ts @@ -6,7 +6,6 @@ import { IRequestPromise } from './types'; const requestData = Symbol('smart_request_data'); export class PromiseAssert extends Promise implements IRequestPromise { - public constructor(options: any) { super(options); } @@ -14,56 +13,63 @@ export class PromiseAssert extends Promise implements IRequestPromise { public status(expected: number) { const selfData = this[requestData]; - return injectResponse(this, this.then(function(body) { - try { - assert.equal(selfData.response.statusCode, expected); - } catch(err) { - selfData.error.message = err.message; - throw selfData.error; - } - return body; - })); + return injectResponse( + this, + this.then(function (body) { + try { + assert.equal(selfData.response.statusCode, expected); + } catch (err) { + selfData.error.message = err.message; + throw selfData.error; + } + return body; + }) + ); } public body_ok(expected: any) { const selfData = this[requestData]; - return injectResponse(this, this.then(function(body) { - try { - if (_.isRegExp(expected)) { - assert(body.ok.match(expected), '\'' + body.ok + '\' doesn\'t match ' + expected); - } else { - assert.equal(body.ok, expected); + return injectResponse( + this, + this.then(function (body) { + try { + if (_.isRegExp(expected)) { + assert(body.ok.match(expected), "'" + body.ok + "' doesn't match " + expected); + } else { + assert.equal(body.ok, expected); + } + assert.equal(body.error, null); + } catch (err) { + selfData.error.message = err.message; + throw selfData.error; } - assert.equal(body.error, null); - } catch(err) { - selfData.error.message = err.message; - throw selfData.error; - } - return body; - })); + return body; + }) + ); } - public body_error(expected: any) { - const selfData = this[requestData]; - return injectResponse(this, this.then(function(body) { - try { - if (_.isRegExp(expected)) { - assert(body.error.match(expected), body.error + ' doesn\'t match ' + expected); - } else { - assert.equal(body.error, expected); + return injectResponse( + this, + this.then(function (body) { + try { + if (_.isRegExp(expected)) { + assert(body.error.match(expected), body.error + " doesn't match " + expected); + } else { + assert.equal(body.error, expected); + } + assert.equal(body.ok, null); + } catch (err) { + selfData.error.message = err.message; + throw selfData.error; } - assert.equal(body.ok, null); - } catch(err) { - selfData.error.message = err.message; - throw selfData.error; - } - return body; - })); + return body; + }) + ); } public request(callback: any) { @@ -74,26 +80,26 @@ export class PromiseAssert extends Promise implements IRequestPromise { public response(cb: any) { const selfData = this[requestData]; - return injectResponse(this, this.then(function(body) { - cb(selfData.response); - return body; - })); + return injectResponse( + this, + this.then(function (body) { + cb(selfData.response); + return body; + }) + ); } public send(data: any) { this[requestData].request.end(data); return this; } - } function injectResponse(smartObject: any, promise: Promise): Promise { - promise[requestData] = smartObject[requestData]; return promise; } - function smartRequest(options: any): Promise { const smartObject: any = {}; @@ -101,9 +107,9 @@ function smartRequest(options: any): Promise { smartObject[requestData].error = Error(); Error.captureStackTrace(smartObject[requestData].error, smartRequest); - const promiseResult: Promise = new PromiseAssert(function(resolve, reject) { + const promiseResult: Promise = new PromiseAssert(function (resolve, reject) { // store request reference on symbol - smartObject[requestData].request = request(options, function(err, res, body) { + smartObject[requestData].request = request(options, function (err, res, body) { if (err) { return reject(err); } @@ -118,4 +124,3 @@ function smartRequest(options: any): Promise { } export default smartRequest; - diff --git a/packages/mock/src/server.ts b/packages/mock/src/server.ts index 1af943182..bd645f832 100644 --- a/packages/mock/src/server.ts +++ b/packages/mock/src/server.ts @@ -1,12 +1,11 @@ import assert from 'assert'; import _ from 'lodash'; -import {API_MESSAGE, HEADERS, HTTP_STATUS, TOKEN_BASIC} from '@verdaccio/dev-commons'; -import {buildToken} from "@verdaccio/utils"; +import { API_MESSAGE, HEADERS, HTTP_STATUS, TOKEN_BASIC } from '@verdaccio/dev-commons'; +import { buildToken } from '@verdaccio/utils'; import smartRequest from './request'; -import {IServerBridge} from './types'; +import { IServerBridge } from './types'; - -import {CREDENTIALS} from "./constants" +import { CREDENTIALS } from './constants'; import getPackage from './fixtures/package'; const buildAuthHeader = (user, pass): string => { @@ -65,7 +64,6 @@ export default class Server implements IServerBridge { }); } - public getPackage(name: string) { return this.request({ uri: `/${encodeURIComponent(name)}`, @@ -139,7 +137,6 @@ export default class Server implements IServerBridge { }); } - public addTag(name: string, tag: string, version: string) { return this.request({ uri: `/${encodeURIComponent(name)}/${encodeURIComponent(tag)}`, @@ -161,20 +158,20 @@ export default class Server implements IServerBridge { timeout: 1000, }); - promise.request(function(req) { + promise.request(function (req) { req.write(data); // it auto abort the request - setTimeout(function() { + setTimeout(function () { req.req.abort(); }, 20); }); - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { promise - .then(function() { + .then(function () { reject(Error('no error')); }) - .catch(function(err) { + .catch(function (err) { if (err.code === 'ECONNRESET') { // @ts-ignore resolve(); @@ -186,25 +183,25 @@ export default class Server implements IServerBridge { } public addPackage(name: string) { - return this.putPackage(name, getPackage(name)) - .status(HTTP_STATUS.CREATED) - .body_ok(API_MESSAGE.PKG_CREATED); + return this.putPackage(name, getPackage(name)).status(HTTP_STATUS.CREATED).body_ok(API_MESSAGE.PKG_CREATED); } public whoami() { return this.request({ - uri: '/-/whoami' - }).status(HTTP_STATUS.OK) - .then(function(body) { + uri: '/-/whoami', + }) + .status(HTTP_STATUS.OK) + .then(function (body) { return body.username; }); } public ping() { return this.request({ - uri: '/-/ping' - }).status(HTTP_STATUS.OK) - .then(function(body) { + uri: '/-/ping', + }) + .status(HTTP_STATUS.OK) + .then(function (body) { return body; }); } @@ -216,6 +213,6 @@ export default class Server implements IServerBridge { headers: { [HEADERS.CONTENT_TYPE]: HEADERS.JSON, }, - }) + }); } } diff --git a/packages/mock/src/server_process.ts b/packages/mock/src/server_process.ts index 9d17d6fba..275921051 100644 --- a/packages/mock/src/server_process.ts +++ b/packages/mock/src/server_process.ts @@ -1,24 +1,20 @@ import assert from 'assert'; -import {fork} from 'child_process'; +import { fork } from 'child_process'; -import {HTTP_STATUS} from '@verdaccio/dev-commons'; +import { HTTP_STATUS } from '@verdaccio/dev-commons'; -import {CREDENTIALS} from './constants'; -import {IVerdaccioConfig, IServerBridge, IServerProcess} from './types'; +import { CREDENTIALS } from './constants'; +import { IVerdaccioConfig, IServerBridge, IServerProcess } from './types'; const defaultBinPath = require.resolve('verdaccio/bin/verdaccio'); export default class VerdaccioProcess implements IServerProcess { - private bridge: IServerBridge; private config: IVerdaccioConfig; private childFork: any; private isDebug: boolean; private silence: boolean; - public constructor(config: IVerdaccioConfig, - bridge: IServerBridge, - silence = true, - isDebug = false) { + public constructor(config: IVerdaccioConfig, bridge: IServerBridge, silence = true, isDebug = false) { this.config = config; this.bridge = bridge; this.silence = silence; @@ -34,7 +30,7 @@ export default class VerdaccioProcess implements IServerProcess { private _start(verdaccioPath: string, resolve: Function, reject: Function) { let childOptions = { - silent: this.silence + silent: this.silence, }; if (this.isDebug) { @@ -44,39 +40,42 @@ export default class VerdaccioProcess implements IServerProcess { childOptions = Object.assign({}, childOptions, { execArgv: [`--inspect=${debugPort}`], env: { - "NODE_DEBUG": 'request' - } + NODE_DEBUG: 'request', + }, }); } - const {configPath, port} = this.config; + const { configPath, port } = this.config; this.childFork = fork(verdaccioPath, ['-c', configPath, '-l', port as string], childOptions); this.childFork.on('message', (msg) => { // verdaccio_started is a message that comes from verdaccio in debug mode that notify has been started if ('verdaccio_started' in msg) { - this.bridge.debug().status(HTTP_STATUS.OK).then((body) => { - this.bridge.auth(CREDENTIALS.user, CREDENTIALS.password) - .status(HTTP_STATUS.CREATED) - .body_ok(new RegExp(CREDENTIALS.user)) - .then(() => resolve([this, body.pid]), reject) - }, reject); + this.bridge + .debug() + .status(HTTP_STATUS.OK) + .then((body) => { + this.bridge + .auth(CREDENTIALS.user, CREDENTIALS.password) + .status(HTTP_STATUS.CREATED) + .body_ok(new RegExp(CREDENTIALS.user)) + .then(() => resolve([this, body.pid]), reject); + }, reject); } }); this.childFork.on('error', (err) => { - reject([err, this]) + reject([err, this]); }); this.childFork.on('disconnect', (err) => { - reject([err, this]) + reject([err, this]); }); this.childFork.on('exit', (err) => { - reject([err, this]) + reject([err, this]); }); } public stop(): void { return this.childFork.kill('SIGINT'); } - } diff --git a/packages/mock/src/utils-test.ts b/packages/mock/src/utils-test.ts index 829027b54..4924d66ba 100644 --- a/packages/mock/src/utils-test.ts +++ b/packages/mock/src/utils-test.ts @@ -1,8 +1,8 @@ -import fs from "fs"; -import path from "path"; -import os from "os"; +import fs from 'fs'; +import path from 'path'; +import os from 'os'; import { pseudoRandomBytes } from 'crypto'; -import { Version } from "@verdaccio/types"; +import { Version } from '@verdaccio/types'; export function generateRamdonStorage() { const tempStorage = pseudoRandomBytes(5).toString('hex'); @@ -11,31 +11,28 @@ export function generateRamdonStorage() { return path.join(tempRoot, tempStorage); } -export function generateNewVersion( - pkgName: string, - version: string, - shashum = '238e7641e59508dc9c20eb4ad37a8aa57ab777b4'): Version { +export function generateNewVersion(pkgName: string, version: string, shashum = '238e7641e59508dc9c20eb4ad37a8aa57ab777b4'): Version { // $FlowFixMe return { - "name": pkgName, - "version": version, - "description": "", - "main": "index.js", - "dependencies": { - "test": "^1.4.1" + name: pkgName, + version: version, + description: '', + main: 'index.js', + dependencies: { + test: '^1.4.1', }, - "author": "", - "license": "ISC", - "readme": "ERROR: No README data found!", - "_id": `${pkgName}@${version}`, - "_npmVersion": "5.5.1", - "_npmUser": { - "name": "Foo" + author: '', + license: 'ISC', + readme: 'ERROR: No README data found!', + _id: `${pkgName}@${version}`, + _npmVersion: '5.5.1', + _npmUser: { + name: 'Foo', }, - "dist": { - "integrity": "sha512-zVEqt1JUCOPsash9q4wMkJEDPD+QCx95TRhQII+JnoS31uBUKoZxhzvvUJCcLVy2CQG4QdwXARU7dYWPnrwhGg==", - "shasum": shashum, - "tarball": `http:\/\/localhost:4873\/${pkgName}\/-\/${pkgName}-${version}.tgz` - } - } + dist: { + integrity: 'sha512-zVEqt1JUCOPsash9q4wMkJEDPD+QCx95TRhQII+JnoS31uBUKoZxhzvvUJCcLVy2CQG4QdwXARU7dYWPnrwhGg==', + shasum: shashum, + tarball: `http:\/\/localhost:4873\/${pkgName}\/-\/${pkgName}-${version}.tgz`, + }, + }; } diff --git a/packages/mock/src/verdaccio-server.ts b/packages/mock/src/verdaccio-server.ts index 279f603ff..fa908171b 100644 --- a/packages/mock/src/verdaccio-server.ts +++ b/packages/mock/src/verdaccio-server.ts @@ -1,7 +1,6 @@ -import {IVerdaccioConfig} from './types'; +import { IVerdaccioConfig } from './types'; export class VerdaccioConfig implements IVerdaccioConfig { - public storagePath: string; public configPath: string; public domainPath: string; diff --git a/packages/mock/test/request.spec.ts b/packages/mock/test/request.spec.ts index 1b811745a..eb6b10baa 100644 --- a/packages/mock/test/request.spec.ts +++ b/packages/mock/test/request.spec.ts @@ -1,9 +1,9 @@ import _ from 'lodash'; -import {HTTP_STATUS} from '@verdaccio/dev-commons'; +import { HTTP_STATUS } from '@verdaccio/dev-commons'; import { VerdaccioError } from '@verdaccio/commons-api'; -import smartRequest, {PromiseAssert} from '../src/request'; -import {mockServer} from '../src/mock'; +import smartRequest, { PromiseAssert } from '../src/request'; +import { mockServer } from '../src/mock'; import { IRequestPromise } from '../src/types'; describe('Request Functional', () => { @@ -19,7 +19,7 @@ describe('Request Functional', () => { }); test('basic resolve', (done) => { - const requestPromise: IRequestPromise = new PromiseAssert(resolve => { + const requestPromise: IRequestPromise = new PromiseAssert((resolve) => { resolve(1); }); // @ts-ignore @@ -36,7 +36,7 @@ describe('Request Functional', () => { mockRegistry = await mockServer(mockServerPort).init(binPath); }); - afterAll(function(done) { + afterAll(function (done) { const [registry, pid] = mockRegistry; registry.stop(); console.log(`registry ${pid} has been stopped`); @@ -47,53 +47,61 @@ describe('Request Functional', () => { test('basic rest', (done) => { const options: any = { url: restTest, - method: 'GET' + method: 'GET', }; - smartRequest(options).then((result)=> { + smartRequest(options).then((result) => { expect(_.isString(result)).toBeTruthy(); done(); - }) + }); }); describe('smartRequest Status', () => { - test('basic check status 200', (done) => { const options: any = { url: restTest, - method: 'GET' + method: 'GET', }; // @ts-ignore - smartRequest(options).status(HTTP_STATUS.OK).then((result)=> { - expect(JSON.parse(result).name).toBe('jquery'); - done(); - }) + smartRequest(options) + .status(HTTP_STATUS.OK) + .then((result) => { + expect(JSON.parse(result).name).toBe('jquery'); + done(); + }); }); test('basic ping status and empty response', (done) => { const options: any = { url: `${domainTest}/-/ping`, - method: 'GET' + method: 'GET', }; // @ts-ignore - smartRequest(options).status(HTTP_STATUS.OK).then((result)=> { - expect(JSON.parse((result))).toEqual({}); - done(); - }) + smartRequest(options) + .status(HTTP_STATUS.OK) + .then((result) => { + expect(JSON.parse(result)).toEqual({}); + done(); + }); }); test('basic check status 404', (done) => { const options: any = { url: 'http://www.google.fake', - method: 'GET' + method: 'GET', }; // @ts-ignore - smartRequest(options).status(HTTP_STATUS.NOT_FOUND).then(() => { - // we do not intent to resolve this - }, (error: VerdaccioError) => { - expect(error.code).toBe('ENOTFOUND'); - done(); - }) + smartRequest(options) + .status(HTTP_STATUS.NOT_FOUND) + .then( + () => { + // we do not intent to resolve this + }, + (error: VerdaccioError) => { + expect(error.code).toBe('ENOTFOUND'); + done(); + } + ); }); }); }); diff --git a/packages/node-api/src/bootstrap.ts b/packages/node-api/src/bootstrap.ts index 3443e4f66..b86da7668 100644 --- a/packages/node-api/src/bootstrap.ts +++ b/packages/node-api/src/bootstrap.ts @@ -6,13 +6,13 @@ import constants from 'constants'; import { Application } from 'express'; import { assign, isObject, isFunction } from 'lodash'; -import { Callback, ConfigWithHttps, HttpsConfKeyCert, HttpsConfPfx } from '@verdaccio/types'; +import { Callback, ConfigWithHttps, HttpsConfKeyCert, HttpsConfPfx } from '@verdaccio/types'; import { API_ERROR, certPem, csrPem, keyPem } from '@verdaccio/dev-commons'; import server from '@verdaccio/server'; -import { logger} from '@verdaccio/logger'; +import { logger } from '@verdaccio/logger'; import { getListListenAddresses, resolveConfigPath } from './cli-utils'; -import {displayExperimentsInfoBox} from "./experiments"; +import { displayExperimentsInfoBox } from './experiments'; function launchServer(app, addr, config, configPath: string, pkgVersion: string, pkgName: string, callback: Callback): void { let webServer; @@ -45,14 +45,13 @@ function startVerdaccio(config: any, cliListen: string, configPath: string, pkgV } server(config).then((app): void => { - const addresses = getListListenAddresses(cliListen, config.listen); - if ('experiments' in config) { - displayExperimentsInfoBox(config.experiments); - } - - addresses.forEach(addr =>launchServer(app, addr, config, configPath, pkgVersion, pkgName, callback)); + const addresses = getListListenAddresses(cliListen, config.listen); + if ('experiments' in config) { + displayExperimentsInfoBox(config.experiments); } - ); + + addresses.forEach((addr) => launchServer(app, addr, config, configPath, pkgVersion, pkgName, callback)); + }); } function unlinkAddressPath(addr) { @@ -129,19 +128,15 @@ function handleHTTPS(app: Application, configPath: string, config: ConfigWithHtt function listenDefaultCallback(webServer: Application, addr: any, pkgName: string, pkgVersion: string): void { webServer - .listen( - addr.port || addr.path, - addr.host, - (): void => { - // send a message for tests - if (isFunction(process.send)) { - process.send({ - verdaccio_started: true, - }); - } + .listen(addr.port || addr.path, addr.host, (): void => { + // send a message for tests + if (isFunction(process.send)) { + process.send({ + verdaccio_started: true, + }); } - ) - .on('error', function(err): void { + }) + .on('error', function (err): void { logger.fatal({ err: err }, 'cannot create server: @{err.message}'); process.exit(2); }); diff --git a/packages/node-api/src/cli-utils.ts b/packages/node-api/src/cli-utils.ts index 2d7f4c4e7..73ddd3996 100644 --- a/packages/node-api/src/cli-utils.ts +++ b/packages/node-api/src/cli-utils.ts @@ -48,9 +48,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/")' ); } diff --git a/packages/node-api/src/experiments.ts b/packages/node-api/src/experiments.ts index 7e31f619c..ed3c8ce0f 100644 --- a/packages/node-api/src/experiments.ts +++ b/packages/node-api/src/experiments.ts @@ -1,11 +1,11 @@ const logger = require('@verdaccio/logger'); export function displayExperimentsInfoBox(experiments) { - const experimentList = Object.keys(experiments); - if (experimentList.length >= 1) { - logger.logger.warn('⚠️ experiments are enabled, we recommend do not use experiments in production, comment out this section to disable it'); - experimentList.forEach(experiment => { - logger.logger.warn(` - support for ${experiment} ${experiments[experiment] ? 'is enabled' : ' is disabled'}`); - }); - } + const experimentList = Object.keys(experiments); + if (experimentList.length >= 1) { + logger.logger.warn('⚠️ experiments are enabled, we recommend do not use experiments in production, comment out this section to disable it'); + experimentList.forEach((experiment) => { + logger.logger.warn(` - support for ${experiment} ${experiments[experiment] ? 'is enabled' : ' is disabled'}`); + }); + } } diff --git a/packages/node-api/src/https.ts b/packages/node-api/src/https.ts index d1cfe61c5..2d4b16f24 100644 --- a/packages/node-api/src/https.ts +++ b/packages/node-api/src/https.ts @@ -1,34 +1,34 @@ import { API_ERROR, certPem, csrPem, keyPem } from '@verdaccio/dev-commons'; -import {resolveConfigPath} from "./cli-utils"; +import { resolveConfigPath } from './cli-utils'; const logger = require('@verdaccio/logger'); export function logHTTPSWarning(storageLocation) { - logger.logger.fatal( - [ - 'You have enabled HTTPS and need to specify either ', - ' "https.key", "https.cert" and "https.ca" or ', - ' "https.pfx" and optionally "https.passphrase" ', - 'to run https server', - '', - // commands are borrowed from node.js docs - 'To quickly create self-signed certificate, use:', - ' $ openssl genrsa -out ' + resolveConfigPath(storageLocation, keyPem) + ' 2048', - ' $ openssl req -new -sha256 -key ' + resolveConfigPath(storageLocation, keyPem) + ' -out ' + resolveConfigPath(storageLocation, csrPem), - ' $ openssl x509 -req -in ' + - resolveConfigPath(storageLocation, csrPem) + - ' -signkey ' + - resolveConfigPath(storageLocation, keyPem) + - ' -out ' + - resolveConfigPath(storageLocation, certPem), - '', - 'And then add to config file (' + storageLocation + '):', - ' https:', - ` key: ${resolveConfigPath(storageLocation, keyPem)}`, - ` cert: ${resolveConfigPath(storageLocation, certPem)}`, - ` ca: ${resolveConfigPath(storageLocation, csrPem)}`, - ].join('\n') - ); - process.exit(2); + logger.logger.fatal( + [ + 'You have enabled HTTPS and need to specify either ', + ' "https.key", "https.cert" and "https.ca" or ', + ' "https.pfx" and optionally "https.passphrase" ', + 'to run https server', + '', + // commands are borrowed from node.js docs + 'To quickly create self-signed certificate, use:', + ' $ openssl genrsa -out ' + resolveConfigPath(storageLocation, keyPem) + ' 2048', + ' $ openssl req -new -sha256 -key ' + resolveConfigPath(storageLocation, keyPem) + ' -out ' + resolveConfigPath(storageLocation, csrPem), + ' $ openssl x509 -req -in ' + + resolveConfigPath(storageLocation, csrPem) + + ' -signkey ' + + resolveConfigPath(storageLocation, keyPem) + + ' -out ' + + resolveConfigPath(storageLocation, certPem), + '', + 'And then add to config file (' + storageLocation + '):', + ' https:', + ` key: ${resolveConfigPath(storageLocation, keyPem)}`, + ` cert: ${resolveConfigPath(storageLocation, certPem)}`, + ` ca: ${resolveConfigPath(storageLocation, csrPem)}`, + ].join('\n') + ); + process.exit(2); } diff --git a/packages/node-api/test/node-api.spec.ts b/packages/node-api/test/node-api.spec.ts index b232ffec4..afef69230 100644 --- a/packages/node-api/test/node-api.spec.ts +++ b/packages/node-api/test/node-api.spec.ts @@ -4,8 +4,8 @@ import fs from 'fs'; import selfsigned from 'selfsigned'; import { configExample } from '@verdaccio/mock'; -import {DEFAULT_DOMAIN, DEFAULT_PROTOCOL} from '@verdaccio/dev-commons'; -import {parseConfigFile} from '@verdaccio/utils'; +import { DEFAULT_DOMAIN, DEFAULT_PROTOCOL } from '@verdaccio/dev-commons'; +import { parseConfigFile } from '@verdaccio/utils'; import { logger } from '@verdaccio/logger'; @@ -19,12 +19,11 @@ jest.mock('@verdaccio/logger', () => ({ trace: jest.fn(), warn: jest.fn(), error: jest.fn(), - fatal: jest.fn() - } + fatal: jest.fn(), + }, })); describe('startServer via API', () => { - const parseConfigurationFile = (name) => { return parseConfigFile(path.join(__dirname, `./partials/config/yaml/${name}.yaml`)); }; @@ -36,19 +35,18 @@ describe('startServer via API', () => { const version = '1.0.0'; const port = '6000'; - await startVerdaccio(configExample(), port, store, version, serverName, - (webServer, addrs, pkgName, pkgVersion) => { - expect(webServer).toBeDefined(); - expect(addrs).toBeDefined(); - expect(addrs.proto).toBe(DEFAULT_PROTOCOL); - expect(addrs.host).toBe(DEFAULT_DOMAIN); - expect(addrs.port).toBe(port); - expect(pkgName).toBeDefined(); - expect(pkgVersion).toBeDefined(); - expect(pkgVersion).toBe(version); - expect(pkgName).toBe(serverName); - done(); - }); + await startVerdaccio(configExample(), port, store, version, serverName, (webServer, addrs, pkgName, pkgVersion) => { + expect(webServer).toBeDefined(); + expect(addrs).toBeDefined(); + expect(addrs.proto).toBe(DEFAULT_PROTOCOL); + expect(addrs.host).toBe(DEFAULT_DOMAIN); + expect(addrs.port).toBe(port); + expect(pkgName).toBeDefined(); + expect(pkgVersion).toBeDefined(); + expect(pkgVersion).toBe(version); + expect(pkgName).toBe(serverName); + done(); + }); }); test('should set keepAliveTimeout to 0 seconds', async (done) => { @@ -57,7 +55,12 @@ describe('startServer via API', () => { const version = '1.0.0'; const port = '6100'; - await startVerdaccio(configExample(parseConfigurationFile('server/keepalivetimeout-0')), port, store, version, serverName, + await startVerdaccio( + configExample(parseConfigurationFile('server/keepalivetimeout-0')), + port, + store, + version, + serverName, (webServer, addrs, pkgName, pkgVersion) => { expect(webServer).toBeDefined(); expect(webServer.keepAliveTimeout).toBeDefined(); @@ -71,7 +74,8 @@ describe('startServer via API', () => { expect(pkgVersion).toBe(version); expect(pkgName).toBe(serverName); done(); - }); + } + ); }); test('should set keepAliveTimeout to 60 seconds', async (done) => { @@ -80,7 +84,12 @@ describe('startServer via API', () => { const version = '1.0.0'; const port = '6200'; - await startVerdaccio(configExample(parseConfigurationFile('server/keepalivetimeout-60')), port, store, version, serverName, + await startVerdaccio( + configExample(parseConfigurationFile('server/keepalivetimeout-60')), + port, + store, + version, + serverName, (webServer, addrs, pkgName, pkgVersion) => { expect(webServer).toBeDefined(); expect(webServer.keepAliveTimeout).toBeDefined(); @@ -94,7 +103,8 @@ describe('startServer via API', () => { expect(pkgVersion).toBe(version); expect(pkgName).toBe(serverName); done(); - }); + } + ); }); test('should set keepAliveTimeout to 5 seconds per default', async (done) => { @@ -103,7 +113,12 @@ describe('startServer via API', () => { const version = '1.0.0'; const port = '6300'; - await startVerdaccio(configExample(parseConfigurationFile('server/keepalivetimeout-undefined')), port, store, version, serverName, + await startVerdaccio( + configExample(parseConfigurationFile('server/keepalivetimeout-undefined')), + port, + store, + version, + serverName, (webServer, addrs, pkgName, pkgVersion) => { expect(webServer).toBeDefined(); expect(webServer.keepAliveTimeout).toBeDefined(); @@ -117,7 +132,8 @@ describe('startServer via API', () => { expect(pkgVersion).toBe(version); expect(pkgName).toBe(serverName); done(); - }); + } + ); }); test('should provide all HTTPS server fails', async (done) => { @@ -160,14 +176,13 @@ describe('startServer via API', () => { cert: certPath, }; - await startVerdaccio(conf, address, store, version, serverName, - (webServer, addrs) => { - expect(webServer).toBeDefined(); - expect(addrs).toBeDefined(); - expect(addrs.proto).toBe('https'); - done(); + await startVerdaccio(conf, address, store, version, serverName, (webServer, addrs) => { + expect(webServer).toBeDefined(); + expect(addrs).toBeDefined(); + expect(addrs.proto).toBe('https'); + done(); }); - }) + }); test('should fails if config is missing', async () => { try { @@ -177,6 +192,5 @@ describe('startServer via API', () => { expect(e.message).toEqual('config file must be an object'); } }); - }); }); diff --git a/packages/node-api/test/node-api.utils.spec.ts b/packages/node-api/test/node-api.utils.spec.ts index 480f24462..eaf170061 100644 --- a/packages/node-api/test/node-api.utils.spec.ts +++ b/packages/node-api/test/node-api.utils.spec.ts @@ -1,76 +1,74 @@ -import _ from "lodash"; -import {DEFAULT_DOMAIN, DEFAULT_PORT, DEFAULT_PROTOCOL} from "@verdaccio/dev-commons"; -import {getListListenAddresses} from "../src/cli-utils"; +import _ from 'lodash'; +import { DEFAULT_DOMAIN, DEFAULT_PORT, DEFAULT_PROTOCOL } from '@verdaccio/dev-commons'; +import { getListListenAddresses } from '../src/cli-utils'; jest.mock('@verdaccio/logger', () => ({ - setup: jest.fn(), - logger: { - child: jest.fn(), - debug: jest.fn(), - trace: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - fatal: jest.fn() - } + setup: jest.fn(), + logger: { + child: jest.fn(), + debug: jest.fn(), + trace: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + fatal: jest.fn(), + }, })); describe('getListListenAddresses test', () => { + test('should return no address if a single address is wrong', () => { + // @ts-ignore + const addrs = getListListenAddresses('wrong'); - test('should return no address if a single address is wrong', () => { - // @ts-ignore - const addrs = getListListenAddresses("wrong"); + expect(_.isArray(addrs)).toBeTruthy(); + expect(addrs).toHaveLength(0); + }); - expect(_.isArray(addrs)).toBeTruthy(); - expect(addrs).toHaveLength(0); - }); + test('should return no address if a two address are wrong', () => { + // @ts-ignore + const addrs = getListListenAddresses(['wrong', 'same-wrong']); - test('should return no address if a two address are wrong', () => { - // @ts-ignore - const addrs = getListListenAddresses(["wrong", "same-wrong"]); + expect(_.isArray(addrs)).toBeTruthy(); + expect(addrs).toHaveLength(0); + }); - expect(_.isArray(addrs)).toBeTruthy(); - expect(addrs).toHaveLength(0); - }); + test('should return a list of 1 address provided', () => { + // @ts-ignore + const addrs = getListListenAddresses(null, '1000'); - test('should return a list of 1 address provided', () => { - // @ts-ignore - const addrs = getListListenAddresses(null, '1000'); + expect(_.isArray(addrs)).toBeTruthy(); + expect(addrs).toHaveLength(1); + }); - expect(_.isArray(addrs)).toBeTruthy(); - expect(addrs).toHaveLength(1); - }); + test('should return a list of 2 address provided', () => { + // @ts-ignore + const addrs = getListListenAddresses(null, ['1000', '2000']); - test('should return a list of 2 address provided', () => { - // @ts-ignore - const addrs = getListListenAddresses(null, ['1000', '2000']); + expect(_.isArray(addrs)).toBeTruthy(); + expect(addrs).toHaveLength(2); + }); - expect(_.isArray(addrs)).toBeTruthy(); - expect(addrs).toHaveLength(2); - }); + test(`should return by default ${DEFAULT_PORT}`, () => { + // @ts-ignore + const [addrs] = getListListenAddresses(); - test(`should return by default ${DEFAULT_PORT}`, () => { - // @ts-ignore - const [addrs] = getListListenAddresses(); + // @ts-ignore + expect(addrs.proto).toBe(DEFAULT_PROTOCOL); + // @ts-ignore + expect(addrs.host).toBe(DEFAULT_DOMAIN); + // @ts-ignore + expect(addrs.port).toBe(DEFAULT_PORT); + }); - // @ts-ignore - expect(addrs.proto).toBe(DEFAULT_PROTOCOL); - // @ts-ignore - expect(addrs.host).toBe(DEFAULT_DOMAIN); - // @ts-ignore - expect(addrs.port).toBe(DEFAULT_PORT); - }); - - test('should return default proto, host and custom port', () => { - const initPort = '1000'; - // @ts-ignore - const [addrs] = getListListenAddresses(null, initPort); - - // @ts-ignore - expect(addrs.proto).toEqual(DEFAULT_PROTOCOL); - // @ts-ignore - expect(addrs.host).toEqual(DEFAULT_DOMAIN); - // @ts-ignore - expect(addrs.port).toEqual(initPort); - }); + test('should return default proto, host and custom port', () => { + const initPort = '1000'; + // @ts-ignore + const [addrs] = getListListenAddresses(null, initPort); + // @ts-ignore + expect(addrs.proto).toEqual(DEFAULT_PROTOCOL); + // @ts-ignore + expect(addrs.host).toEqual(DEFAULT_DOMAIN); + // @ts-ignore + expect(addrs.port).toEqual(initPort); + }); }); diff --git a/packages/proxy/src/up-storage.ts b/packages/proxy/src/up-storage.ts index 7a9def308..a21668fa0 100644 --- a/packages/proxy/src/up-storage.ts +++ b/packages/proxy/src/up-storage.ts @@ -1,6 +1,6 @@ import zlib from 'zlib'; import Stream from 'stream'; -import URL, {UrlWithStringQuery} from 'url'; +import URL, { UrlWithStringQuery } from 'url'; import JSONStream from 'JSONStream'; import _ from 'lodash'; import request from 'request'; @@ -11,7 +11,7 @@ import { Config, Callback, Headers, Logger, Package } from '@verdaccio/types'; import { IProxy, UpLinkConfLocal } from '@verdaccio/dev-types'; const LoggerApi = require('@verdaccio/logger'); -const encode = function(thing): string { +const encode = function (thing): string { return encodeURIComponent(thing).replace(/^%40/, '@'); }; @@ -107,16 +107,16 @@ class ProxyStorage implements IProxy { if (this._statusCheck() === false) { const streamRead = new Stream.Readable(); - process.nextTick(function(): void { + process.nextTick(function (): void { if (cb) { cb(ErrorCode.getInternalError(API_ERROR.UPLINK_OFFLINE)); } streamRead.emit('error', ErrorCode.getInternalError(API_ERROR.UPLINK_OFFLINE)); }); // $FlowFixMe - streamRead._read = function(): void {}; + streamRead._read = function (): void {}; // preventing 'Uncaught, unspecified "error" event' - streamRead.on('error', function(): void {}); + streamRead.on('error', function (): void {}); return streamRead; } @@ -143,64 +143,66 @@ class ProxyStorage implements IProxy { headers['Content-Type'] = headers['Content-Type'] || HEADERS.JSON; } - const requestCallback = cb ? function(err, res, body): void { - let error; - const responseLength = err ? 0 : body.length; - // $FlowFixMe - processBody(); - logActivity(); - // $FlowFixMe - cb(err, res, body); + const requestCallback = cb + ? function (err, res, body): void { + let error; + const responseLength = err ? 0 : body.length; + // $FlowFixMe + processBody(); + logActivity(); + // $FlowFixMe + cb(err, res, body); - /** - * Perform a decode. - */ - function processBody(): void { - if (err) { - error = err.message; - return; - } + /** + * Perform a decode. + */ + function processBody(): void { + if (err) { + error = err.message; + return; + } - if (options.json && res.statusCode < 300) { - try { - // $FlowFixMe - body = JSON.parse(body.toString(CHARACTER_ENCODING.UTF8)); - } catch (_err) { - body = {}; - err = _err; - error = err.message; + if (options.json && res.statusCode < 300) { + try { + // $FlowFixMe + body = JSON.parse(body.toString(CHARACTER_ENCODING.UTF8)); + } catch (_err) { + body = {}; + err = _err; + error = err.message; + } + } + + if (!err && isObject(body)) { + if (_.isString(body.error)) { + error = body.error; + } + } + } + /** + * Perform a log. + */ + function logActivity(): void { + let message = "@{!status}, req: '@{request.method} @{request.url}'"; + // FIXME: use LOG_VERDACCIO_BYTES + message += error ? ', error: @{!error}' : ', bytes: @{bytes.in}/@{bytes.out}'; + self.logger.warn( + { + err: err || undefined, // if error is null/false change this to undefined so it wont log + request: { method: method, url: uri }, + level: 35, // http + status: res != null ? res.statusCode : 'ERR', + error: error, + bytes: { + in: json ? json.length : 0, + out: responseLength || 0, + }, + }, + message + ); } } - - if (!err && isObject(body)) { - if (_.isString(body.error)) { - error = body.error; - } - } - } - /** - * Perform a log. - */ - function logActivity(): void { - let message = "@{!status}, req: '@{request.method} @{request.url}'"; - // FIXME: use LOG_VERDACCIO_BYTES - message += error ? ', error: @{!error}' : ', bytes: @{bytes.in}/@{bytes.out}'; - self.logger.warn( - { - err: err || undefined, // if error is null/false change this to undefined so it wont log - request: { method: method, url: uri }, - level: 35, // http - status: res != null ? res.statusCode : 'ERR', - error: error, - bytes: { - in: json ? json.length : 0, - out: responseLength || 0, - }, - }, - message - ); - } - } : undefined; + : undefined; let requestOptions = { url: uri, @@ -217,14 +219,14 @@ class ProxyStorage implements IProxy { if (this.ca) { requestOptions = Object.assign({}, requestOptions, { - ca: this.ca + ca: this.ca, }); } const req = request(requestOptions, requestCallback); let statusCalled = false; - req.on('response', function(res): void { + req.on('response', function (res): void { // FIXME: _verdaccio_aborted seems not used // @ts-ignore if (!req._verdaccio_aborted && !statusCalled) { @@ -249,7 +251,7 @@ class ProxyStorage implements IProxy { })(); } }); - req.on('error', function(_err): void { + req.on('error', function (_err): void { // FIXME: _verdaccio_aborted seems not used // @ts-ignore if (!req._verdaccio_aborted && !statusCalled) { @@ -465,7 +467,7 @@ class ProxyStorage implements IProxy { }, }); - readStream.on('response', function(res: any) { + readStream.on('response', function (res: any) { if (res.statusCode === HTTP_STATUS.NOT_FOUND) { return stream.emit('error', ErrorCode.getNotFound(API_ERROR.NOT_FILE_UPLINK)); } @@ -480,13 +482,13 @@ class ProxyStorage implements IProxy { readStream.pipe(stream); }); - readStream.on('error', function(err) { + readStream.on('error', function (err) { stream.emit('error', err); }); - readStream.on('data', function(data) { + readStream.on('data', function (data) { current_length += data.length; }); - readStream.on('end', function(data) { + readStream.on('end', function (data) { if (data) { current_length += data.length; } diff --git a/packages/proxy/test/headers.auth.spec.ts b/packages/proxy/test/headers.auth.spec.ts index 3d0d81bab..d1033dc41 100644 --- a/packages/proxy/test/headers.auth.spec.ts +++ b/packages/proxy/test/headers.auth.spec.ts @@ -1,7 +1,7 @@ -import {buildToken} from "@verdaccio/utils"; +import { buildToken } from '@verdaccio/utils'; -import {ERROR_CODE, TOKEN_BASIC, TOKEN_BEARER, DEFAULT_REGISTRY, HEADERS} from "@verdaccio/dev-commons"; -import {setup} from '@verdaccio/logger'; +import { ERROR_CODE, TOKEN_BASIC, TOKEN_BEARER, DEFAULT_REGISTRY, HEADERS } from '@verdaccio/dev-commons'; +import { setup } from '@verdaccio/logger'; import { ProxyStorage } from '../src/up-storage'; @@ -9,7 +9,7 @@ setup([]); function createUplink(config) { const defaultConfig = { - url: DEFAULT_REGISTRY + url: DEFAULT_REGISTRY, }; const mergeConfig = Object.assign({}, defaultConfig, config); // @ts-ignore @@ -20,12 +20,11 @@ function setHeaders(config: unknown = {}, headers: unknown = {}) { const uplink = createUplink(config); // @ts-ignore return uplink._setHeaders({ - headers + headers, }); } describe('uplink headers auth test', () => { - test('if set headers empty should return default headers', () => { const headers = setHeaders(); const keys = Object.keys(headers); @@ -38,46 +37,49 @@ describe('uplink headers auth test', () => { test('if assigns value invalid to attribute auth', () => { const fnError = function () { setHeaders({ - auth: '' + auth: '', }); }; - expect(function ( ) { + expect(function () { fnError(); }).toThrow(Error('Auth invalid')); }); test('if assigns the header authorization', () => { - const headers = setHeaders({}, { - [HEADERS.AUTHORIZATION]: buildToken(TOKEN_BASIC, 'Zm9vX2Jhcg==') - }); + const headers = setHeaders( + {}, + { + [HEADERS.AUTHORIZATION]: buildToken(TOKEN_BASIC, 'Zm9vX2Jhcg=='), + } + ); expect(Object.keys(headers)).toHaveLength(4); expect(headers[HEADERS.AUTHORIZATION]).toEqual(buildToken(TOKEN_BASIC, 'Zm9vX2Jhcg==')); }); - test( - 'if assigns headers authorization and token the header precedes', - () => { - const headers = setHeaders({ + test('if assigns headers authorization and token the header precedes', () => { + const headers = setHeaders( + { auth: { type: TOKEN_BEARER, - token: 'tokenBearer' - } - }, { - [HEADERS.AUTHORIZATION]: buildToken(TOKEN_BASIC, 'tokenBasic') - }); + token: 'tokenBearer', + }, + }, + { + [HEADERS.AUTHORIZATION]: buildToken(TOKEN_BASIC, 'tokenBasic'), + } + ); - expect(headers[HEADERS.AUTHORIZATION]).toEqual(buildToken(TOKEN_BASIC, 'tokenBasic')); - } - ); + expect(headers[HEADERS.AUTHORIZATION]).toEqual(buildToken(TOKEN_BASIC, 'tokenBasic')); + }); test('set type auth basic', () => { const headers = setHeaders({ auth: { type: TOKEN_BASIC, - token: 'Zm9vX2Jhcg==' - } + token: 'Zm9vX2Jhcg==', + }, }); expect(Object.keys(headers)).toHaveLength(4); @@ -88,8 +90,8 @@ describe('uplink headers auth test', () => { const headers = setHeaders({ auth: { type: TOKEN_BEARER, - token: 'Zm9vX2Jhcf===' - } + token: 'Zm9vX2Jhcf===', + }, }); expect(Object.keys(headers)).toHaveLength(4); @@ -97,16 +99,16 @@ describe('uplink headers auth test', () => { }); test('set auth type invalid', () => { - const fnError = function() { + const fnError = function () { setHeaders({ auth: { type: 'null', - token: 'Zm9vX2Jhcf===' - } - }) + token: 'Zm9vX2Jhcf===', + }, + }); }; - expect(function ( ) { + expect(function () { fnError(); }).toThrow(Error(`Auth type 'null' not allowed`)); }); @@ -115,8 +117,8 @@ describe('uplink headers auth test', () => { process.env.NPM_TOKEN = 'myToken'; const headers = setHeaders({ auth: { - type: TOKEN_BEARER - } + type: TOKEN_BEARER, + }, }); expect(headers[HEADERS.AUTHORIZATION]).toBe(buildToken(TOKEN_BEARER, 'myToken')); @@ -128,25 +130,24 @@ describe('uplink headers auth test', () => { const headers = setHeaders({ auth: { type: TOKEN_BASIC, - token_env: 'NPM_TOKEN_TEST' - } + token_env: 'NPM_TOKEN_TEST', + }, }); expect(headers[HEADERS.AUTHORIZATION]).toBe(buildToken(TOKEN_BASIC, 'myTokenTest')); delete process.env.NPM_TOKEN_TEST; }); - test('if token not set', () => { - const fnError = function() { + const fnError = function () { setHeaders({ auth: { - type: TOKEN_BASIC - } + type: TOKEN_BASIC, + }, }); }; - expect(function( ) { + expect(function () { fnError(); }).toThrow(ERROR_CODE.token_required); }); diff --git a/packages/proxy/test/noProxy.spec.ts b/packages/proxy/test/noProxy.spec.ts index dee7b9917..9dc7d7a78 100644 --- a/packages/proxy/test/noProxy.spec.ts +++ b/packages/proxy/test/noProxy.spec.ts @@ -16,81 +16,81 @@ describe('Use proxy', () => { }); test('local config should take priority', () => { - const x = setupProxy('http://x/x', {http_proxy: '123'}, {http_proxy: '456'}); + const x = setupProxy('http://x/x', { http_proxy: '123' }, { http_proxy: '456' }); expect(x.proxy).toEqual('123'); }); test('no_proxy is invalid', () => { - let x = setupProxy('http://x/x', {http_proxy: '123', no_proxy: false}, {}); + let x = setupProxy('http://x/x', { http_proxy: '123', no_proxy: false }, {}); expect(x.proxy).toEqual('123'); - x = setupProxy('http://x/x', {http_proxy: '123', no_proxy: null}, {}); + x = setupProxy('http://x/x', { http_proxy: '123', no_proxy: null }, {}); expect(x.proxy).toEqual('123'); - x = setupProxy('http://x/x', {http_proxy: '123', no_proxy: []}, {}); + x = setupProxy('http://x/x', { http_proxy: '123', no_proxy: [] }, {}); expect(x.proxy).toEqual('123'); - x = setupProxy('http://x/x', {http_proxy: '123', no_proxy: ''}, {}); + x = setupProxy('http://x/x', { http_proxy: '123', no_proxy: '' }, {}); expect(x.proxy).toEqual('123'); }); test('no_proxy - simple/include', () => { - let x = setupProxy('http://localhost', {http_proxy: '123'}, {no_proxy: 'localhost'}); + let x = setupProxy('http://localhost', { http_proxy: '123' }, { no_proxy: 'localhost' }); expect(x.proxy).toEqual(undefined); }); test('no_proxy - simple/not', () => { - let x = setupProxy('http://localhost', {http_proxy: '123'}, {no_proxy: 'blah'}); + let x = setupProxy('http://localhost', { http_proxy: '123' }, { no_proxy: 'blah' }); expect(x.proxy).toEqual('123'); }); test('no_proxy - various, single string', () => { - let x = setupProxy('http://blahblah', {http_proxy: '123'}, {no_proxy: 'blah'}); + let x = setupProxy('http://blahblah', { http_proxy: '123' }, { no_proxy: 'blah' }); expect(x.proxy).toEqual('123'); - x = setupProxy('http://blah.blah', {}, {http_proxy: '123', no_proxy: 'blah'}); + x = setupProxy('http://blah.blah', {}, { http_proxy: '123', no_proxy: 'blah' }); expect(x.proxy).toEqual(undefined); - x = setupProxy('http://blahblah', {}, {http_proxy: '123', no_proxy: '.blah'}); + x = setupProxy('http://blahblah', {}, { http_proxy: '123', no_proxy: '.blah' }); expect(x.proxy).toEqual('123'); - x = setupProxy('http://blah.blah', {http_proxy: '123', no_proxy: '.blah'}, {}); + x = setupProxy('http://blah.blah', { http_proxy: '123', no_proxy: '.blah' }, {}); expect(x.proxy).toEqual(undefined); - x = setupProxy('http://blah', {http_proxy: '123', no_proxy: '.blah'}, {}); + x = setupProxy('http://blah', { http_proxy: '123', no_proxy: '.blah' }, {}); expect(x.proxy).toEqual(undefined); - x = setupProxy('http://blahh', {http_proxy: '123', no_proxy: 'blah'}, {}); + x = setupProxy('http://blahh', { http_proxy: '123', no_proxy: 'blah' }, {}); expect(x.proxy).toEqual('123'); }); test('no_proxy - various, array', () => { - let x = setupProxy('http://blahblah', {http_proxy: '123'}, {no_proxy: 'foo,bar,blah'}); + let x = setupProxy('http://blahblah', { http_proxy: '123' }, { no_proxy: 'foo,bar,blah' }); expect(x.proxy).toEqual('123'); - x = setupProxy('http://blah.blah', {http_proxy: '123'}, {no_proxy: 'foo,bar,blah'}); + x = setupProxy('http://blah.blah', { http_proxy: '123' }, { no_proxy: 'foo,bar,blah' }); expect(x.proxy).toEqual(undefined); - x = setupProxy('http://blah.foo', {http_proxy: '123'}, {no_proxy: 'foo,bar,blah'}); + x = setupProxy('http://blah.foo', { http_proxy: '123' }, { no_proxy: 'foo,bar,blah' }); expect(x.proxy).toEqual(undefined); - x = setupProxy('http://foo.baz', {http_proxy: '123'}, {no_proxy: 'foo,bar,blah'}); + x = setupProxy('http://foo.baz', { http_proxy: '123' }, { no_proxy: 'foo,bar,blah' }); expect(x.proxy).toEqual('123'); - x = setupProxy('http://blahblah', {http_proxy: '123'}, {no_proxy: ['foo', 'bar', 'blah']}); + x = setupProxy('http://blahblah', { http_proxy: '123' }, { no_proxy: ['foo', 'bar', 'blah'] }); expect(x.proxy).toEqual('123'); - x = setupProxy('http://blah.blah', {http_proxy: '123'}, {no_proxy: ['foo', 'bar', 'blah']}); + x = setupProxy('http://blah.blah', { http_proxy: '123' }, { no_proxy: ['foo', 'bar', 'blah'] }); expect(x.proxy).toEqual(undefined); }); test('no_proxy - hostport', () => { - let x = setupProxy('http://localhost:80', {http_proxy: '123'}, {no_proxy: 'localhost'}); + let x = setupProxy('http://localhost:80', { http_proxy: '123' }, { no_proxy: 'localhost' }); expect(x.proxy).toEqual(undefined); - x = setupProxy('http://localhost:8080', {http_proxy: '123'}, {no_proxy: 'localhost'}); + x = setupProxy('http://localhost:8080', { http_proxy: '123' }, { no_proxy: 'localhost' }); expect(x.proxy).toEqual(undefined); }); test('no_proxy - secure', () => { - let x = setupProxy('https://something', {http_proxy: '123'}, {}); + let x = setupProxy('https://something', { http_proxy: '123' }, {}); expect(x.proxy).toEqual(undefined); - x = setupProxy('https://something', {https_proxy: '123'}, {}); + x = setupProxy('https://something', { https_proxy: '123' }, {}); expect(x.proxy).toEqual('123'); - x = setupProxy('https://something', {http_proxy: '456', https_proxy: '123'}, {}); + x = setupProxy('https://something', { http_proxy: '456', https_proxy: '123' }, {}); expect(x.proxy).toEqual('123'); }); }); diff --git a/packages/server/src/debug/index.ts b/packages/server/src/debug/index.ts index f02e016d1..75a154a0e 100644 --- a/packages/server/src/debug/index.ts +++ b/packages/server/src/debug/index.ts @@ -4,23 +4,20 @@ import { $ResponseExtend, $RequestExtend, $NextFunctionVer } from '@verdaccio/de 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, + }); + }); }; diff --git a/packages/server/src/server.ts b/packages/server/src/server.ts index 9071176f8..0ddb59c8c 100644 --- a/packages/server/src/server.ts +++ b/packages/server/src/server.ts @@ -21,7 +21,7 @@ import { log, final, errorReportingMiddleware } from '@verdaccio/middleware'; import hookDebug from './debug'; -const defineAPI = function(config: IConfig, storage: IStorageHandler): any { +const defineAPI = function (config: IConfig, storage: IStorageHandler): any { const auth: IAuth = new Auth(config); const app: Application = express(); // run in production mode by default, just in case @@ -32,14 +32,14 @@ const defineAPI = function(config: IConfig, storage: IStorageHandler): any { // Router setup app.use(log(config)); app.use(errorReportingMiddleware); - app.use(function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + app.use(function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { res.setHeader('X-Powered-By', config.user_agent); next(); }); app.use(compression()); - app.get('/favicon.ico', function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + app.get('/favicon.ico', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { req.url = '/-/static/favicon.png'; next(); }); @@ -55,7 +55,7 @@ const defineAPI = function(config: IConfig, storage: IStorageHandler): any { logger: logger, }; - const plugins: IPluginMiddleware[] = loadPlugin(config, config.middlewares, plugin_params, function(plugin: IPluginMiddleware) { + const plugins: IPluginMiddleware[] = loadPlugin(config, config.middlewares, plugin_params, function (plugin: IPluginMiddleware) { return plugin.register_middlewares; }); plugins.forEach((plugin: IPluginMiddleware) => { @@ -70,17 +70,17 @@ const defineAPI = function(config: IConfig, storage: IStorageHandler): any { app.use('/', renderWebMiddleware(config, auth, storage)); app.use('/-/verdaccio/', webAPI(config, auth, storage)); } else { - app.get('/', function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) { + app.get('/', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) { next(ErrorCode.getNotFound(API_ERROR.WEB_DISABLED)); }); } // Catch 404 - app.get('/*', function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) { + app.get('/*', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) { next(ErrorCode.getNotFound(API_ERROR.FILE_NOT_FOUND)); }); - app.use(function(err: HttpError, req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) { + app.use(function (err: HttpError, req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) { if (_.isError(err)) { if (err.code === 'ECONNABORT' && res.statusCode === HTTP_STATUS.NOT_MODIFIED) { return next(); @@ -102,7 +102,7 @@ const defineAPI = function(config: IConfig, storage: IStorageHandler): any { return app; }; -export default (async function(configHash: any): Promise { +export default (async function (configHash: any): Promise { setup(configHash.logs); const config: IConfig = new AppConfig(_.cloneDeep(configHash)); // register middleware plugins diff --git a/packages/server/test/api/helpers/publish-api.js b/packages/server/test/api/helpers/publish-api.js index 13da4e7bf..099fc4124 100644 --- a/packages/server/test/api/helpers/publish-api.js +++ b/packages/server/test/api/helpers/publish-api.js @@ -1,53 +1,50 @@ const json = { - "_id": "@scope\/pk1-test", - "name": "@scope\/pk1-test", - "description": "", - "dist-tags": { - "latest": "1.0.6" + _id: '@scope/pk1-test', + name: '@scope/pk1-test', + description: '', + 'dist-tags': { + latest: '1.0.6', }, - "versions": { - "1.0.6": { - "name": "@scope\/pk1-test", - "version": "1.0.6", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + versions: { + '1.0.6': { + name: '@scope/pk1-test', + version: '1.0.6', + description: '', + main: 'index.js', + scripts: { + test: 'echo "Error: no test specified" && exit 1', }, - "keywords": [ - - ], - "author": { - "name": "User NPM", - "email": "user@domain.com" + keywords: [], + author: { + name: 'User NPM', + email: 'user@domain.com', }, - "license": "ISC", - "dependencies": { - "verdaccio": "^2.7.2" + license: 'ISC', + dependencies: { + verdaccio: '^2.7.2', }, - "readme": "# test", - "readmeFilename": "README.md", - "_id": "@scope\/pk1-test@1.0.6", - "_npmVersion": "5.5.1", - "_nodeVersion": "8.7.0", - "_npmUser": { - + readme: '# test', + readmeFilename: 'README.md', + _id: '@scope/pk1-test@1.0.6', + _npmVersion: '5.5.1', + _nodeVersion: '8.7.0', + _npmUser: {}, + dist: { + integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + shasum: '2c03764f651a9f016ca0b7620421457b619151b9', + tarball: 'http://localhost:5555/@scope/pk1-test/-/@scope/pk1-test-1.0.6.tgz', }, - "dist": { - "integrity": "sha512-6gHiERpiDgtb3hjqpQH5\/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==", - "shasum": "2c03764f651a9f016ca0b7620421457b619151b9", - "tarball": "http:\/\/localhost:5555\/@scope\/pk1-test\/-\/@scope\/pk1-test-1.0.6.tgz" - } - } + }, }, - "readme": "# test", - "_attachments": { - "@scope\/pk1-test-1.0.6.tgz": { - "content_type": "application\/octet-stream", - "data": "H4sIAAAAAAAAE+2W32vbMBDH85y\/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo\/\/79KPeQsnIw5KUDX\/9IOvurLuz\/DHSjK\/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1aW8eML+Vv10m9oF\/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0ScCdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI\/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yoEHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS\/pLQe+D+FIv\/agIWI6GX66kFuIhT+1gDjrp\/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0\/jWiAK8OcMjt8MW3OlfQppcuhhQ6k+2OgkK2Q8DssFPi\/IHpU9fz3\/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6\/f88f\/Pu47zomiPk2Lv\/dOv8h+P\/34\/D\/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=", - "length": 512 - } - } -} + readme: '# test', + _attachments: { + '@scope/pk1-test-1.0.6.tgz': { + content_type: 'application/octet-stream', + data: + 'H4sIAAAAAAAAE+2W32vbMBDH85y/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo//79KPeQsnIw5KUDX/9IOvurLuz/DHSjK/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1aW8eML+Vv10m9oF/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0ScCdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yoEHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS/pLQe+D+FIv/agIWI6GX66kFuIhT+1gDjrp/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0/jWiAK8OcMjt8MW3OlfQppcuhhQ6k+2OgkK2Q8DssFPi/IHpU9fz3/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6/f88f/Pu47zomiPk2Lv/dOv8h+P/34/D/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=', + length: 512, + }, + }, +}; module.exports = json; diff --git a/packages/server/test/api/helpers/utils.ts b/packages/server/test/api/helpers/utils.ts index 6f8a90504..225c21d36 100644 --- a/packages/server/test/api/helpers/utils.ts +++ b/packages/server/test/api/helpers/utils.ts @@ -1,37 +1,36 @@ -import { Package } from "@verdaccio/types"; - +import { Package } from '@verdaccio/types'; export function generateVersion(pkgName, version) { - return { - "name": pkgName, - "version": version, - "description": "some foo dependency", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": { - "name": "User NPM", - "email": "user@domain.com" - }, - "license": "ISC", - "dependencies": { - "verdaccio": "^4.0.0" - }, - "readme": "# test", - "readmeFilename": "README.md", - "_id": `${pkgName}@${version}`, - "_npmVersion": "5.5.1", - "_npmUser": { - 'name': 'foo', - }, - "dist": { - "integrity": "sha512-6gHiERpiDgtb3hjqpQH5\/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==", - "shasum": "2c03764f651a9f016ca0b7620421457b619151b9", // pragma: allowlist secret - "tarball": `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz` - } - } + return { + name: pkgName, + version: version, + description: 'some foo dependency', + main: 'index.js', + scripts: { + test: 'echo "Error: no test specified" && exit 1', + }, + keywords: [], + author: { + name: 'User NPM', + email: 'user@domain.com', + }, + license: 'ISC', + dependencies: { + verdaccio: '^4.0.0', + }, + readme: '# test', + readmeFilename: 'README.md', + _id: `${pkgName}@${version}`, + _npmVersion: '5.5.1', + _npmUser: { + name: 'foo', + }, + dist: { + integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + shasum: '2c03764f651a9f016ca0b7620421457b619151b9', // pragma: allowlist secret + tarball: `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz`, + }, + }; } /** @@ -41,88 +40,87 @@ export function generateVersion(pkgName, version) { * @param _versions */ export function generatePackageUnpublish(pkgName: string, _versions: string[] = ['1.0.0']): Package { - const latest: string = _versions[_versions.length - 1]; - const versions = _versions.reduce((cat, version) => { - cat[version] = generateVersion(pkgName, version); - return cat; - }, {}); + const latest: string = _versions[_versions.length - 1]; + const versions = _versions.reduce((cat, version) => { + cat[version] = generateVersion(pkgName, version); + return cat; + }, {}); - // @ts-ignore - return { - "_id": pkgName, - "name": pkgName, - "readme": "# test", - // users usually is present when run npm star [pkg] - "users": {}, - "dist-tags": { - "latest": latest - }, - "versions": versions, - } + // @ts-ignore + return { + _id: pkgName, + name: pkgName, + readme: '# test', + // users usually is present when run npm star [pkg] + users: {}, + 'dist-tags': { + latest: latest, + }, + versions: versions, + }; } export function generateStarMedatada(pkgName: string, users): any { - return { - "_id": pkgName, - "_rev": "3-b0cdaefc9bdb77c8", - "users": users - } + return { + _id: pkgName, + _rev: '3-b0cdaefc9bdb77c8', + users: users, + }; } export function generatePackageMetadata(pkgName: string, version = '1.0.0'): Package { - // @ts-ignore - return { - "_id": pkgName, - "name": pkgName, - "dist-tags": { - "latest": version - }, - "versions": { - [version]: { - "name": pkgName, - "version": version, - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - - ], - "author": { - "name": "User NPM", - "email": "user@domain.com" - }, - "license": "ISC", - "dependencies": { - "verdaccio": "^2.7.2" - }, - "readme": "# test", - "readmeFilename": "README.md", - "_id": `${pkgName}@${version}`, - "_npmVersion": "5.5.1", - "_npmUser": { - 'name': 'foo', - }, - "dist": { - "integrity": "sha512-6gHiERpiDgtb3hjqpQH5\/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==", - "shasum": "2c03764f651a9f016ca0b7620421457b619151b9", // pragma: allowlist secret - "tarball": `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz` - } - } - }, - "readme": "# test", - "_attachments": { - [`${pkgName}-${version}.tgz`]: { - "content_type": "application\/octet-stream", - "data": "H4sIAAAAAAAAE+2W32vbMBDH85y\/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo\/\/79KPeQsnIw5KUDX\/9IOvurLuz\/DHSjK\/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1aW8eML+Vv10m9oF\/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0ScCdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI\/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yoEHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS\/pLQe+D+FIv\/agIWI6GX66kFuIhT+1gDjrp\/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0\/jWiAK8OcMjt8MW3OlfQppcuhhQ6k+2OgkK2Q8DssFPi\/IHpU9fz3\/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6\/f88f\/Pu47zomiPk2Lv\/dOv8h+P\/34\/D\/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=", - "length": 512 - } - } - } + // @ts-ignore + return { + _id: pkgName, + name: pkgName, + 'dist-tags': { + latest: version, + }, + versions: { + [version]: { + name: pkgName, + version: version, + description: '', + main: 'index.js', + scripts: { + test: 'echo "Error: no test specified" && exit 1', + }, + keywords: [], + author: { + name: 'User NPM', + email: 'user@domain.com', + }, + license: 'ISC', + dependencies: { + verdaccio: '^2.7.2', + }, + readme: '# test', + readmeFilename: 'README.md', + _id: `${pkgName}@${version}`, + _npmVersion: '5.5.1', + _npmUser: { + name: 'foo', + }, + dist: { + integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + shasum: '2c03764f651a9f016ca0b7620421457b619151b9', // pragma: allowlist secret + tarball: `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz`, + }, + }, + }, + readme: '# test', + _attachments: { + [`${pkgName}-${version}.tgz`]: { + content_type: 'application/octet-stream', + data: + 'H4sIAAAAAAAAE+2W32vbMBDH85y/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo//79KPeQsnIw5KUDX/9IOvurLuz/DHSjK/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1aW8eML+Vv10m9oF/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0ScCdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yoEHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS/pLQe+D+FIv/agIWI6GX66kFuIhT+1gDjrp/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0/jWiAK8OcMjt8MW3OlfQppcuhhQ6k+2OgkK2Q8DssFPi/IHpU9fz3/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6/f88f/Pu47zomiPk2Lv/dOv8h+P/34/D/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=', + length: 512, + }, + }, + }; } -export function generateDeprecateMetadata(pkgName: string, version = '1.0.0', deprecated:string = ''): Package { +export function generateDeprecateMetadata(pkgName: string, version = '1.0.0', deprecated: string = ''): Package { const res = { ...generatePackageMetadata(pkgName, version), _attachments: {}, diff --git a/packages/server/test/api/index.spec.ts b/packages/server/test/api/index.spec.ts index 2bd3b21a4..f4b942f43 100644 --- a/packages/server/test/api/index.spec.ts +++ b/packages/server/test/api/index.spec.ts @@ -2,20 +2,15 @@ import path from 'path'; import request from 'supertest'; import _ from 'lodash'; -import { - HEADERS, - HTTP_STATUS, - HEADER_TYPE, - API_MESSAGE, - TOKEN_BEARER, -} from '@verdaccio/dev-commons'; -import {buildToken, encodeScopedUri} from '@verdaccio/utils'; -import {setup, logger} from '@verdaccio/logger'; +import { HEADERS, HTTP_STATUS, HEADER_TYPE, API_MESSAGE, TOKEN_BEARER } from '@verdaccio/dev-commons'; +import { buildToken, encodeScopedUri } from '@verdaccio/utils'; +import { setup, logger } from '@verdaccio/logger'; -import {mockServer} from '@verdaccio/mock'; +import { mockServer } from '@verdaccio/mock'; import { - configExample, DOMAIN_SERVERS, + configExample, + DOMAIN_SERVERS, getNewToken, getPackage, putPackage, @@ -24,15 +19,9 @@ import { generateUnPublishURI, } from '@verdaccio/mock'; -import publishMetadata from './helpers/publish-api'; -import { - generateDeprecateMetadata, - generatePackageMetadata, - generatePackageUnpublish, - generateStarMedatada, generateVersion -} from './helpers/utils'; - import endPointAPI from '../../src'; +import publishMetadata from './helpers/publish-api'; +import { generateDeprecateMetadata, generatePackageMetadata, generatePackageUnpublish, generateStarMedatada, generateVersion } from './helpers/utils'; setup([]); @@ -53,24 +42,28 @@ describe('endpoint unit test', () => { let app; let mockRegistry; - beforeAll(async function(done) { + beforeAll(async function (done) { const store = generateRamdonStorage(); const mockServerPort = 55549; - const configForTest = configExample({ - filters: { - [path.join(__dirname, './plugin/filter')]: { - pkg: 'npm_test', - version: '2.0.0' - } + const configForTest = configExample( + { + filters: { + [path.join(__dirname, './plugin/filter')]: { + pkg: 'npm_test', + version: '2.0.0', + }, + }, + storage: store, + self_path: store, + uplinks: { + npmjs: { + url: `http://${DOMAIN_SERVERS}:${mockServerPort}`, + }, + }, }, - storage: store, - self_path: store, - uplinks: { - npmjs: { - url: `http://${DOMAIN_SERVERS}:${mockServerPort}` - } - } - }, 'api.spec.yaml', __dirname); + 'api.spec.yaml', + __dirname + ); app = await endPointAPI(configForTest); const binPath = require.resolve('verdaccio/bin/verdaccio'); @@ -79,7 +72,7 @@ describe('endpoint unit test', () => { done(); }); - afterAll(function(done) { + afterAll(function (done) { const [registry, pid] = mockRegistry; registry.stop(); logger.info(`registry ${pid} has been stopped`); @@ -96,7 +89,7 @@ describe('endpoint unit test', () => { .set(HEADERS.AUTHORIZATION, 'FakeHader') .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .expect(HTTP_STATUS.FORBIDDEN) - .end(function(err, res) { + .end(function (err, res) { expect(res.body.error).toBeDefined(); expect(res.body.error).toMatch(/authorization required to access package auth-package/); done(); @@ -109,7 +102,7 @@ describe('endpoint unit test', () => { .set(HEADERS.AUTHORIZATION, TOKEN_BEARER) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .expect(HTTP_STATUS.FORBIDDEN) - .end(function(err, res) { + .end(function (err, res) { expect(res.body.error).toBeDefined(); expect(res.body.error).toMatch(/authorization required to access package auth-package/); done(); @@ -122,7 +115,7 @@ describe('endpoint unit test', () => { .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, '12345')) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .expect(HTTP_STATUS.FORBIDDEN) - .end(function(err, res) { + .end(function (err, res) { expect(res.body.error).toBeDefined(); expect(res.body.error).toMatch(/authorization required to access package auth-package/); done(); @@ -130,14 +123,13 @@ describe('endpoint unit test', () => { }); }); - test('should test add a new user', (done) => { request(app) .put(`/-/user/org.couchdb.user:${credentials.name}`) .send(credentials) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { + .end(function (err, res) { if (err) { return done(err); } @@ -154,7 +146,7 @@ describe('endpoint unit test', () => { .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { expect(err).toBeNull(); expect(res.body).toBeDefined(); expect(res.body.name).toMatch(/vue/); @@ -173,13 +165,12 @@ describe('endpoint unit test', () => { // proxy: npmjs 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) { + .end(function (err, res) { if (err) { return done(err); } @@ -191,13 +182,12 @@ describe('endpoint unit test', () => { }); test('should fetch jquery specific version package from remote uplink', (done) => { - request(app) .get('/jquery/1.5.1') .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { if (err) { return done(err); } @@ -209,13 +199,12 @@ describe('endpoint unit test', () => { }); test('should fetch jquery specific tag package from remote uplink', (done) => { - request(app) .get('/jquery/latest') .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { if (err) { return done(err); } @@ -227,13 +216,12 @@ describe('endpoint unit test', () => { }); test('should fails on fetch jquery specific tag package from remote uplink', (done) => { - request(app) .get('/jquery/never-will-exist-this-tag') .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.NOT_FOUND) - .end(function(err) { + .end(function (err) { if (err) { return done(err); } @@ -242,13 +230,12 @@ describe('endpoint unit test', () => { }); test('should not found a unexisting remote package under scope', (done) => { - request(app) .get('/@verdaccio/not-found') .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.NOT_FOUND) - .end(function(err) { + .end(function (err) { if (err) { return done(err); } @@ -263,7 +250,7 @@ describe('endpoint unit test', () => { .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { if (err) { return done(err); } @@ -275,12 +262,12 @@ describe('endpoint unit test', () => { test('should not found when a filter fails', (done) => { request(app) - // Filter errors look like other uplink errors + // Filter errors look like other uplink errors .get('/trigger-filter-failure') .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.NOT_FOUND) - .end(function(err) { + .end(function (err) { if (err) { return done(err); } @@ -290,13 +277,12 @@ describe('endpoint unit test', () => { }); test('should forbid access to remote package', (done) => { - request(app) .get('/forbidden-place') .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.UNAUTHORIZED) - .end(function(err) { + .end(function (err) { if (err) { return done(err); } @@ -305,12 +291,11 @@ describe('endpoint unit test', () => { }); test('should fetch a tarball from remote uplink', (done) => { - request(app) .get('/jquery/-/jquery-1.5.1.tgz') .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.OCTET_STREAM) .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { if (err) { return done(err); } @@ -321,12 +306,11 @@ describe('endpoint unit test', () => { }); test('should fetch a scoped tarball from remote uplink', (done) => { - request(app) .get('/@jquery/jquery/-/@jquery/jquery-1.5.1.tgz') .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.OCTET_STREAM) .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { if (err) { return done(err); } @@ -337,12 +321,11 @@ describe('endpoint unit test', () => { }); test('should fails fetch a tarball from remote uplink', (done) => { - request(app) .get('/jquery/-/jquery-not-found-tarball-0.0.1.tgz') .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.OCTET_STREAM) .expect(HTTP_STATUS.NOT_FOUND) - .end(function(err) { + .end(function (err) { if (err) { expect(err).not.toBeNull(); return done(err); @@ -351,20 +334,19 @@ describe('endpoint unit test', () => { done(); }); }); - }); describe('should test dist-tag api', () => { const jqueryVersion = '2.1.2'; const jqueryUpdatedVersion = { - 'beta': '3.0.0', - 'jota': '1.6.3' + beta: '3.0.0', + jota: '1.6.3', }; test('should set a new tag on jquery', (done) => { putVersion(app, '/jquery/verdaccio-tag', jqueryVersion) .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { + .end(function (err, res) { if (err) { expect(err).toBeNull(); return done(err); @@ -377,13 +359,12 @@ describe('endpoint unit test', () => { }); test('should fetch all tag for jquery', (done) => { - request(app) .get('/-/package/jquery/dist-tags') .set('accept-encoding', HEADERS.JSON) .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { if (err) { expect(err).toBeNull(); return done(err); @@ -396,13 +377,12 @@ describe('endpoint unit test', () => { }); test('should update a new tag on jquery', (done) => { - request(app) .post('/-/package/jquery/dist-tags') .send(JSON.stringify(jqueryUpdatedVersion)) .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { + .end(function (err, res) { if (err) { expect(err).toBeNull(); return done(err); @@ -415,13 +395,12 @@ describe('endpoint unit test', () => { }); test('should fetch all tags for jquery and ccheck previous update', (done) => { - request(app) .get('/-/package/jquery/dist-tags') .set('accept-encoding', HEADERS.JSON) .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { if (err) { expect(err).toBeNull(); return done(err); @@ -434,14 +413,13 @@ describe('endpoint unit test', () => { }); test('should set a remove a tag on jquery', (done) => { - request(app) .del('/-/package/jquery/dist-tags/verdaccio-tag') .set('accept-encoding', HEADERS.JSON) .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) // .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { + .end(function (err, res) { if (err) { expect(err).toBeNull(); return done(err); @@ -452,7 +430,6 @@ describe('endpoint unit test', () => { done(); }); }); - }); describe('should test search api', () => { @@ -465,7 +442,7 @@ describe('endpoint unit test', () => { // .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .expect(HEADERS.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.OK) - .end(function(err) { + .end(function (err) { if (err) { expect(err).toBeNull(); return done(err); @@ -475,7 +452,6 @@ describe('endpoint unit test', () => { done(); }); }); - }); describe('should test publish/unpublish api', () => { @@ -494,14 +470,13 @@ describe('endpoint unit test', () => { } const newVersion = '2.0.1'; - const [newErr] = await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, - generatePackageMetadata(pkgName, newVersion), token); + const [newErr] = await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, generatePackageMetadata(pkgName, newVersion), token); if (newErr) { expect(newErr).toBeNull(); return done(newErr); } - const deletePayload = generatePackageUnpublish(pkgName, ['2.0.0']); + const deletePayload = generatePackageUnpublish(pkgName, ['2.0.0']); const [err2, res2] = await putPackage(request(app), generateUnPublishURI(pkgName), deletePayload, token); expect(err2).toBeNull(); @@ -551,14 +526,13 @@ describe('endpoint unit test', () => { const newVersion = '1.0.0'; const token = await getNewToken(request(app), credentials); - const [newErr] = await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, - generatePackageMetadata(pkgName, newVersion), token); + const [newErr] = await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, generatePackageMetadata(pkgName, newVersion), token); if (newErr) { expect(newErr).toBeNull(); return done(newErr); } - const deletePayload = generatePackageUnpublish(pkgName, ['2.0.0']); + const deletePayload = generatePackageUnpublish(pkgName, ['2.0.0']); const [err2, res2] = await putPackage(request(app), generateUnPublishURI(pkgName), deletePayload, token); expect(err2).not.toBeNull(); @@ -588,8 +562,7 @@ describe('endpoint unit test', () => { const newVersion = '1.0.0'; const token = await getNewToken(request(app), credentials); - const [newErr, resp] = await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, - generatePackageMetadata(pkgName, newVersion), token); + const [newErr, resp] = await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, generatePackageMetadata(pkgName, newVersion), token); expect(newErr).not.toBeNull(); expect(resp.body.error).toMatch(/user jota_only_unpublish_fail is not allowed to publish package only-unpublish/); @@ -604,11 +577,15 @@ describe('endpoint unit test', () => { .put('/super-admin-can-unpublish') .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) - .send(JSON.stringify(_.assign({}, publishMetadata, { - name: 'super-admin-can-unpublish' - }))) + .send( + JSON.stringify( + _.assign({}, publishMetadata, { + name: 'super-admin-can-unpublish', + }) + ) + ) .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { + .end(function (err, res) { if (err) { expect(err).toBeNull(); return done(err); @@ -622,7 +599,7 @@ describe('endpoint unit test', () => { .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { + .end(function (err, res) { expect(err).toBeNull(); expect(res.body.ok).toBeDefined(); expect(res.body.ok).toMatch(API_MESSAGE.PKG_REMOVED); @@ -638,11 +615,15 @@ describe('endpoint unit test', () => { .put('/all-can-unpublish') .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) - .send(JSON.stringify(_.assign({}, publishMetadata, { - name: 'all-can-unpublish' - }))) + .send( + JSON.stringify( + _.assign({}, publishMetadata, { + name: 'all-can-unpublish', + }) + ) + ) .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { + .end(function (err, res) { if (err) { expect(err).toBeNull(); return done(err); @@ -656,7 +637,7 @@ describe('endpoint unit test', () => { .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { + .end(function (err, res) { expect(err).toBeNull(); expect(res.body.ok).toBeDefined(); expect(res.body.ok).toMatch(API_MESSAGE.PKG_REMOVED); @@ -667,91 +648,98 @@ describe('endpoint unit test', () => { }); describe('should test star and stars api', () => { - const pkgName = '@scope/starPackage'; - const credentials = { name: 'jota_star', password: 'secretPass' }; - let token = ''; - beforeAll(async (done) =>{ - token = await getNewToken(request(app), credentials); - await putPackage(request(app), `/${pkgName}`, generatePackageMetadata(pkgName), token); + const pkgName = '@scope/starPackage'; + const credentials = { name: 'jota_star', password: 'secretPass' }; + let token = ''; + beforeAll(async (done) => { + token = await getNewToken(request(app), credentials); + await putPackage(request(app), `/${pkgName}`, generatePackageMetadata(pkgName), token); + done(); + }); + + test('should star a package', (done) => { + request(app) + .put(`/${pkgName}`) + .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .send( + JSON.stringify( + generateStarMedatada(pkgName, { + [credentials.name]: true, + }) + ) + ) + .expect(HTTP_STATUS.OK) + .end(function (err, res) { + if (err) { + expect(err).toBeNull(); + return done(err); + } + expect(res.body.success).toBeDefined(); + expect(res.body.success).toBeTruthy(); done(); - }); + }); + }); - test('should star a package', (done) => { - request(app) - .put(`/${pkgName}`) - .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .send(JSON.stringify(generateStarMedatada(pkgName, { - [credentials.name]: true - }))) - .expect(HTTP_STATUS.OK) - .end(function(err, res) { - if (err) { - expect(err).toBeNull(); - return done(err); - } - expect(res.body.success).toBeDefined(); - expect(res.body.success).toBeTruthy(); - done(); - }); - }); + test('should unstar a package', (done) => { + request(app) + .put(`/${pkgName}`) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) + .send(JSON.stringify(generateStarMedatada(pkgName, {}))) + .expect(HTTP_STATUS.OK) + .end(function (err, res) { + if (err) { + expect(err).toBeNull(); + return done(err); + } + expect(res.body.success).toBeDefined(); + expect(res.body.success).toBeTruthy(); + done(); + }); + }); - test('should unstar a package', (done) => { + test('should retrieve stars list with credentials', async (done) => { + request(app) + .put(`/${pkgName}`) + .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .send(generateStarMedatada(pkgName, { [credentials.name]: true })) + .expect(HTTP_STATUS.OK) + .end(function (err) { + if (err) { + expect(err).toBeNull(); + return done(err); + } request(app) - .put(`/${pkgName}`) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) - .send(JSON.stringify(generateStarMedatada(pkgName, {}))) - .expect(HTTP_STATUS.OK) - .end(function(err, res) { - if (err) { - expect(err).toBeNull(); - return done(err); - } - expect(res.body.success).toBeDefined(); - expect(res.body.success).toBeTruthy(); - done(); - }); - }); - - test('should retrieve stars list with credentials', async (done) => { - request(app) - .put(`/${pkgName}`) - .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .send(generateStarMedatada(pkgName, {[credentials.name]: true})) - .expect(HTTP_STATUS.OK).end(function(err) { + .get('/-/_view/starredByUser') + .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .send( + JSON.stringify({ + key: [credentials.name], + }) + ) + .expect(HTTP_STATUS.OK) + .end(function (err, res) { if (err) { - expect(err).toBeNull(); - return done(err); + expect(err).toBeNull(); + return done(err); } - request(app) - .get('/-/_view/starredByUser') - .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .send(JSON.stringify({ - key: [credentials.name] - })) - .expect(HTTP_STATUS.OK) - .end(function(err, res) { - if (err) { - expect(err).toBeNull(); - return done(err); - } - expect(res.body.rows).toBeDefined(); - expect(res.body.rows).toHaveLength(1); - done(); - }); - }); - }); + expect(res.body.rows).toBeDefined(); + expect(res.body.rows).toHaveLength(1); + done(); + }); + }); + }); }); describe('should test (un)deprecate api', () => { const pkgName = '@scope/deprecate'; const credentials = { name: 'jota_deprecate', password: 'secretPass' }; - const version = '1.0.0' + const version = '1.0.0'; let token = ''; - beforeAll(async (done) =>{ + beforeAll(async (done) => { token = await getNewToken(request(app), credentials); await putPackage(request(app), `/${pkgName}`, generatePackageMetadata(pkgName, version), token); done(); @@ -764,7 +752,7 @@ describe('endpoint unit test', () => { expect(err).toBeNull(); return done(err); } - const [,res] = await getPackage(request(app), '', pkgName); + const [, res] = await getPackage(request(app), '', pkgName); expect(res.body.versions[version].deprecated).toEqual('get deprecated'); done(); }); @@ -778,7 +766,7 @@ describe('endpoint unit test', () => { expect(err).toBeNull(); return done(err); } - const [,res] = await getPackage(request(app), '', pkgName); + const [, res] = await getPackage(request(app), '', pkgName); expect(res.body.versions[version].deprecated).not.toBeDefined(); done(); }); @@ -797,7 +785,7 @@ describe('endpoint unit test', () => { expect(err2).not.toBeNull(); expect(res2.body.error).toBeDefined(); expect(res2.body.error).toMatch(/user only_unpublish is not allowed to publish package @scope\/deprecate/); - }) + }); test('should deprecate multiple packages', async (done) => { await putPackage(request(app), `/${pkgName}`, generatePackageMetadata(pkgName, '1.0.1'), token); @@ -807,11 +795,11 @@ describe('endpoint unit test', () => { deprecated: 'get deprecated', }; await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, pkg, token); - const [,res] = await getPackage(request(app), '', pkgName); + const [, res] = await getPackage(request(app), '', pkgName); expect(res.body.versions[version].deprecated).toEqual('get deprecated'); expect(res.body.versions['1.0.1'].deprecated).toEqual('get deprecated'); - done() - }) + done(); + }); }); }); }); diff --git a/packages/server/test/basic/index.spec.ts b/packages/server/test/basic/index.spec.ts index 9bd557b12..77f970472 100644 --- a/packages/server/test/basic/index.spec.ts +++ b/packages/server/test/basic/index.spec.ts @@ -1,16 +1,14 @@ -import path from "path"; +import path from 'path'; import express from 'express'; import request from 'request'; -import {API_ERROR} from '@verdaccio/dev-commons'; -import {parseConfigFile} from "@verdaccio/utils"; +import { API_ERROR } from '@verdaccio/dev-commons'; +import { parseConfigFile } from '@verdaccio/utils'; import { setup } from '@verdaccio/logger'; import endPointAPI from '../../src'; -setup([ - {type: 'stdout', format: 'pretty', level: 'trace'} -]); +setup([{ type: 'stdout', format: 'pretty', level: 'trace' }]); const app = express(); const server = require('http').createServer(app); @@ -23,10 +21,10 @@ describe('basic system test', () => { let port; jest.setTimeout(20000); - beforeAll(async function(done) { + beforeAll(async function (done) { const config = parseConfigFile(parseConfigurationFile('basic.yaml')); app.use(await endPointAPI(config)); - server.listen(0, function() { + server.listen(0, function () { port = server.address().port; done(); }); @@ -36,24 +34,30 @@ describe('basic system test', () => { server.close(done); }); - test('server should respond on /', done => { - request({ - url: 'http://localhost:' + port + '/', - }, function(err, res, body) { - expect(err).toBeNull(); - expect(body).toMatch(/Verdaccio/); - done(); - }); + test('server should respond on /', (done) => { + request( + { + url: 'http://localhost:' + port + '/', + }, + function (err, res, body) { + expect(err).toBeNull(); + expect(body).toMatch(/Verdaccio/); + done(); + } + ); }); - test('server should respond on /___not_found_package', done => { - request({ - json: true, - url: `http://localhost:${port}/___not_found_package`, - }, function(err, res, body) { - expect(err).toBeNull(); - expect(body.error).toMatch(API_ERROR.NO_PACKAGE); - done(); - }); + test('server should respond on /___not_found_package', (done) => { + request( + { + json: true, + url: `http://localhost:${port}/___not_found_package`, + }, + function (err, res, body) { + expect(err).toBeNull(); + expect(body.error).toMatch(API_ERROR.NO_PACKAGE); + done(); + } + ); }); }); diff --git a/packages/server/test/jwt/index.spec.ts b/packages/server/test/jwt/index.spec.ts index fcb2cf10d..f40aecc62 100644 --- a/packages/server/test/jwt/index.spec.ts +++ b/packages/server/test/jwt/index.spec.ts @@ -1,12 +1,12 @@ import path from 'path'; import request from 'supertest'; -import {HEADERS, HTTP_STATUS, HEADER_TYPE, TOKEN_BEARER, TOKEN_BASIC, API_ERROR} from '@verdaccio/dev-commons'; -import {mockServer, generateRamdonStorage} from '@verdaccio/mock'; -import {buildUserBuffer, buildToken} from '@verdaccio/utils'; -import {configExample, DOMAIN_SERVERS, addUser, getPackage, loginUserToken} from '@verdaccio/mock'; +import { HEADERS, HTTP_STATUS, HEADER_TYPE, TOKEN_BEARER, TOKEN_BASIC, API_ERROR } from '@verdaccio/dev-commons'; +import { mockServer, generateRamdonStorage } from '@verdaccio/mock'; +import { buildUserBuffer, buildToken } from '@verdaccio/utils'; +import { configExample, DOMAIN_SERVERS, addUser, getPackage, loginUserToken } from '@verdaccio/mock'; -import {setup, logger} from '@verdaccio/logger'; +import { setup, logger } from '@verdaccio/logger'; import endPointAPI from '../../src'; @@ -22,18 +22,22 @@ describe('endpoint user auth JWT unit test', () => { let mockRegistry; const FAKE_TOKEN: string = buildToken(TOKEN_BEARER, 'fake'); - beforeAll(async function(done) { + beforeAll(async function (done) { const mockServerPort = 55546; const store = generateRamdonStorage(); - const configForTest = configExample({ - storage: store, - uplinks: { - remote: { - url: `http://${DOMAIN_SERVERS}:${mockServerPort}` - } + const configForTest = configExample( + { + storage: store, + uplinks: { + remote: { + url: `http://${DOMAIN_SERVERS}:${mockServerPort}`, + }, + }, + self_path: store, }, - self_path: store - }, 'jwt.yaml', __dirname); + 'jwt.yaml', + __dirname + ); app = await endPointAPI(configForTest); const binPath = require.resolve('verdaccio/bin/verdaccio'); @@ -42,7 +46,7 @@ describe('endpoint user auth JWT unit test', () => { done(); }); - afterAll(function(done) { + afterAll(function (done) { const [registry, pid] = mockRegistry; registry.stop(); logger.info(`registry ${pid} has been stopped`); @@ -86,12 +90,13 @@ describe('endpoint user auth JWT unit test', () => { const token = buildUserBuffer(credentials.name, credentials.password).toString('base64'); // put should exist in request // @ts-ignore - request(app).put(`/-/user/org.couchdb.user:${credentials.name}/-rev/undefined`) + request(app) + .put(`/-/user/org.couchdb.user:${credentials.name}/-rev/undefined`) .send(credentials) .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BASIC, token)) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { + .end(function (err, res) { expect(err).toBeNull(); expect(res.body.ok).toBeDefined(); expect(res.body.token).toBeDefined(); diff --git a/packages/server/test/package-access/index.spec.ts b/packages/server/test/package-access/index.spec.ts index 01b0e8df3..6afda6475 100644 --- a/packages/server/test/package-access/index.spec.ts +++ b/packages/server/test/package-access/index.spec.ts @@ -1,16 +1,14 @@ import path from 'path'; import request from 'supertest'; -import {setup, logger} from '@verdaccio/logger' +import { setup, logger } from '@verdaccio/logger'; setup([]); import { HEADERS, HTTP_STATUS } from '@verdaccio/dev-commons'; +import { generateRamdonStorage, mockServer, configExample, DOMAIN_SERVERS } from '@verdaccio/mock'; import endPointAPI from '../../src'; -import {generateRamdonStorage, mockServer, configExample, DOMAIN_SERVERS} from '@verdaccio/mock'; - - describe('api with no limited access configuration', () => { let app; let mockRegistry; @@ -19,14 +17,18 @@ describe('api with no limited access configuration', () => { beforeAll(async (done) => { const mockServerPort = 55530; - const configForTest = configExample({ - self_path: store, - uplinks: { - remote: { - url: `http://${DOMAIN_SERVERS}:${mockServerPort}` - } + const configForTest = configExample( + { + self_path: store, + uplinks: { + remote: { + url: `http://${DOMAIN_SERVERS}:${mockServerPort}`, + }, + }, }, - }, 'pkg.access.yaml', __dirname); + 'pkg.access.yaml', + __dirname + ); app = await endPointAPI(configForTest); const binPath = require.resolve('verdaccio/bin/verdaccio'); @@ -35,8 +37,7 @@ describe('api with no limited access configuration', () => { done(); }); - - afterAll(function(done) { + afterAll(function (done) { const [registry, pid] = mockRegistry; registry.stop(); logger.info(`registry ${pid} has been stopped`); @@ -45,16 +46,14 @@ describe('api with no limited access configuration', () => { }); describe('test proxy packages partially restricted', () => { - - test('should test fails on fetch endpoint /-/not-found', (done) => { request(app) - // @ts-ignore + // @ts-ignore .get('/not-found-for-sure') .set(HEADERS.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HEADERS.CONTENT_TYPE, /json/) .expect(HTTP_STATUS.NOT_FOUND) - .end(function(err) { + .end(function (err) { if (err) { return done(err); } @@ -70,7 +69,7 @@ describe('api with no limited access configuration', () => { .set(HEADERS.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HEADERS.CONTENT_TYPE, /json/) .expect(HTTP_STATUS.OK) - .end(function(err) { + .end(function (err) { if (err) { return done(err); } @@ -86,7 +85,7 @@ describe('api with no limited access configuration', () => { .set(HEADERS.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HEADERS.CONTENT_TYPE, /json/) .expect(HTTP_STATUS.OK) - .end(function(err) { + .end(function (err) { if (err) { return done(err); } @@ -95,5 +94,4 @@ describe('api with no limited access configuration', () => { }); }); }); - }); diff --git a/packages/server/test/profile/index.spec.ts b/packages/server/test/profile/index.spec.ts index f59f9215f..dd603d72a 100644 --- a/packages/server/test/profile/index.spec.ts +++ b/packages/server/test/profile/index.spec.ts @@ -1,17 +1,16 @@ import path from 'path'; import request from 'supertest'; -import {mockServer} from '@verdaccio/mock'; -import {API_ERROR, HTTP_STATUS, SUPPORT_ERRORS} from '@verdaccio/dev-commons'; -import {setup, logger} from '@verdaccio/logger'; +import { mockServer } from '@verdaccio/mock'; +import { API_ERROR, HTTP_STATUS, SUPPORT_ERRORS } from '@verdaccio/dev-commons'; +import { setup, logger } from '@verdaccio/logger'; -import {generateRamdonStorage, getNewToken, getProfile, postProfile, configExample, DOMAIN_SERVERS} from '@verdaccio/mock'; +import { generateRamdonStorage, getNewToken, getProfile, postProfile, configExample, DOMAIN_SERVERS } from '@verdaccio/mock'; import endPointAPI from '../../src'; setup([]); - describe('endpoint user profile', () => { let app; let mockRegistry; @@ -20,15 +19,19 @@ describe('endpoint user profile', () => { beforeAll(async (done) => { const store = generateRamdonStorage(); const mockServerPort = 55544; - const configForTest = configExample({ - storage: store, - uplinks: { - remote: { - url: `http://${DOMAIN_SERVERS}:${mockServerPort}` - } + const configForTest = configExample( + { + storage: store, + uplinks: { + remote: { + url: `http://${DOMAIN_SERVERS}:${mockServerPort}`, + }, + }, + self_path: store, }, - self_path: store - }, 'profile.yaml', __dirname); + 'profile.yaml', + __dirname + ); app = await endPointAPI(configForTest); const binPath = require.resolve('verdaccio/bin/verdaccio'); @@ -37,7 +40,7 @@ describe('endpoint user profile', () => { done(); }); - afterAll(function(done) { + afterAll(function (done) { const [registry, pid] = mockRegistry; registry.stop(); logger.info(`registry ${pid} has been stopped`); @@ -45,7 +48,6 @@ describe('endpoint user profile', () => { done(); }); - test('should fetch a profile of logged user', async (done) => { const credentials = { name: 'JotaJWT', password: 'secretPass' }; const token = await getNewToken(request(app), credentials); @@ -62,7 +64,7 @@ describe('endpoint user profile', () => { password: { new: '12345678', old: credentials.password, - } + }, }; const token = await getNewToken(request(app), credentials); const [err1, res1] = await postProfile(request(app), body, token); @@ -78,7 +80,7 @@ describe('endpoint user profile', () => { password: { new: 'p1', old: credentials.password, - } + }, }; const token = await getNewToken(request(app), credentials); const [, resp] = await postProfile(request(app), body, token, HTTP_STATUS.UNAUTHORIZED); @@ -94,7 +96,7 @@ describe('endpoint user profile', () => { test('should report TFA is disabled', async (done) => { const credentials = { name: 'userTest2002', password: 'secretPass002' }; const body = { - tfa: {} + tfa: {}, }; const token = await getNewToken(request(app), credentials); const [, resp] = await postProfile(request(app), body, token, HTTP_STATUS.SERVICE_UNAVAILABLE); diff --git a/packages/server/test/proxy/index.spec.ts b/packages/server/test/proxy/index.spec.ts index 05ec415d1..d047c0d57 100644 --- a/packages/server/test/proxy/index.spec.ts +++ b/packages/server/test/proxy/index.spec.ts @@ -1,14 +1,14 @@ -import path from "path"; +import path from 'path'; import _ from 'lodash'; import { Config as AppConfig } from '@verdaccio/config'; -import {Config, UpLinkConf} from '@verdaccio/types'; +import { Config, UpLinkConf } from '@verdaccio/types'; import { VerdaccioError } from '@verdaccio/commons-api'; -import {IProxy} from '@verdaccio/dev-types'; -import { API_ERROR, HTTP_STATUS } from "@verdaccio/dev-commons"; +import { IProxy } from '@verdaccio/dev-types'; +import { API_ERROR, HTTP_STATUS } from '@verdaccio/dev-commons'; import { mockServer, configExample, DOMAIN_SERVERS } from '@verdaccio/mock'; import { ProxyStorage } from '@verdaccio/proxy'; -import {setup, logger} from '@verdaccio/logger'; +import { setup, logger } from '@verdaccio/logger'; setup([]); @@ -16,7 +16,7 @@ describe('UpStorge', () => { const mockServerPort = 55547; let mockRegistry; const uplinkDefault = { - url: `http://0.0.0.0:${mockServerPort}` + url: `http://0.0.0.0:${mockServerPort}`, }; const generateProxy = (config: UpLinkConf = uplinkDefault) => { const appConfig: Config = new AppConfig(configExample()); @@ -30,7 +30,7 @@ describe('UpStorge', () => { mockRegistry = await mockServer(mockServerPort, { storePath, silence: true }).init(binPath); }); - afterAll(function(done) { + afterAll(function (done) { const [registry, pid] = mockRegistry; registry.stop(); logger.info(`registry ${pid} has been stopped`); @@ -59,7 +59,7 @@ describe('UpStorge', () => { test('should be get remote metadata with etag', (done) => { const proxy = generateProxy(); - proxy.getRemoteMetadata('jquery', {etag: '123456'}, (err, data, etag) => { + proxy.getRemoteMetadata('jquery', { etag: '123456' }, (err, data, etag) => { expect(err).toBeNull(); expect(_.isString(etag)).toBeTruthy(); expect(data.name).toBe('jquery'); @@ -70,7 +70,7 @@ describe('UpStorge', () => { test('should be get remote metadata package does not exist', (done) => { const proxy = generateProxy(); - proxy.getRemoteMetadata('@verdaccio/fake-package', {etag: '123456'}, (err) => { + proxy.getRemoteMetadata('@verdaccio/fake-package', { etag: '123456' }, (err) => { expect(err).not.toBeNull(); expect(err.statusCode).toBe(HTTP_STATUS.NOT_FOUND); expect(err.message).toMatch(API_ERROR.NOT_PACKAGE_UPLINK); @@ -79,23 +79,21 @@ describe('UpStorge', () => { }); }); - describe('UpStorge::fetchTarball', () => { test('should fetch a tarball from uplink', (done) => { const proxy = generateProxy(); const tarball = `http://${DOMAIN_SERVERS}:${mockServerPort}/jquery/-/jquery-1.5.1.tgz`; const stream = proxy.fetchTarball(tarball); - stream.on('error', function(err) { + stream.on('error', function (err) { expect(err).toBeNull(); done(); }); - stream.on('content-length', function(contentLength) { + stream.on('content-length', function (contentLength) { expect(contentLength).toBeDefined(); done(); }); - }); test('should throw a 404 on fetch a tarball from uplink', (done) => { @@ -103,7 +101,7 @@ describe('UpStorge', () => { const tarball = `http://${DOMAIN_SERVERS}:${mockServerPort}/jquery/-/no-exist-1.5.1.tgz`; const stream = proxy.fetchTarball(tarball); - stream.on('error', function(err: VerdaccioError) { + stream.on('error', function (err: VerdaccioError) { expect(err).not.toBeNull(); expect(err.statusCode).toBe(HTTP_STATUS.NOT_FOUND); expect(err.message).toMatch(API_ERROR.NOT_FILE_UPLINK); @@ -111,11 +109,10 @@ describe('UpStorge', () => { done(); }); - stream.on('content-length', function(contentLength) { + stream.on('content-length', function (contentLength) { expect(contentLength).toBeDefined(); done(); }); - }); test('should be offline uplink', (done) => { @@ -126,14 +123,14 @@ describe('UpStorge', () => { // to test a uplink is offline we have to be try 3 times // the default failed request are set to 2 - process.nextTick(function() { - stream.on('error', function(err) { + process.nextTick(function () { + stream.on('error', function (err) { expect(err).not.toBeNull(); // expect(err.statusCode).toBe(404); expect(proxy.failed_requests).toBe(1); const streamSecondTry = proxy.fetchTarball(tarball); - streamSecondTry.on('error', function(err) { + streamSecondTry.on('error', function (err) { expect(err).not.toBeNull(); /* code: 'ENOTFOUND', @@ -142,7 +139,7 @@ describe('UpStorge', () => { // expect(err.statusCode).toBe(404); expect(proxy.failed_requests).toBe(2); const streamThirdTry = proxy.fetchTarball(tarball); - streamThirdTry.on('error', function(err: VerdaccioError) { + streamThirdTry.on('error', function (err: VerdaccioError) { expect(err).not.toBeNull(); expect(err.statusCode).toBe(HTTP_STATUS.INTERNAL_ERROR); expect(proxy.failed_requests).toBe(2); @@ -156,16 +153,13 @@ describe('UpStorge', () => { }); describe('UpStorge::isUplinkValid', () => { - describe('valid use cases', () => { - const validateUpLink = ( - url: string, - tarBallUrl = `${url}/artifactory/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz`) => { + const validateUpLink = (url: string, tarBallUrl = `${url}/artifactory/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz`) => { const uplinkConf = { url }; const proxy: IProxy = generateProxy(uplinkConf); return proxy.isUplinkValid(tarBallUrl); - } + }; test('should validate tarball path against uplink', () => { expect(validateUpLink('https://artifactory.mydomain.com')).toBe(true); @@ -190,8 +184,7 @@ describe('UpStorge', () => { // corner case https://github.com/verdaccio/verdaccio/issues/571 test('should validate tarball path against uplink case#6', () => { // same protocol, same domain, port === 443 which is also the standard for https - expect(validateUpLink('https://my.domain.test', - `https://my.domain.test:443/artifactory/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz`)).toBe(true); + expect(validateUpLink('https://my.domain.test', `https://my.domain.test:443/artifactory/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz`)).toBe(true); }); test('should validate tarball path against uplink case#7', () => { @@ -253,7 +246,5 @@ describe('UpStorge', () => { expect(proxy.isUplinkValid(tarBallUrl)).toBe(false); }); }); - }); - }); diff --git a/packages/server/test/storage/index.spec.ts b/packages/server/test/storage/index.spec.ts index 094cad50e..e2a37bcf6 100644 --- a/packages/server/test/storage/index.spec.ts +++ b/packages/server/test/storage/index.spec.ts @@ -1,69 +1,35 @@ import path from 'path'; import fs from 'fs'; -import {Writable} from 'stream'; +import { Writable } from 'stream'; import { Config as AppConfig } from '@verdaccio/config'; import { Storage } from '@verdaccio/store'; -import {IStorageHandler} from '@verdaccio/dev-types'; +import { IStorageHandler } from '@verdaccio/dev-types'; -import {Config} from '@verdaccio/types'; -import {API_ERROR, HTTP_STATUS} from '@verdaccio/dev-commons'; -import {mockServer, configExample, DOMAIN_SERVERS, generateRamdonStorage} from '@verdaccio/mock'; +import { Config } from '@verdaccio/types'; +import { API_ERROR, HTTP_STATUS } from '@verdaccio/dev-commons'; +import { mockServer, configExample, DOMAIN_SERVERS, generateRamdonStorage } from '@verdaccio/mock'; -import {setup, logger} from '@verdaccio/logger'; +import { setup, logger } from '@verdaccio/logger'; setup([]); - const mockServerPort = 55548; -const generateStorage = async function() { +const generateStorage = async function () { const storagePath = generateRamdonStorage(); - const storageConfig = configExample({ - self_path: storagePath, - storage: storagePath, - uplinks: { - npmjs: { - url: `http://${DOMAIN_SERVERS}:${mockServerPort}` - } - } - }, 'store.spec.yaml', __dirname); - - const config: Config = new AppConfig(storageConfig); - const store: IStorageHandler = new Storage(config); - await store.init(config, []); - - return store; -}; - -const generateSameUplinkStorage = async function() { - const storagePath = generateRamdonStorage(); - console.log("-->storagePath", storagePath); - const storageConfig = configExample({ - self_path: storagePath, - storage: storagePath, - packages: { - jquery: { - access: ['$all'], - publish: ['$all'], - proxy: ['cached'], + const storageConfig = configExample( + { + self_path: storagePath, + storage: storagePath, + uplinks: { + npmjs: { + url: `http://${DOMAIN_SERVERS}:${mockServerPort}`, + }, }, - '@jquery/*': { - access: ['$all'], - publish: ['$all'], - proxy: ['notcached'], - } }, - uplinks: { - cached: { - url: `http://${DOMAIN_SERVERS}:${mockServerPort}`, - cache: true, - }, - notcached: { - url: `http://${DOMAIN_SERVERS}:${mockServerPort}`, - cache: false, - } - } - }, 'store.spec.yaml', __dirname); + 'store.spec.yaml', + __dirname + ); const config: Config = new AppConfig(storageConfig); const store: IStorageHandler = new Storage(config); @@ -72,23 +38,65 @@ const generateSameUplinkStorage = async function() { return store; }; -const createNullStream = () => new Writable({ - write: function(chunk, encoding, next) { - next(); - } -}); +const generateSameUplinkStorage = async function () { + const storagePath = generateRamdonStorage(); + console.log('-->storagePath', storagePath); + const storageConfig = configExample( + { + self_path: storagePath, + storage: storagePath, + packages: { + jquery: { + access: ['$all'], + publish: ['$all'], + proxy: ['cached'], + }, + '@jquery/*': { + access: ['$all'], + publish: ['$all'], + proxy: ['notcached'], + }, + }, + uplinks: { + cached: { + url: `http://${DOMAIN_SERVERS}:${mockServerPort}`, + cache: true, + }, + notcached: { + url: `http://${DOMAIN_SERVERS}:${mockServerPort}`, + cache: false, + }, + }, + }, + 'store.spec.yaml', + __dirname + ); + + const config: Config = new AppConfig(storageConfig); + const store: IStorageHandler = new Storage(config); + await store.init(config, []); + + return store; +}; + +const createNullStream = () => + new Writable({ + write: function (chunk, encoding, next) { + next(); + }, + }); describe('StorageTest', () => { let mockRegistry; - beforeAll(async done => { + beforeAll(async (done) => { const binPath = require.resolve('verdaccio/bin/verdaccio'); const storePath = path.join(__dirname, '/mock/store'); mockRegistry = await mockServer(mockServerPort, { storePath, silence: true }).init(binPath); done(); }); - afterAll(function(done) { + afterAll(function (done) { const [registry, pid] = mockRegistry; registry.stop(); logger.info(`registry ${pid} has been stopped`); @@ -185,7 +193,7 @@ describe('StorageTest', () => { test.skip('should not touch if the package exists and has no uplinks', async (done) => { const storagePath = generateRamdonStorage(); - const storage: IStorageHandler = await generateStorage() as IStorageHandler; + const storage: IStorageHandler = (await generateStorage()) as IStorageHandler; const metadataSource = path.join(__dirname, '../../partials/metadata'); const metadataPath = path.join(storagePath, 'npm_test/package.json'); diff --git a/packages/server/test/token/index.spec.ts b/packages/server/test/token/index.spec.ts index 65b27be70..8fef17b99 100644 --- a/packages/server/test/token/index.spec.ts +++ b/packages/server/test/token/index.spec.ts @@ -2,16 +2,12 @@ import path from 'path'; import request from 'supertest'; import _ from 'lodash'; -import { - HEADERS, - HTTP_STATUS, - HEADER_TYPE, TOKEN_BEARER, API_ERROR, SUPPORT_ERRORS, -} from '@verdaccio/dev-commons'; +import { HEADERS, HTTP_STATUS, HEADER_TYPE, TOKEN_BEARER, API_ERROR, SUPPORT_ERRORS } from '@verdaccio/dev-commons'; -import {buildToken} from '@verdaccio/utils'; -import {generateRamdonStorage, DOMAIN_SERVERS, mockServer, getNewToken, configExample} from '@verdaccio/mock'; +import { buildToken } from '@verdaccio/utils'; +import { generateRamdonStorage, DOMAIN_SERVERS, mockServer, getNewToken, configExample } from '@verdaccio/mock'; -import {setup, logger} from '@verdaccio/logger'; +import { setup, logger } from '@verdaccio/logger'; import endPointAPI from '../../src'; @@ -27,13 +23,13 @@ const generateTokenCLI = async (app, token, payload): Promise => { .send(JSON.stringify(payload)) .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .end(function(err, resp) { + .end(function (err, resp) { if (err) { return reject([err, resp]); } resolve([err, resp]); }); - }); + }); }; const deleteTokenCLI = async (app, token, tokenToDelete): Promise => { @@ -43,7 +39,7 @@ const deleteTokenCLI = async (app, token, tokenToDelete): Promise => { .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .end(function(err, resp) { + .end(function (err, resp) { if (err) { return reject([err, resp]); } @@ -57,18 +53,22 @@ describe('endpoint unit test', () => { let mockRegistry; let token; - beforeAll(async function(done) { + beforeAll(async function (done) { const store = generateRamdonStorage(); const mockServerPort = 55543; - const configForTest = configExample({ - storage: store, - self_path: store, - uplinks: { - npmjs: { - url: `http://${DOMAIN_SERVERS}:${mockServerPort}` - } - } - }, 'token.spec.yaml', __dirname); + const configForTest = configExample( + { + storage: store, + self_path: store, + uplinks: { + npmjs: { + url: `http://${DOMAIN_SERVERS}:${mockServerPort}`, + }, + }, + }, + 'token.spec.yaml', + __dirname + ); app = await endPointAPI(configForTest); const binPath = require.resolve('verdaccio/bin/verdaccio'); @@ -78,7 +78,7 @@ describe('endpoint unit test', () => { done(); }); - afterAll(function(done) { + afterAll(function (done) { const [registry, pid] = mockRegistry; registry.stop(); logger.info(`registry ${pid} has been stopped`); @@ -93,12 +93,12 @@ describe('endpoint unit test', () => { .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.OK) - .end(function(err, resp) { + .end(function (err, resp) { if (err) { return done(err); } - const { objects, urls} = resp.body; + const { objects, urls } = resp.body; expect(objects).toHaveLength(0); expect(urls.next).toEqual(''); done(); @@ -109,7 +109,7 @@ describe('endpoint unit test', () => { await generateTokenCLI(app, token, { password: credentials.password, readonly: false, - cidr_whitelist: [] + cidr_whitelist: [], }); request(app) @@ -117,12 +117,12 @@ describe('endpoint unit test', () => { .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.OK) - .end(function(err, resp) { + .end(function (err, resp) { if (err) { return done(err); } - const { objects, urls} = resp.body; + const { objects, urls } = resp.body; expect(objects).toHaveLength(1); const [tokenGenerated] = objects; @@ -141,7 +141,7 @@ describe('endpoint unit test', () => { const res = await generateTokenCLI(app, token, { password: credentials.password, readonly: false, - cidr_whitelist: [] + cidr_whitelist: [], }); const t = res[1].body.token; @@ -153,7 +153,7 @@ describe('endpoint unit test', () => { .set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token)) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(HTTP_STATUS.OK) - .end(function(err) { + .end(function (err) { if (err) { return done(err); } @@ -171,7 +171,7 @@ describe('endpoint unit test', () => { await generateTokenCLI(app, token, { password: 'wrongPassword', readonly: false, - cidr_whitelist: [] + cidr_whitelist: [], }); done(); } catch (e) { @@ -187,7 +187,7 @@ describe('endpoint unit test', () => { try { const res = await generateTokenCLI(app, token, { password: credentials.password, - cidr_whitelist: [] + cidr_whitelist: [], }); expect(res[0]).toBeNull(); diff --git a/packages/server/test/web/index.spec.ts b/packages/server/test/web/index.spec.ts index c889c965f..3945854a7 100644 --- a/packages/server/test/web/index.spec.ts +++ b/packages/server/test/web/index.spec.ts @@ -1,12 +1,11 @@ import path from 'path'; import request from 'supertest'; +import { HEADERS, API_ERROR, HTTP_STATUS, HEADER_TYPE, DIST_TAGS } from '@verdaccio/dev-commons'; -import { HEADERS, API_ERROR, HTTP_STATUS, HEADER_TYPE, DIST_TAGS} from '@verdaccio/dev-commons'; +import { addUser, mockServer, DOMAIN_SERVERS, configExample, generateRamdonStorage } from '@verdaccio/mock'; -import {addUser, mockServer, DOMAIN_SERVERS, configExample, generateRamdonStorage} from '@verdaccio/mock'; - -import {setup, logger} from '@verdaccio/logger'; +import { setup, logger } from '@verdaccio/logger'; import endPointAPI from '../../src'; import forbiddenPlace from './partials/forbidden-place'; import publishMetadata from './partials/publish-api'; @@ -23,15 +22,19 @@ describe('endpoint web unit test', () => { beforeAll(async (done) => { const store = generateRamdonStorage(); const mockServerPort = 55523; - const configForTest = configExample({ - storage: store, - self_path: store, - uplinks: { - remote: { - url: `http://${DOMAIN_SERVERS}:${mockServerPort}` - } + const configForTest = configExample( + { + storage: store, + self_path: store, + uplinks: { + remote: { + url: `http://${DOMAIN_SERVERS}:${mockServerPort}`, + }, + }, }, - }, 'web.yaml', __dirname); + 'web.yaml', + __dirname + ); app = await endPointAPI(configForTest); const binPath = require.resolve('verdaccio/bin/verdaccio'); const storePath = path.join(__dirname, '/mock/store'); @@ -39,7 +42,7 @@ describe('endpoint web unit test', () => { done(); }); - afterAll(function(done) { + afterAll(function (done) { const [registry, pid] = mockRegistry; registry.stop(); logger.info(`registry ${pid} has been stopped`); @@ -55,19 +58,15 @@ describe('endpoint web unit test', () => { .send(JSON.stringify(publishMetadata)) .expect(HTTP_STATUS.CREATED); - await request(app) - .put('/forbidden-place') - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .send(JSON.stringify(forbiddenPlace)) - .expect(HTTP_STATUS.CREATED); + await request(app).put('/forbidden-place').set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON).send(JSON.stringify(forbiddenPlace)).expect(HTTP_STATUS.CREATED); }); describe('Packages', () => { test('should display all packages', (done) => { request(app) - .get('/-/verdaccio/packages' ) + .get('/-/verdaccio/packages') .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { expect(res.body).toHaveLength(1); done(); }); @@ -78,7 +77,7 @@ describe('endpoint web unit test', () => { .get('/-/verdaccio/package/readme/@scope/pk1-test') .expect(HTTP_STATUS.OK) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_CHARSET) - .end(function(err, res) { + .end(function (err, res) { expect(res.text).toMatch('

test

\n'); done(); }); @@ -90,7 +89,7 @@ describe('endpoint web unit test', () => { .get('/-/verdaccio/package/readme/@scope/404') .expect(HTTP_STATUS.OK) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_CHARSET) - .end(function(err, res) { + .end(function (err, res) { expect(res.body.error).toMatch(API_ERROR.NO_PACKAGE); done(); }); @@ -101,7 +100,7 @@ describe('endpoint web unit test', () => { .get('/-/verdaccio/sidebar/@scope/pk1-test') .expect(HTTP_STATUS.OK) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .end(function(err, res) { + .end(function (err, res) { // console.log("-->", res); // expect(err).toBeNull(); @@ -121,7 +120,7 @@ describe('endpoint web unit test', () => { .get('/-/verdaccio/sidebar/@scope/pk1-test?v=1.0.6') .expect(HTTP_STATUS.OK) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .end(function(err, res) { + .end(function (err, res) { const sideBarInfo = res.body; const latestVersion = publishMetadata.versions[publishMetadata[DIST_TAGS].latest]; @@ -138,7 +137,7 @@ describe('endpoint web unit test', () => { .get('/-/verdaccio/sidebar/@scope/404') .expect(HTTP_STATUS.NOT_FOUND) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .end(function() { + .end(function () { done(); }); }); @@ -148,19 +147,18 @@ describe('endpoint web unit test', () => { .get('/-/verdaccio/sidebar/@scope/pk1-test?v=0.0.0-not-found') .expect(HTTP_STATUS.NOT_FOUND) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) - .end(function() { + .end(function () { done(); }); }); }); describe('Search', () => { - test('should search pk1-test', (done) => { request(app) .get('/-/verdaccio/search/scope') .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { expect(res.body).toHaveLength(1); done(); }); @@ -170,7 +168,7 @@ describe('endpoint web unit test', () => { request(app) .get('/-/verdaccio/search/@') .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { // in a normal world, the output would be 1 // https://github.com/verdaccio/verdaccio/issues/345 // should fix this @@ -183,7 +181,7 @@ describe('endpoint web unit test', () => { request(app) .get('/-/verdaccio/search/forbidden-place') .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { // this is expected since we are not logged // and forbidden-place is allow_access: 'nobody' expect(res.body).toHaveLength(0); @@ -203,10 +201,10 @@ describe('endpoint web unit test', () => { .post('/-/verdaccio/login') .send({ username: credentials.name, - password: credentials.password + password: credentials.password, }) .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { expect(err).toBeNull(); expect(res.body.error).toBeUndefined(); expect(res.body.token).toBeDefined(); @@ -219,13 +217,15 @@ describe('endpoint web unit test', () => { test('should fails on log unvalid user', (done) => { request(app) .post('/-/verdaccio/login') - .send(JSON.stringify({ - username: 'fake', - password: 'fake' - })) + .send( + JSON.stringify({ + username: 'fake', + password: 'fake', + }) + ) // FIXME: there should be 401 .expect(HTTP_STATUS.OK) - .end(function(err, res) { + .end(function (err, res) { expect(res.body.error).toMatch(/bad username\/password, access denied/); done(); }); diff --git a/packages/store/src/local-storage.ts b/packages/store/src/local-storage.ts index 5cb6a5a88..d1edc281c 100644 --- a/packages/store/src/local-storage.ts +++ b/packages/store/src/local-storage.ts @@ -2,7 +2,7 @@ import assert from 'assert'; import UrlNode from 'url'; import _ from 'lodash'; import { ErrorCode, isObject, getLatestVersion, tagVersion, validateName } from '@verdaccio/utils'; -import {API_ERROR, DIST_TAGS, HTTP_STATUS, STORAGE, SUPPORT_ERRORS, USERS} from '@verdaccio/dev-commons'; +import { API_ERROR, DIST_TAGS, HTTP_STATUS, STORAGE, SUPPORT_ERRORS, USERS } from '@verdaccio/dev-commons'; import { createTarballHash } from '@verdaccio/utils'; import { loadPlugin } from '@verdaccio/loaders'; import LocalDatabase from '@verdaccio/local-storage'; @@ -24,19 +24,20 @@ import { Author, CallbackAction, onSearchPackage, - onEndSearchPackage, StorageUpdateCallback, + onEndSearchPackage, + StorageUpdateCallback, } from '@verdaccio/types'; import { IStorage, StringValue } from '@verdaccio/dev-types'; import { VerdaccioError } from '@verdaccio/commons-api'; import { - prepareSearchPackage , + prepareSearchPackage, generatePackageTemplate, normalizePackage, generateRevision, getLatestReadme, cleanUpReadme, - normalizeContributors + normalizeContributors, } from './storage-utils'; /** @@ -60,7 +61,7 @@ class LocalStorage implements IStorage { return callback(ErrorCode.getNotFound('this package cannot be added')); } - storage.createPackage(name, generatePackageTemplate(name), err => { + storage.createPackage(name, generatePackageTemplate(name), (err) => { // FIXME: it will be fixed here https://github.com/verdaccio/verdaccio/pull/1360 // @ts-ignore if (_.isNull(err) === false && (err.code === STORAGE.FILE_EXIST_ERROR || err.code === HTTP_STATUS.CONFLICT)) { @@ -200,7 +201,7 @@ class LocalStorage implements IStorage { if (change) { this.logger.debug({ name }, 'updating package @{name} info'); - this._writePackage(name, packageLocalJson, function(err): void { + this._writePackage(name, packageLocalJson, function (err): void { callback(err, packageLocalJson); }); } else { @@ -337,11 +338,11 @@ class LocalStorage implements IStorage { */ public changePackage(name: string, incomingPkg: Package, revision: string | void, callback: Callback): void { if (!isObject(incomingPkg.versions) || !isObject(incomingPkg[DIST_TAGS])) { - this.logger.debug({name}, `changePackage bad data for @{name}`); + this.logger.debug({ name }, `changePackage bad data for @{name}`); return callback(ErrorCode.getBadData()); } - this.logger.debug({name}, `changePackage udapting package for @{name}`); + this.logger.debug({ name }, `changePackage udapting package for @{name}`); this._updatePackage( name, (localData: Package, cb: CallbackAction): void => { @@ -378,7 +379,7 @@ class LocalStorage implements IStorage { localData[DIST_TAGS] = incomingPkg[DIST_TAGS]; cb(null); }, - function(err): void { + function (err): void { if (err) { return callback(err); } @@ -434,10 +435,10 @@ class LocalStorage implements IStorage { const _transform = uploadStream._transform; const storage = this._getLocalStorage(name); - uploadStream.abort = function(): void {}; - uploadStream.done = function(): void {}; + uploadStream.abort = function (): void {}; + uploadStream.done = function (): void {}; - uploadStream._transform = function(data, ...args): void { + uploadStream._transform = function (data, ...args): void { shaOneHash.update(data); // measure the length for validation reasons length += data.length; @@ -463,15 +464,15 @@ class LocalStorage implements IStorage { const writeStream: IUploadTarball = storage.writeTarball(filename); - writeStream.on('error', err => { + writeStream.on('error', (err) => { // @ts-ignore if (err.code === STORAGE.FILE_EXIST_ERROR || err.code === HTTP_STATUS.CONFLICT) { uploadStream.emit('error', ErrorCode.getConflict()); uploadStream.abort(); - // @ts-ignore + // @ts-ignore } else if (err.code === STORAGE.NO_SUCH_FILE_ERROR || err.code === HTTP_STATUS.NOT_FOUND) { // check if package exists to throw an appropriate message - this.getPackageMetadata(name, function(_err: VerdaccioError, _res: Package): void { + this.getPackageMetadata(name, function (_err: VerdaccioError, _res: Package): void { if (_err) { uploadStream.emit('error', _err); } else { @@ -483,7 +484,7 @@ class LocalStorage implements IStorage { } }); - writeStream.on('open', function(): void { + writeStream.on('open', function (): void { // re-emitting open because it's handled in storage.js uploadStream.emit('open'); }); @@ -497,7 +498,7 @@ class LocalStorage implements IStorage { }; cb(null); }, - function(err): void { + function (err): void { if (err) { uploadStream.emit('error', err); } else { @@ -507,11 +508,11 @@ class LocalStorage implements IStorage { ); }); - uploadStream.abort = function(): void { + uploadStream.abort = function (): void { writeStream.abort(); }; - uploadStream.done = function(): void { + uploadStream.done = function (): void { if (!length) { uploadStream.emit('error', ErrorCode.getBadData('refusing to accept zero-length file')); writeStream.abort(); @@ -569,13 +570,13 @@ class LocalStorage implements IStorage { const readTarballStream = storage.readTarball(filename); const e404 = ErrorCode.getNotFound; - stream.abort = function(): void { + stream.abort = function (): void { if (_.isNil(readTarballStream) === false) { readTarballStream.abort(); } }; - readTarballStream.on('error', function(err) { + readTarballStream.on('error', function (err) { // @ts-ignore if (err.code === STORAGE.NO_SUCH_FILE_ERROR || err.code === HTTP_STATUS.NOT_FOUND) { stream.emit('error', e404('no such file available')); @@ -584,11 +585,11 @@ class LocalStorage implements IStorage { } }); - readTarballStream.on('content-length', function(content): void { + readTarballStream.on('content-length', function (content): void { stream.emit('content-length', content); }); - readTarballStream.on('open', function(): void { + readTarballStream.on('open', function (): void { // re-emitting open because it's handled in storage.js stream.emit('open'); readTarballStream.pipe(stream); @@ -786,21 +787,21 @@ class LocalStorage implements IStorage { } private _deleteAttachments(storage: any, attachments: string[], callback: Callback): void { - this.logger.debug({l: attachments.length }, `[storage/_deleteAttachments] delete attachments total: @{l}`); - const unlinkNext = function(cb): void { + this.logger.debug({ l: attachments.length }, `[storage/_deleteAttachments] delete attachments total: @{l}`); + const unlinkNext = function (cb): void { if (_.isEmpty(attachments)) { return cb(); } const attachment = attachments.shift(); - storage.deletePackage(attachment, function(): void { + storage.deletePackage(attachment, function (): void { unlinkNext(cb); }); }; - unlinkNext(function(): void { + unlinkNext(function (): void { // try to unlink the directory, but ignore errors because it can fail - storage.removePackage(function(err): void { + storage.removePackage(function (err): void { callback(err); }); }); @@ -849,10 +850,14 @@ class LocalStorage implements IStorage { logger: this.logger, }; - const plugins: IPluginStorage[] = loadPlugin>(this.config, this.config.store, plugin_params, (plugin): IPluginStorage => { - return plugin.getPackageStorage; - }); - + const plugins: IPluginStorage[] = loadPlugin>( + this.config, + this.config.store, + plugin_params, + (plugin): IPluginStorage => { + return plugin.getPackageStorage; + } + ); return _.head(plugins); } diff --git a/packages/store/src/search.ts b/packages/store/src/search.ts index 4b912a32f..3cb99c6db 100644 --- a/packages/store/src/search.ts +++ b/packages/store/src/search.ts @@ -103,6 +103,4 @@ class Search implements IWebSearch { const SearchInstance = new Search(); -export { - SearchInstance -} +export { SearchInstance }; diff --git a/packages/store/src/storage-utils.ts b/packages/store/src/storage-utils.ts index e1c1fc590..50d6dbbd8 100644 --- a/packages/store/src/storage-utils.ts +++ b/packages/store/src/storage-utils.ts @@ -29,15 +29,13 @@ export function generatePackageTemplate(name: string): Package { export function normalizePackage(pkg: Package): Package { const pkgProperties = ['versions', 'dist-tags', '_distfiles', '_attachments', '_uplinks', 'time']; - pkgProperties.forEach( - (key): void => { - const pkgProp = pkg[key]; + pkgProperties.forEach((key): void => { + const pkgProp = pkg[key]; - if (_.isNil(pkgProp) || isObject(pkgProp) === false) { - pkg[key] = {}; - } + if (_.isNil(pkgProp) || isObject(pkgProp) === false) { + pkg[key] = {}; } - ); + }); if (_.isString(pkg._rev) === false) { pkg._rev = STORAGE.DEFAULT_REVISION; @@ -71,7 +69,7 @@ export function getLatestReadme(pkg: Package): string { // In case of empty readme - trying to get ANY readme in the following order: 'next','beta','alpha','test','dev','canary' const readmeDistTagsPriority = ['next', 'beta', 'alpha', 'test', 'dev', 'canary']; - readmeDistTagsPriority.forEach(function(tag): string | void { + readmeDistTagsPriority.forEach(function (tag): string | void { if (readme) { return readme; } @@ -131,80 +129,62 @@ export function cleanUpLinksRef(keepUpLinkData: boolean, result: Package): Packa * @param {*} localStorage */ export function checkPackageLocal(name: string, localStorage: IStorage): Promise { - return new Promise( - (resolve, reject): void => { - localStorage.getPackageMetadata( - name, - (err, results): void => { - if (!_.isNil(err) && err.status !== HTTP_STATUS.NOT_FOUND) { - return reject(err); - } - if (results) { - return reject(ErrorCode.getConflict(API_ERROR.PACKAGE_EXIST)); - } - return resolve(); - } - ); - } - ); + return new Promise((resolve, reject): void => { + localStorage.getPackageMetadata(name, (err, results): void => { + if (!_.isNil(err) && err.status !== HTTP_STATUS.NOT_FOUND) { + return reject(err); + } + if (results) { + return reject(ErrorCode.getConflict(API_ERROR.PACKAGE_EXIST)); + } + return resolve(); + }); + }); } export function publishPackage(name: string, metadata: any, localStorage: IStorage): Promise { - return new Promise( - (resolve, reject): void => { - localStorage.addPackage( - name, - metadata, - (err, latest): void => { - if (!_.isNull(err)) { - return reject(err); - } else if (!_.isUndefined(latest)) { - SearchInstance.add(latest); - } - return resolve(); - } - ); - } - ); + return new Promise((resolve, reject): void => { + localStorage.addPackage(name, metadata, (err, latest): void => { + if (!_.isNull(err)) { + return reject(err); + } else if (!_.isUndefined(latest)) { + SearchInstance.add(latest); + } + return resolve(); + }); + }); } export function checkPackageRemote(name: string, isAllowPublishOffline: boolean, syncMetadata: Function): Promise { - return new Promise( - (resolve, reject): void => { - syncMetadata( - name, - null, - {}, - (err, packageJsonLocal, upLinksErrors): void => { - // something weird - if (err && err.status !== HTTP_STATUS.NOT_FOUND) { - return reject(err); - } + return new Promise((resolve, reject): void => { + syncMetadata(name, null, {}, (err, packageJsonLocal, upLinksErrors): void => { + // something weird + if (err && err.status !== HTTP_STATUS.NOT_FOUND) { + return reject(err); + } - // checking package exist already - if (_.isNil(packageJsonLocal) === false) { - return reject(ErrorCode.getConflict(API_ERROR.PACKAGE_EXIST)); - } + // checking package exist already + if (_.isNil(packageJsonLocal) === false) { + return reject(ErrorCode.getConflict(API_ERROR.PACKAGE_EXIST)); + } - for (let errorItem = 0; errorItem < upLinksErrors.length; errorItem++) { - // checking error - // if uplink fails with a status other than 404, we report failure - if (_.isNil(upLinksErrors[errorItem][0]) === false) { - if (upLinksErrors[errorItem][0].status !== HTTP_STATUS.NOT_FOUND) { - if (isAllowPublishOffline) { - return resolve(); - } - - return reject(ErrorCode.getServiceUnavailable(API_ERROR.UPLINK_OFFLINE_PUBLISH)); - } + for (let errorItem = 0; errorItem < upLinksErrors.length; errorItem++) { + // checking error + // if uplink fails with a status other than 404, we report failure + if (_.isNil(upLinksErrors[errorItem][0]) === false) { + if (upLinksErrors[errorItem][0].status !== HTTP_STATUS.NOT_FOUND) { + if (isAllowPublishOffline) { + return resolve(); } - } - return resolve(); + return reject(ErrorCode.getServiceUnavailable(API_ERROR.UPLINK_OFFLINE_PUBLISH)); + } } - ); - } - ); + } + + return resolve(); + }); + }); } export function mergeUplinkTimeIntoLocal(localMetadata: Package, remoteMetadata: Package): any { diff --git a/packages/store/src/storage.ts b/packages/store/src/storage.ts index 74244314e..084f9f223 100644 --- a/packages/store/src/storage.ts +++ b/packages/store/src/storage.ts @@ -5,31 +5,18 @@ import _ from 'lodash'; import { ProxyStorage } from '@verdaccio/proxy'; import { API_ERROR, HTTP_STATUS, DIST_TAGS } from '@verdaccio/dev-commons'; import { ReadTarball } from '@verdaccio/streams'; -import { - ErrorCode, - normalizeDistTags, - validateMetadata, - isObject, - hasProxyTo, -} from '@verdaccio/utils'; +import { ErrorCode, normalizeDistTags, validateMetadata, isObject, hasProxyTo } from '@verdaccio/utils'; import { setupUpLinks, updateVersionsHiddenUpLink } from '@verdaccio/proxy'; import { IReadTarball, IUploadTarball, Versions, Package, Config, MergeTags, Version, DistFile, Callback, Logger } from '@verdaccio/types'; import { IStorage, IProxy, IStorageHandler, ProxyList, StringValue, IGetPackageOptions, ISyncUplinks, IPluginFilters } from '@verdaccio/dev-types'; import { GenericBody, TokenFilter, Token } from '@verdaccio/types'; import { logger } from '@verdaccio/logger'; import { VerdaccioError } from '@verdaccio/commons-api'; -import { SearchInstance }from './search'; +import { SearchInstance } from './search'; import { LocalStorage } from './local-storage'; import { mergeVersions } from './metadata-utils'; -import { - checkPackageLocal, - publishPackage, - checkPackageRemote, - cleanUpLinksRef, - mergeUplinkTimeIntoLocal, - generatePackageTemplate -} from './storage-utils'; +import { checkPackageLocal, publishPackage, checkPackageRemote, cleanUpLinksRef, mergeUplinkTimeIntoLocal, generatePackageTemplate } from './storage-utils'; class Storage implements IStorageHandler { public localStorage: IStorage; @@ -41,7 +28,7 @@ class Storage implements IStorageHandler { public constructor(config: Config) { this.config = config; this.uplinks = setupUpLinks(config); - this.logger = logger.child({module: 'storage'}); + this.logger = logger.child({ module: 'storage' }); this.filters = []; // @ts-ignore this.localStorage = null; @@ -152,7 +139,7 @@ class Storage implements IStorageHandler { */ public getTarball(name: string, filename: string): IReadTarball { const readStream = new ReadTarball({}); - readStream.abort = function() {}; + readStream.abort = function () {}; const self = this; @@ -163,48 +150,37 @@ class Storage implements IStorageHandler { // flow: should be IReadTarball let localStream: any = self.localStorage.getTarball(name, filename); let isOpen = false; - localStream.on( - 'error', - (err): any => { - if (isOpen || err.status !== HTTP_STATUS.NOT_FOUND) { - return readStream.emit('error', err); - } - - // local reported 404 - const err404 = err; - localStream.abort(); - localStream = null; // we force for garbage collector - self.localStorage.getPackageMetadata( - name, - (err, info: Package): void => { - if (_.isNil(err) && info._distfiles && _.isNil(info._distfiles[filename]) === false) { - // information about this file exists locally - serveFile(info._distfiles[filename]); - } else { - // we know nothing about this file, trying to get information elsewhere - self._syncUplinksMetadata( - name, - info, - {}, - (err, info: Package): any => { - if (_.isNil(err) === false) { - return readStream.emit('error', err); - } - if (_.isNil(info._distfiles) || _.isNil(info._distfiles[filename])) { - return readStream.emit('error', err404); - } - serveFile(info._distfiles[filename]); - } - ); - } - } - ); + localStream.on('error', (err): any => { + if (isOpen || err.status !== HTTP_STATUS.NOT_FOUND) { + return readStream.emit('error', err); } - ); - localStream.on('content-length', function(v): void { + + // local reported 404 + const err404 = err; + localStream.abort(); + localStream = null; // we force for garbage collector + self.localStorage.getPackageMetadata(name, (err, info: Package): void => { + if (_.isNil(err) && info._distfiles && _.isNil(info._distfiles[filename]) === false) { + // information about this file exists locally + serveFile(info._distfiles[filename]); + } else { + // we know nothing about this file, trying to get information elsewhere + self._syncUplinksMetadata(name, info, {}, (err, info: Package): any => { + if (_.isNil(err) === false) { + return readStream.emit('error', err); + } + if (_.isNil(info._distfiles) || _.isNil(info._distfiles[filename])) { + return readStream.emit('error', err404); + } + serveFile(info._distfiles[filename]); + }); + } + }); + }); + localStream.on('content-length', function (v): void { readStream.emit('content-length', v); }); - localStream.on('open', function(): void { + localStream.on('open', function (): void { isOpen = true; localStream.pipe(readStream); }); @@ -239,24 +215,24 @@ class Storage implements IStorageHandler { savestream = self.localStorage.addTarball(name, filename); } - let on_open = function(): void { + let on_open = function (): void { // prevent it from being called twice - on_open = function() {}; + on_open = function () {}; const rstream2 = uplink.fetchTarball(file.url); - rstream2.on('error', function(err): void { + rstream2.on('error', function (err): void { if (savestream) { savestream.abort(); } savestream = null; readStream.emit('error', err); }); - rstream2.on('end', function(): void { + rstream2.on('end', function (): void { if (savestream) { savestream.done(); } }); - rstream2.on('content-length', function(v): void { + rstream2.on('content-length', function (v): void { readStream.emit('content-length', v); if (savestream) { savestream.emit('content-length', v); @@ -269,11 +245,11 @@ class Storage implements IStorageHandler { }; if (savestream) { - savestream.on('open', function(): void { + savestream.on('open', function (): void { on_open(); }); - savestream.on('error', function(err): void { + savestream.on('error', function (err): void { self.logger.warn({ err: err, fileName: file }, 'error saving file @{fileName}: @{err.message}\n@{err.stack}'); if (savestream) { savestream.abort(); @@ -301,32 +277,29 @@ class Storage implements IStorageHandler { * @property {function} options.callback Callback for receive data */ public getPackage(options: IGetPackageOptions): void { - this.localStorage.getPackageMetadata( - options.name, - (err, data): void => { - if (err && (!err.status || err.status >= HTTP_STATUS.INTERNAL_ERROR)) { - // report internal errors right away + this.localStorage.getPackageMetadata(options.name, (err, data): void => { + if (err && (!err.status || err.status >= HTTP_STATUS.INTERNAL_ERROR)) { + // report internal errors right away + return options.callback(err); + } + + this._syncUplinksMetadata(options.name, data, { req: options.req, uplinksLook: options.uplinksLook }, function getPackageSynUpLinksCallback( + err, + result: Package, + uplinkErrors + ): void { + if (err) { return options.callback(err); } - this._syncUplinksMetadata(options.name, data, { req: options.req, uplinksLook: options.uplinksLook }, function getPackageSynUpLinksCallback( - err, - result: Package, - uplinkErrors - ): void { - if (err) { - return options.callback(err); - } + normalizeDistTags(cleanUpLinksRef(options.keepUpLinkData, result)); - normalizeDistTags(cleanUpLinksRef(options.keepUpLinkData, result)); + // npm can throw if this field doesn't exist + result._attachments = {}; - // npm can throw if this field doesn't exist - result._attachments = {}; - - options.callback(null, result, uplinkErrors); - }); - } - ); + options.callback(null, result, uplinkErrors); + }); + }); } /** @@ -348,7 +321,7 @@ class Storage implements IStorageHandler { async.eachSeries( Object.keys(this.uplinks), - function(up_name, cb): void { + function (up_name, cb): void { // shortcut: if `local=1` is supplied, don't call uplinks if (options.req.query.local !== undefined) { return cb(); @@ -356,40 +329,34 @@ class Storage implements IStorageHandler { // search by keyword for each uplink const lstream: IUploadTarball = self.uplinks[up_name].search(options); // join streams - lstream.pipe( - stream, - { end: false } - ); - lstream.on('error', function(err): void { + lstream.pipe(stream, { end: false }); + lstream.on('error', function (err): void { self.logger.error({ err: err }, 'uplink error: @{err.message}'); cb(); - cb = function(): void {}; + cb = function (): void {}; }); - lstream.on('end', function(): void { + lstream.on('end', function (): void { cb(); - cb = function(): void {}; + cb = function (): void {}; }); - stream.abort = function(): void { + stream.abort = function (): void { if (lstream.abort) { lstream.abort(); } cb(); - cb = function(): void {}; + cb = function (): void {}; }; }, // executed after all series - function(): void { + function (): void { // attach a local search results const lstream: IReadTarball = self.localStorage.search(startkey, options); - stream.abort = function(): void { + stream.abort = function (): void { lstream.abort(); }; - lstream.pipe( - stream, - { end: true } - ); - lstream.on('error', function(err: VerdaccioError): void { + lstream.pipe(stream, { end: true }); + lstream.on('error', function (err: VerdaccioError): void { self.logger.error({ err: err }, 'search error: @{err.message}'); stream.end(); }); @@ -405,49 +372,47 @@ class Storage implements IStorageHandler { */ public getLocalDatabase(callback: Callback): void { const self = this; - this.localStorage.storagePlugin.get( - (err, locals): void => { - if (err) { - callback(err); - } - - const packages: Version[] = []; - const getPackage = function(itemPkg): void { - self.localStorage.getPackageMetadata(locals[itemPkg], function(err, pkgMetadata: Package): void { - if (_.isNil(err)) { - const latest = pkgMetadata[DIST_TAGS].latest; - if (latest && pkgMetadata.versions[latest]) { - const version: Version = pkgMetadata.versions[latest]; - const timeList = pkgMetadata.time as GenericBody; - const time = timeList[latest]; - // @ts-ignore - version.time = time; - - // Add for stars api - // @ts-ignore - version.users = pkgMetadata.users; - - packages.push(version); - } else { - self.logger.warn({ package: locals[itemPkg] }, 'package @{package} does not have a "latest" tag?'); - } - } - - if (itemPkg >= locals.length - 1) { - callback(null, packages); - } else { - getPackage(itemPkg + 1); - } - }); - }; - - if (locals.length) { - getPackage(0); - } else { - callback(null, []); - } + this.localStorage.storagePlugin.get((err, locals): void => { + if (err) { + callback(err); } - ); + + const packages: Version[] = []; + const getPackage = function (itemPkg): void { + self.localStorage.getPackageMetadata(locals[itemPkg], function (err, pkgMetadata: Package): void { + if (_.isNil(err)) { + const latest = pkgMetadata[DIST_TAGS].latest; + if (latest && pkgMetadata.versions[latest]) { + const version: Version = pkgMetadata.versions[latest]; + const timeList = pkgMetadata.time as GenericBody; + const time = timeList[latest]; + // @ts-ignore + version.time = time; + + // Add for stars api + // @ts-ignore + version.users = pkgMetadata.users; + + packages.push(version); + } else { + self.logger.warn({ package: locals[itemPkg] }, 'package @{package} does not have a "latest" tag?'); + } + } + + if (itemPkg >= locals.length - 1) { + callback(null, packages); + } else { + getPackage(itemPkg + 1); + } + }); + }; + + if (locals.length) { + getPackage(0); + } else { + callback(null, []); + } + }); } /** @@ -488,59 +453,55 @@ class Storage implements IStorageHandler { _options.etag = upLinkMeta.etag; } - upLink.getRemoteMetadata( - name, - _options, - (err, upLinkResponse, eTag): void => { - if (err && err.remoteStatus === 304) { - upLinkMeta.fetched = Date.now(); - } - - if (err || !upLinkResponse) { - return cb(null, [err || ErrorCode.getInternalError('no data')]); - } - - try { - validateMetadata(upLinkResponse, name); - } catch (err) { - self.logger.error( - { - sub: 'out', - err: err, - }, - 'package.json validating error @{!err.message}\n@{err.stack}' - ); - return cb(null, [err]); - } - - packageInfo._uplinks[upLink.upname] = { - etag: eTag, - fetched: Date.now(), - }; - - packageInfo.time = mergeUplinkTimeIntoLocal(packageInfo, upLinkResponse); - - updateVersionsHiddenUpLink(upLinkResponse.versions, upLink); - - try { - mergeVersions(packageInfo, upLinkResponse); - } catch (err) { - self.logger.error( - { - sub: 'out', - err: err, - }, - 'package.json parsing error @{!err.message}\n@{err.stack}' - ); - return cb(null, [err]); - } - - // if we got to this point, assume that the correct package exists - // on the uplink - found = true; - cb(); + upLink.getRemoteMetadata(name, _options, (err, upLinkResponse, eTag): void => { + if (err && err.remoteStatus === 304) { + upLinkMeta.fetched = Date.now(); } - ); + + if (err || !upLinkResponse) { + return cb(null, [err || ErrorCode.getInternalError('no data')]); + } + + try { + validateMetadata(upLinkResponse, name); + } catch (err) { + self.logger.error( + { + sub: 'out', + err: err, + }, + 'package.json validating error @{!err.message}\n@{err.stack}' + ); + return cb(null, [err]); + } + + packageInfo._uplinks[upLink.upname] = { + etag: eTag, + fetched: Date.now(), + }; + + packageInfo.time = mergeUplinkTimeIntoLocal(packageInfo, upLinkResponse); + + updateVersionsHiddenUpLink(upLinkResponse.versions, upLink); + + try { + mergeVersions(packageInfo, upLinkResponse); + } catch (err) { + self.logger.error( + { + sub: 'out', + err: err, + }, + 'package.json parsing error @{!err.message}\n@{err.stack}' + ); + return cb(null, [err]); + } + + // if we got to this point, assume that the correct package exists + // on the uplink + found = true; + cb(); + }); }, // @ts-ignore (err: Error, upLinksErrors: any): AsyncResultArrayCallback => { @@ -620,4 +581,4 @@ class Storage implements IStorageHandler { } } -export { Storage } +export { Storage }; diff --git a/packages/store/test/local-storage.spec.ts b/packages/store/test/local-storage.spec.ts index 703645573..8f268d5be 100644 --- a/packages/store/test/local-storage.spec.ts +++ b/packages/store/test/local-storage.spec.ts @@ -1,20 +1,19 @@ import path from 'path'; import rimRaf from 'rimraf'; -import {Config as AppConfig } from '@verdaccio/config'; +import { Config as AppConfig } from '@verdaccio/config'; // @ts-ignore -import { logger, setup} from '@verdaccio/logger'; +import { logger, setup } from '@verdaccio/logger'; import { configExample, generateNewVersion } from '@verdaccio/mock'; -import {IStorage} from '@verdaccio/dev-types'; -import { LocalStorage } from '../src/local-storage'; - +import { IStorage } from '@verdaccio/dev-types'; const readMetadata = (fileName = 'metadata') => readFile(`../fixtures/${fileName}`).toString(); -import {Config, MergeTags, Package} from '@verdaccio/types'; -import { API_ERROR, HTTP_STATUS, DIST_TAGS} from '@verdaccio/dev-commons'; +import { Config, MergeTags, Package } from '@verdaccio/types'; +import { API_ERROR, HTTP_STATUS, DIST_TAGS } from '@verdaccio/dev-commons'; import { VerdaccioError } from '@verdaccio/commons-api'; -import {generatePackageTemplate} from '../src/storage-utils'; -import {readFile} from './fixtures/test.utils'; +import { LocalStorage } from '../src/local-storage'; +import { generatePackageTemplate } from '../src/storage-utils'; +import { readFile } from './fixtures/test.utils'; setup([]); @@ -26,16 +25,18 @@ describe('LocalStorage', () => { const tarballName2 = `${pkgName}-add-tarball-1.0.5.tgz`; const getStorage = (LocalStorageClass = LocalStorage) => { - const config: Config = new AppConfig(configExample({ - self_path: path.join('../partials/store') - })); + const config: Config = new AppConfig( + configExample({ + self_path: path.join('../partials/store'), + }) + ); return new LocalStorageClass(config, logger); - } + }; const getPackageMetadataFromStore = (pkgName: string): Promise => { return new Promise((resolve) => { - storage.getPackageMetadata(pkgName, (err, data ) => { + storage.getPackageMetadata(pkgName, (err, data) => { resolve(data); }); }); @@ -143,7 +144,7 @@ describe('LocalStorage', () => { await addNewVersion(pkgName, '3.0.0'); const tags: MergeTags = { beta: '3.0.0', - latest: '2.0.0' + latest: '2.0.0', }; storage.mergeTags(pkgName, tags, async (err, data) => { @@ -166,7 +167,7 @@ describe('LocalStorage', () => { await addNewVersion(pkgName, '2.0.0'); await addNewVersion(pkgName, '3.0.0'); const tags: MergeTags = { - beta: '9999.0.0' + beta: '9999.0.0', }; storage.mergeTags(pkgName, tags, async (err) => { @@ -180,7 +181,7 @@ describe('LocalStorage', () => { test('should fails on mergeTags', async (done) => { const tags: MergeTags = { beta: '3.0.0', - latest: '2.0.0' + latest: '2.0.0', }; storage.mergeTags('not-found', tags, async (err) => { @@ -215,7 +216,7 @@ describe('LocalStorage', () => { await addPackageToStore(pkgName, generatePackageTemplate(pkgName)); await addNewVersion(pkgName, version); - storage.addVersion(pkgName, version, generateNewVersion(pkgName, version), '', err => { + storage.addVersion(pkgName, version, generateNewVersion(pkgName, version), '', (err) => { expect(err).not.toBeNull(); expect(err.statusCode).toEqual(HTTP_STATUS.CONFLICT); expect(err.message).toMatch(API_ERROR.PACKAGE_EXIST); @@ -230,7 +231,7 @@ describe('LocalStorage', () => { const tarballName = `${pkgName}-${version}.tgz`; await addTarballToStore(pkgName, tarballName); - storage.addVersion(pkgName, version, generateNewVersion(pkgName, version, 'fake'), '', err => { + storage.addVersion(pkgName, version, generateNewVersion(pkgName, version, 'fake'), '', (err) => { expect(err).not.toBeNull(); expect(err.statusCode).toEqual(HTTP_STATUS.BAD_REQUEST); expect(err.message).toMatch(/shasum error/); @@ -258,18 +259,18 @@ describe('LocalStorage', () => { const pkgName = 'add-update-versions-test-1'; const version = '1.0.2'; let _storage; - beforeEach(done => { + beforeEach((done) => { class MockLocalStorage extends LocalStorage {} // @ts-ignore - MockLocalStorage.prototype._writePackage = jest.fn(LocalStorage.prototype._writePackage) + MockLocalStorage.prototype._writePackage = jest.fn(LocalStorage.prototype._writePackage); _storage = getStorage(MockLocalStorage); rimRaf(path.join(configExample().storage, pkgName), async () => { await addPackageToStore(pkgName, generatePackageTemplate(pkgName)); await addNewVersion(pkgName, '1.0.1'); await addNewVersion(pkgName, version); done(); - }) - }) + }); + }); test('should update versions from external source', async (done) => { _storage.updateVersions(pkgName, metadata, (err, data) => { @@ -290,22 +291,22 @@ describe('LocalStorage', () => { }); }); - test('should not update if the metadata match', done => { - _storage.updateVersions(pkgName, metadata, e => { - expect(e).toBeNull() - _storage.updateVersions(pkgName, metadata, err => { - expect(err).toBeNull() + test('should not update if the metadata match', (done) => { + _storage.updateVersions(pkgName, metadata, (e) => { + expect(e).toBeNull(); + _storage.updateVersions(pkgName, metadata, (err) => { + expect(err).toBeNull(); expect(_storage._writePackage).toHaveBeenCalledTimes(1); - done() - }) - }) - }) + done(); + }); + }); + }); }); describe('LocalStorage::changePackage', () => { const pkgName = 'change-package'; - test('should unpublish a version', async done => { + test('should unpublish a version', async (done) => { await addPackageToStore(pkgName, generatePackageTemplate(pkgName)); await addNewVersion(pkgName, '1.0.1'); await addNewVersion(pkgName, '1.0.2'); @@ -315,7 +316,7 @@ describe('LocalStorage', () => { storage.changePackage(pkgName, metadata, rev, (err) => { expect(err).toBeUndefined(); - storage.getPackageMetadata(pkgName, (err, data ) => { + storage.getPackageMetadata(pkgName, (err, data) => { expect(err).toBeNull(); expect(data.versions['1.0.1']).toBeDefined(); expect(data.versions['1.0.2']).toBeUndefined(); @@ -327,9 +328,7 @@ describe('LocalStorage', () => { }); describe('LocalStorage::tarball operations', () => { - describe('LocalStorage::addTarball', () => { - test('should add a new tarball', (done) => { const tarballData = JSON.parse(readMetadata('addTarball')); const stream = storage.addTarball(pkgName, tarballName); @@ -338,7 +337,7 @@ describe('LocalStorage', () => { expect(err).toBeNull(); done(); }); - stream.on('success', function() { + stream.on('success', function () { done(); }); @@ -353,7 +352,7 @@ describe('LocalStorage', () => { expect(err).toBeNull(); done(); }); - stream.on('success', function() { + stream.on('success', function () { done(); }); @@ -394,7 +393,7 @@ describe('LocalStorage', () => { test('should fails on use invalid package name on add a new tarball', (done) => { const stream = storage.addTarball(pkgName, `${pkgName}-fails-add-tarball-1.0.4.tgz`); - stream.on('error', function(err: VerdaccioError) { + stream.on('error', function (err: VerdaccioError) { expect(err).not.toBeNull(); expect(err.statusCode).toEqual(HTTP_STATUS.BAD_DATA); expect(err.message).toMatch(/refusing to accept zero-length file/); @@ -407,7 +406,7 @@ describe('LocalStorage', () => { test('should fails on abort on add a new tarball', (done) => { const stream = storage.addTarball('__proto__', `${pkgName}-fails-add-tarball-1.0.4.tgz`); stream.abort(); - stream.on('error', function(err: VerdaccioError) { + stream.on('error', function (err: VerdaccioError) { expect(err).not.toBeNull(); expect(err.statusCode).toEqual(HTTP_STATUS.FORBIDDEN); expect(err.message).toMatch(/can't use this filename/); @@ -416,10 +415,8 @@ describe('LocalStorage', () => { stream.done(); }); - }); describe('LocalStorage::removeTarball', () => { - test('should remove a tarball', (done) => { storage.removeTarball(pkgName, tarballName2, 'rev', (err, pkg) => { expect(err).toBeNull(); @@ -441,18 +438,18 @@ describe('LocalStorage', () => { describe('LocalStorage::getTarball', () => { test('should get a existing tarball', (done) => { const stream = storage.getTarball(pkgName, tarballName); - stream.on('content-length', function(contentLength) { + stream.on('content-length', function (contentLength) { expect(contentLength).toBe(279); done(); }); - stream.on('open', function() { + stream.on('open', function () { done(); }); }); test('should fails on get a tarball that does not exist', (done) => { const stream = storage.getTarball('fake', tarballName); - stream.on('error', function(err: VerdaccioError) { + stream.on('error', function (err: VerdaccioError) { expect(err).not.toBeNull(); expect(err.statusCode).toEqual(HTTP_STATUS.NOT_FOUND); expect(err.message).toMatch(/no such file available/); @@ -470,16 +467,15 @@ describe('LocalStorage', () => { expect(pkg.name).toEqual(pkgName); }); - stream.on('error', function(err) { + stream.on('error', function (err) { expect(err).not.toBeNull(); done(); }); - stream.on('end', function() { + stream.on('end', function () { done(); }); }); - }); }); @@ -502,7 +498,7 @@ describe('LocalStorage', () => { test('should fails with package not found', (done) => { const pkgName = 'npm_test_fake'; - storage.removePackage(pkgName, err => { + storage.removePackage(pkgName, (err) => { expect(err).not.toBeNull(); expect(err.message).toMatch(/no such package available/); done(); @@ -510,7 +506,7 @@ describe('LocalStorage', () => { }); test('should fails with @scoped package not found', (done) => { - storage.removePackage(pkgNameScoped, err => { + storage.removePackage(pkgNameScoped, (err) => { expect(err).not.toBeNull(); expect(err.message).toMatch(API_ERROR.NO_PACKAGE); done(); @@ -518,5 +514,4 @@ describe('LocalStorage', () => { }); }); }); - }); diff --git a/packages/store/test/merge.dist.tags.spec.ts b/packages/store/test/merge.dist.tags.spec.ts index 72fecab20..1e5989d90 100644 --- a/packages/store/test/merge.dist.tags.spec.ts +++ b/packages/store/test/merge.dist.tags.spec.ts @@ -2,74 +2,62 @@ import assert from 'assert'; import { semverSort } from '@verdaccio/utils'; import { setup } from '@verdaccio/logger'; -import {mergeVersions} from '../src/metadata-utils'; +import { mergeVersions } from '../src/metadata-utils'; setup([]); describe('Storage._merge_versions versions', () => { - test('simple', () => { let pkg = { - 'versions': {a: 1, b: 1, c: 1}, + versions: { a: 1, b: 1, c: 1 }, 'dist-tags': {}, }; // @ts-ignore - mergeVersions(pkg, {versions: {a: 2, q: 2}}); + mergeVersions(pkg, { versions: { a: 2, q: 2 } }); assert.deepEqual(pkg, { - 'versions': {a: 1, b: 1, c: 1, q: 2}, + versions: { a: 1, b: 1, c: 1, q: 2 }, 'dist-tags': {}, }); }); test('dist-tags - compat', () => { let pkg = { - 'versions': {}, - 'dist-tags': {q: '1.1.1', w: '2.2.2'}, + versions: {}, + 'dist-tags': { q: '1.1.1', w: '2.2.2' }, }; // @ts-ignore - mergeVersions(pkg, {'dist-tags': {q: '2.2.2', w: '3.3.3', t: '4.4.4'}}); + mergeVersions(pkg, { 'dist-tags': { q: '2.2.2', w: '3.3.3', t: '4.4.4' } }); assert.deepEqual(pkg, { - 'versions': {}, - 'dist-tags': {q: '2.2.2', w: '3.3.3', t: '4.4.4'}, + versions: {}, + 'dist-tags': { q: '2.2.2', w: '3.3.3', t: '4.4.4' }, }); }); test('dist-tags - staging', () => { - let pkg = { versions: {}, // we've been locally publishing 1.1.x in preparation for the next // public release - 'dist-tags': {q:'1.1.10',w:'2.2.2'}, + 'dist-tags': { q: '1.1.10', w: '2.2.2' }, }; // 1.1.2 is the latest public release, but we want to continue testing // against our local 1.1.10, which may end up published as 1.1.3 in the // future // @ts-ignore - mergeVersions(pkg, {'dist-tags':{q:'1.1.2',w:'3.3.3',t:'4.4.4'}}) + mergeVersions(pkg, { 'dist-tags': { q: '1.1.2', w: '3.3.3', t: '4.4.4' } }); assert.deepEqual(pkg, { versions: {}, - 'dist-tags': {q:'1.1.10',w:'3.3.3',t:'4.4.4'}, + 'dist-tags': { q: '1.1.10', w: '3.3.3', t: '4.4.4' }, }); - }); test('semverSort', () => { - - assert.deepEqual(semverSort(['1.2.3', '1.2', '1.2.3a', '1.2.3c', '1.2.3-b']), - ['1.2.3a', - '1.2.3-b', - '1.2.3c', - '1.2.3'] - ); - + assert.deepEqual(semverSort(['1.2.3', '1.2', '1.2.3a', '1.2.3c', '1.2.3-b']), ['1.2.3a', '1.2.3-b', '1.2.3c', '1.2.3']); }); - }); - diff --git a/packages/store/test/search.spec.ts b/packages/store/test/search.spec.ts index 7accbe649..9a9dd4a65 100644 --- a/packages/store/test/search.spec.ts +++ b/packages/store/test/search.spec.ts @@ -32,12 +32,12 @@ const packages = [ ]; describe('search', () => { - beforeAll(async function() { + beforeAll(async function () { const config = new Config(configExample()); const storage = new Storage(config); await storage.init(config); SearchInstance.configureStorage(storage); - packages.map(function(item) { + packages.map(function (item) { // @ts-ignore SearchInstance.add(item); }); diff --git a/packages/store/test/storage-utils.spec.ts b/packages/store/test/storage-utils.spec.ts index 09487cd31..d7b5eff30 100644 --- a/packages/store/test/storage-utils.spec.ts +++ b/packages/store/test/storage-utils.spec.ts @@ -1,8 +1,8 @@ -import {Package} from '@verdaccio/types'; +import { Package } from '@verdaccio/types'; import { STORAGE, DIST_TAGS } from '@verdaccio/dev-commons'; -import {normalizePackage, mergeUplinkTimeIntoLocal} from '../src/storage-utils'; +import { normalizePackage, mergeUplinkTimeIntoLocal } from '../src/storage-utils'; -import {readFile} from "./fixtures/test.utils"; +import { readFile } from './fixtures/test.utils'; describe('Storage Utils', () => { describe('normalizePackage', () => { @@ -48,13 +48,13 @@ describe('Storage Utils', () => { describe('mergeTime', () => { const vGroup1 = { - "1.0.15": "2018-06-12T23:15:05.864Z", - "1.0.16": "2018-06-12T23:17:46.578Z", - "1.0.17": "2018-06-12T23:20:59.106Z" + '1.0.15': '2018-06-12T23:15:05.864Z', + '1.0.16': '2018-06-12T23:17:46.578Z', + '1.0.17': '2018-06-12T23:20:59.106Z', }; const vGroup2 = { - "1.0.6": "2018-06-07T05:50:21.505Z", - "1.0.7": "2018-06-12T20:35:07.621Z" + '1.0.6': '2018-06-07T05:50:21.505Z', + '1.0.7': '2018-06-12T20:35:07.621Z', }; test('mergeTime basic', () => { const pkg1: Package = { @@ -63,9 +63,9 @@ describe('Storage Utils', () => { _rev: '', _uplinks: {}, time: { - "modified": "2018-06-13T06:44:45.747Z", - "created": "2018-06-07T05:50:21.505Z", - ...vGroup1 + modified: '2018-06-13T06:44:45.747Z', + created: '2018-06-07T05:50:21.505Z', + ...vGroup1, }, name: '', versions: {}, @@ -79,17 +79,16 @@ describe('Storage Utils', () => { _uplinks: {}, name: '', time: { - "modified": "2019-06-13T06:44:45.747Z", - "created": "2019-06-07T05:50:21.505Z", - ...vGroup2 + modified: '2019-06-13T06:44:45.747Z', + created: '2019-06-07T05:50:21.505Z', + ...vGroup2, }, versions: {}, [DIST_TAGS]: {}, }; const mergedPkg = mergeUplinkTimeIntoLocal(pkg1, pkg2); - expect(Object.keys(mergedPkg)).toEqual(["modified", "created", - ...Object.keys(vGroup1), ...Object.keys(vGroup2)]); + expect(Object.keys(mergedPkg)).toEqual(['modified', 'created', ...Object.keys(vGroup1), ...Object.keys(vGroup2)]); }); test('mergeTime remote empty', () => { @@ -100,9 +99,9 @@ describe('Storage Utils', () => { _uplinks: {}, name: '', time: { - "modified": "2018-06-13T06:44:45.747Z", - "created": "2018-06-07T05:50:21.505Z", - ...vGroup1 + modified: '2018-06-13T06:44:45.747Z', + created: '2018-06-07T05:50:21.505Z', + ...vGroup1, }, versions: {}, [DIST_TAGS]: {}, @@ -118,7 +117,7 @@ describe('Storage Utils', () => { [DIST_TAGS]: {}, }; const mergedPkg = mergeUplinkTimeIntoLocal(pkg1, pkg2); - expect(Object.keys(mergedPkg)).toEqual(["modified", "created", ...Object.keys(vGroup1)]); + expect(Object.keys(mergedPkg)).toEqual(['modified', 'created', ...Object.keys(vGroup1)]); }); }); }); diff --git a/packages/utils/src/auth-utils.ts b/packages/utils/src/auth-utils.ts index 08fd87ed7..74adf189c 100644 --- a/packages/utils/src/auth-utils.ts +++ b/packages/utils/src/auth-utils.ts @@ -23,7 +23,7 @@ export const defaultNonLoggedUserRoles = [ ROLES.$ANONYMOUS, // groups without '$' are going to be deprecated eventually ROLES.DEPRECATED_ALL, - ROLES.DEPRECATED_ANONYMOUS + ROLES.DEPRECATED_ANONYMOUS, ]; /** @@ -65,14 +65,17 @@ export type ActionsAllowed = 'publish' | 'unpublish' | 'access'; export function allow_action(action: ActionsAllowed, logger): AllowAction { return function allowActionCallback(user: RemoteUser, pkg: AuthPackageAllow, callback: AllowActionCallback): void { - logger.trace({remote: user.name}, `[auth/allow_action]: user: @{user.name}`); + logger.trace({ remote: user.name }, `[auth/allow_action]: user: @{user.name}`); const { name, groups } = user; const groupAccess = pkg[action] as string[]; - const hasPermission = groupAccess.some(group => name === group || groups.includes(group)); - logger.trace({pkgName: pkg.name, hasPermission, remote: user.name, groupAccess}, `[auth/allow_action]: hasPermission? @{hasPermission} for user: @{user}`); + const hasPermission = groupAccess.some((group) => name === group || groups.includes(group)); + logger.trace( + { pkgName: pkg.name, hasPermission, remote: user.name, groupAccess }, + `[auth/allow_action]: hasPermission? @{hasPermission} for user: @{user}` + ); if (hasPermission) { - logger.trace({remote: user.name}, `auth/allow_action: access granted to: @{user}`); + logger.trace({ remote: user.name }, `auth/allow_action: access granted to: @{user}`); return callback(null, true); } @@ -88,18 +91,18 @@ export function allow_action(action: ActionsAllowed, logger): AllowAction { * */ export function handleSpecialUnpublish(logger): any { - return function(user: RemoteUser, pkg: AuthPackageAllow, callback: AllowActionCallback): void { + return function (user: RemoteUser, pkg: AuthPackageAllow, callback: AllowActionCallback): void { const action = 'unpublish'; // verify whether the unpublish prop has been defined const isUnpublishMissing: boolean = _.isNil(pkg[action]); - const hasGroups: boolean = isUnpublishMissing ? false : ((pkg[action]) as string[]).length > 0; - logger.trace({user: user.name, name: pkg.name, hasGroups}, `fallback unpublish for @{name} has groups: @{hasGroups} for @{user}`); + const hasGroups: boolean = isUnpublishMissing ? false : (pkg[action] as string[]).length > 0; + logger.trace({ user: user.name, name: pkg.name, hasGroups }, `fallback unpublish for @{name} has groups: @{hasGroups} for @{user}`); if (isUnpublishMissing || hasGroups === false) { return callback(null, undefined); } - logger.trace({user: user.name, name: pkg.name, action, hasGroups}, `allow_action for @{action} for @{name} has groups: @{hasGroups} for @{user}`); + logger.trace({ user: user.name, name: pkg.name, action, hasGroups }, `allow_action for @{action} for @{name} has groups: @{hasGroups} for @{user}`); return allow_action(action, logger)(user, pkg, callback); }; } diff --git a/packages/utils/src/config-utils.ts b/packages/utils/src/config-utils.ts index f1fc731a9..37605003d 100644 --- a/packages/utils/src/config-utils.ts +++ b/packages/utils/src/config-utils.ts @@ -2,7 +2,6 @@ import assert from 'assert'; import _ from 'lodash'; import minimatch from 'minimatch'; - import { PackageList, UpLinksConfList } from '@verdaccio/types'; import { MatchedPackage, LegacyPackageList } from '@verdaccio/dev-types'; import { ErrorCode } from './utils'; @@ -20,23 +19,21 @@ const BLACKLIST = { * @return {Array} */ export function normalizeUserList(groupsList: any): any { - const result: any[] = []; - if (_.isNil(groupsList)) { - return result; - } + const result: any[] = []; + if (_.isNil(groupsList)) { + return result; + } - // if it's a string, split it to array - if (_.isString(groupsList)) { - const groupsArray = groupsList.split(/\s+/); + // if it's a string, split it to array + if (_.isString(groupsList)) { + const groupsArray = groupsList.split(/\s+/); - result.push(groupsArray); - } else if (Array.isArray(groupsList)) { - result.push(groupsList); - } else { - throw ErrorCode.getInternalError( - 'CONFIG: bad package acl (array or string expected): ' + JSON.stringify(groupsList) - ); - } + result.push(groupsArray); + } else if (Array.isArray(groupsList)) { + result.push(groupsList); + } else { + throw ErrorCode.getInternalError('CONFIG: bad package acl (array or string expected): ' + JSON.stringify(groupsList)); + } return _.flatten(result); } @@ -58,10 +55,7 @@ export function uplinkSanityCheck(uplinks: UpLinksConfList, users: any = BLACKLI } 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; @@ -90,7 +84,7 @@ export function hasProxyTo(pkg: string, upLink: string, packages: PackageList): const matchedPkg: MatchedPackage = getMatchedPackagesSpec(pkg, packages); const proxyList = typeof matchedPkg !== 'undefined' ? matchedPkg.proxy : []; if (proxyList) { - return proxyList.some(curr => upLink === curr); + return proxyList.some((curr) => upLink === curr); } return false; @@ -112,7 +106,7 @@ export function normalisePackageAccess(packages: LegacyPackageList): LegacyPacka normalizedPkgs['**'] = { access: [], publish: [], - proxy: [] + proxy: [], }; } @@ -126,9 +120,7 @@ export function normalisePackageAccess(packages: LegacyPackageList): LegacyPacka normalizedPkgs[pkg].publish = normalizeUserList(packageAccess.publish); normalizedPkgs[pkg].proxy = normalizeUserList(packageAccess.proxy); // if unpublish is not defined, we set to false to fallback in publish access - normalizedPkgs[pkg].unpublish = _.isUndefined(packageAccess.unpublish) - ? false - : normalizeUserList(packageAccess.unpublish); + normalizedPkgs[pkg].unpublish = _.isUndefined(packageAccess.unpublish) ? false : normalizeUserList(packageAccess.unpublish); } } diff --git a/packages/utils/src/crypto-utils.ts b/packages/utils/src/crypto-utils.ts index 2630ff922..334bd4bb2 100644 --- a/packages/utils/src/crypto-utils.ts +++ b/packages/utils/src/crypto-utils.ts @@ -42,9 +42,7 @@ export function createTarballHash(): Hash { * @return {String} */ export function stringToMD5(data: Buffer | string): string { - return createHash('md5') - .update(data) - .digest('hex'); + return createHash('md5').update(data).digest('hex'); } export function generateRandomHexString(length = 8): string { @@ -59,7 +57,7 @@ export function generateRandomHexString(length = 8): string { * @param options */ export async function signPayload(payload: RemoteUser, secretOrPrivateKey: string, options: JWTSignOptions = {}): Promise { - return new Promise(function(resolve, reject): Promise { + return new Promise(function (resolve, reject): Promise { return jwt.sign( payload, secretOrPrivateKey, diff --git a/packages/utils/src/utils.ts b/packages/utils/src/utils.ts index b9ac8b004..8d50fafc3 100644 --- a/packages/utils/src/utils.ts +++ b/packages/utils/src/utils.ts @@ -8,16 +8,7 @@ import YAML from 'js-yaml'; import { Request } from 'express'; import sanitizyReadme from '@verdaccio/readme'; -import { - APP_ERROR, - DEFAULT_PORT, - DEFAULT_DOMAIN, - DEFAULT_PROTOCOL, - CHARACTER_ENCODING, - HEADERS, - DIST_TAGS, - DEFAULT_USER, -} from '@verdaccio/dev-commons'; +import { APP_ERROR, DEFAULT_PORT, DEFAULT_DOMAIN, DEFAULT_PROTOCOL, CHARACTER_ENCODING, HEADERS, DIST_TAGS, DEFAULT_USER } from '@verdaccio/dev-commons'; import { Package, Version, Author } from '@verdaccio/types'; import { StringValue } from '@verdaccio/dev-types'; @@ -34,7 +25,6 @@ import { getCode, } from '@verdaccio/commons-api'; - // eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -184,12 +174,7 @@ export function convertDistRemoteToLocalTarballUrls(pkg: Package, req: Request, * @param {*} uri * @return {String} a parsed url */ -export function getLocalRegistryTarballUri( - uri: string, - pkgName: string, - req: Request, - urlPrefix: string | void -): string { +export function getLocalRegistryTarballUri(uri: string, pkgName: string, req: Request, urlPrefix: string | void): string { const currentHost = req.headers.host; if (!currentHost) { @@ -287,10 +272,10 @@ export function parseAddress(urlAddress: any): any { * Function filters out bad semver versions and sorts the array. * @return {Array} sorted Array */ -export function semverSort(listVersions: string[], /* logger */): string[] { +export function semverSort(listVersions: string[] /* logger */): string[] { return ( listVersions - .filter(function(x): boolean { + .filter(function (x): boolean { if (!semver.parse(x, true)) { // FIXME: logger is always undefined // logger.warn({ ver: x }, 'ignoring bad version @{ver}'); @@ -365,8 +350,8 @@ export function parseInterval(interval: any): number { } let result = 0; let last_suffix = Infinity; - interval.split(/\s+/).forEach(function(x): void { - if (!x){ + interval.split(/\s+/).forEach(function (x): void { + if (!x) { return; } const m = x.match(/^((0|[1-9][0-9]*)(\.[0-9]+)?)(ms|s|m|h|d|w|M|y|)$/); @@ -452,7 +437,7 @@ export function fileExists(path: string): boolean { } export function sortByName(packages: any[], orderAscending: boolean | void = true): string[] { - return packages.slice().sort(function(a, b): number { + return packages.slice().sort(function (a, b): number { const comparatorNames = a.name.toLowerCase() < b.name.toLowerCase(); return orderAscending ? (comparatorNames ? -1 : 1) : comparatorNames ? 1 : -1; diff --git a/packages/utils/test/auth-utils.spec.ts b/packages/utils/test/auth-utils.spec.ts index cc4ce0f80..1a7f291ec 100644 --- a/packages/utils/test/auth-utils.spec.ts +++ b/packages/utils/test/auth-utils.spec.ts @@ -1,165 +1,165 @@ -import { API_ERROR, ROLES } from "@verdaccio/dev-commons"; -import { VerdaccioError, getForbidden } from "@verdaccio/commons-api"; +import { API_ERROR, ROLES } from '@verdaccio/dev-commons'; +import { VerdaccioError, getForbidden } from '@verdaccio/commons-api'; import { - allow_action, - createAnonymousRemoteUser, - createRemoteUser, - validatePassword, - ActionsAllowed, - AllowActionCallbackResponse, - getDefaultPlugins, - createSessionToken, - getAuthenticatedMessage, -} from "../src"; + allow_action, + createAnonymousRemoteUser, + createRemoteUser, + validatePassword, + ActionsAllowed, + AllowActionCallbackResponse, + getDefaultPlugins, + createSessionToken, + getAuthenticatedMessage, +} from '../src'; jest.mock('@verdaccio/logger', () => ({ - logger: { trace: jest.fn() } + logger: { trace: jest.fn() }, })); describe('Auth Utilities', () => { + describe('validatePassword', () => { + test('should validate password according the length', () => { + expect(validatePassword('12345', 1)).toBeTruthy(); + }); - describe('validatePassword', () => { - test('should validate password according the length', () => { - expect(validatePassword('12345', 1)).toBeTruthy(); - }); + test('should fails on validate password according the length', () => { + expect(validatePassword('12345', 10)).toBeFalsy(); + }); - test('should fails on validate password according the length', () => { - expect(validatePassword('12345', 10)).toBeFalsy(); - }); + test('should fails on validate password according the length and default config', () => { + expect(validatePassword('12')).toBeFalsy(); + }); - test('should fails on validate password according the length and default config', () => { - expect(validatePassword('12')).toBeFalsy(); - }); + test('should validate password according the length and default config', () => { + expect(validatePassword('1235678910')).toBeTruthy(); + }); + }); - test('should validate password according the length and default config', () => { - expect(validatePassword('1235678910')).toBeTruthy(); - }); - }); + describe('createRemoteUser and createAnonymousRemoteUser', () => { + test('should create a remote user with default groups', () => { + expect(createRemoteUser('12345', ['foo', 'bar'])).toEqual({ + groups: ['foo', 'bar', ROLES.$ALL, ROLES.$AUTH, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_AUTH, ROLES.ALL], + name: '12345', + real_groups: ['foo', 'bar'], + }); + }); - describe('createRemoteUser and createAnonymousRemoteUser', () => { - test('should create a remote user with default groups', () => { - expect(createRemoteUser('12345', ['foo', 'bar'])).toEqual( - { - "groups": ["foo", "bar", ROLES.$ALL, ROLES.$AUTH, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_AUTH, ROLES.ALL], - "name": "12345", - "real_groups": ["foo", "bar"] - } - ); - }); + test('should create a anonymous remote user with default groups', () => { + expect(createAnonymousRemoteUser()).toEqual({ + groups: [ROLES.$ALL, ROLES.$ANONYMOUS, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_ANONYMOUS], + name: undefined, + real_groups: [], + }); + }); + }); - test('should create a anonymous remote user with default groups', () => { - expect(createAnonymousRemoteUser()).toEqual( - { - "groups": [ROLES.$ALL, ROLES.$ANONYMOUS, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_ANONYMOUS], - "name": undefined, - "real_groups": [] - } - ); - }); - }); + describe('allow_action', () => { + describe('access/publish/unpublish and anonymous', () => { + const packageAccess = { + name: 'foo', + version: undefined, + access: ['foo'], + unpublish: false, + }; - describe('allow_action', () => { - describe('access/publish/unpublish and anonymous', () => { - const packageAccess = { - name: 'foo', - version: undefined, - access: ['foo'], - unpublish: false - }; + // const type = 'access'; + test.each(['access', 'publish', 'unpublish'])('should restrict %s to anonymous users', (type) => { + allow_action(type as ActionsAllowed, { trace: jest.fn() })( + createAnonymousRemoteUser(), + { + ...packageAccess, + [type]: ['foo'], + }, + (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { + expect(error).not.toBeNull(); + expect(allowed).toBeUndefined(); + } + ); + }); - // const type = 'access'; - test.each(['access', 'publish', 'unpublish'])('should restrict %s to anonymous users', (type) => { - allow_action(type as ActionsAllowed, { trace: jest.fn()})( - createAnonymousRemoteUser(), { - ...packageAccess, - [type]: ['foo'] - }, - (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { - expect(error).not.toBeNull(); - expect(allowed).toBeUndefined(); - } - ); - }); + test.each(['access', 'publish', 'unpublish'])('should allow %s to anonymous users', (type) => { + allow_action(type as ActionsAllowed, { trace: jest.fn() })( + createAnonymousRemoteUser(), + { + ...packageAccess, + [type]: [ROLES.$ANONYMOUS], + }, + (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { + expect(error).toBeNull(); + expect(allowed).toBe(true); + } + ); + }); - test.each(['access', 'publish', 'unpublish'])('should allow %s to anonymous users', (type) => { - allow_action(type as ActionsAllowed, { trace: jest.fn()})( - createAnonymousRemoteUser(), { - ...packageAccess, - [type]: [ROLES.$ANONYMOUS] - }, - (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { - expect(error).toBeNull(); - expect(allowed).toBe(true); - } - ); - }); + test.each(['access', 'publish', 'unpublish'])('should allow %s only if user is anonymous if the logged user has groups', (type) => { + allow_action(type as ActionsAllowed, { trace: jest.fn() })( + createRemoteUser('juan', ['maintainer', 'admin']), + { + ...packageAccess, + [type]: [ROLES.$ANONYMOUS], + }, + (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { + expect(error).not.toBeNull(); + expect(allowed).toBeUndefined(); + } + ); + }); - test.each(['access', 'publish', 'unpublish'])('should allow %s only if user is anonymous if the logged user has groups', (type) => { - allow_action(type as ActionsAllowed, { trace: jest.fn()})( - createRemoteUser('juan', ['maintainer', 'admin']), { - ...packageAccess, - [type]: [ROLES.$ANONYMOUS] - }, - (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { - expect(error).not.toBeNull(); - expect(allowed).toBeUndefined(); - } - ); - }); + test.each(['access', 'publish', 'unpublish'])('should allow %s only if user is anonymous match any other groups', (type) => { + allow_action(type as ActionsAllowed, { trace: jest.fn() })( + createRemoteUser('juan', ['maintainer', 'admin']), + { + ...packageAccess, + [type]: ['admin', 'some-other-group', ROLES.$ANONYMOUS], + }, + (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { + expect(error).toBeNull(); + expect(allowed).toBe(true); + } + ); + }); - test.each(['access', 'publish', 'unpublish'])('should allow %s only if user is anonymous match any other groups', (type) => { - allow_action(type as ActionsAllowed, { trace: jest.fn()})( - createRemoteUser('juan', ['maintainer', 'admin']), { - ...packageAccess, - [type]: ['admin', 'some-other-group', ROLES.$ANONYMOUS] - }, - (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { - expect(error).toBeNull(); - expect(allowed).toBe(true); - } - ); - }); + test.each(['access', 'publish', 'unpublish'])('should not allow %s anonymous if other groups are defined and does not match', (type) => { + allow_action(type as ActionsAllowed, { trace: jest.fn() })( + createRemoteUser('juan', ['maintainer', 'admin']), + { + ...packageAccess, + [type]: ['bla-bla-group', 'some-other-group', ROLES.$ANONYMOUS], + }, + (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { + expect(error).not.toBeNull(); + expect(allowed).toBeUndefined(); + } + ); + }); + }); + }); + describe('createSessionToken', () => { + test('should generate session token', () => { + expect(createSessionToken()).toHaveProperty('expires'); + expect(createSessionToken().expires).toBeInstanceOf(Date); + }); + }); - test.each(['access', 'publish', 'unpublish'])('should not allow %s anonymous if other groups are defined and does not match', (type) => { - allow_action(type as ActionsAllowed, { trace: jest.fn()})( - createRemoteUser('juan', ['maintainer', 'admin']), { - ...packageAccess, - [type]: ['bla-bla-group', 'some-other-group', ROLES.$ANONYMOUS] - }, - (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { - expect(error).not.toBeNull(); - expect(allowed).toBeUndefined(); - } - ); - }); - }); - }); - describe('createSessionToken', () => { - test('should generate session token', () => { - expect(createSessionToken()).toHaveProperty('expires'); - expect(createSessionToken().expires).toBeInstanceOf(Date); - }); - }); + describe('getDefaultPlugins', () => { + test('authentication should fail by default (default)', () => { + const plugin = getDefaultPlugins({ trace: jest.fn() }); + plugin.authenticate('foo', 'bar', (error: any) => { + expect(error).toEqual(getForbidden(API_ERROR.BAD_USERNAME_PASSWORD)); + }); + }); - describe('getDefaultPlugins', () => { - test('authentication should fail by default (default)', () => { - const plugin = getDefaultPlugins({ trace: jest.fn()}); - plugin.authenticate('foo', 'bar', (error: any) => { - expect(error).toEqual(getForbidden(API_ERROR.BAD_USERNAME_PASSWORD)); - }); - }); + test('add user should fail by default (default)', () => { + const plugin = getDefaultPlugins({ trace: jest.fn() }); + // @ts-ignore + plugin.adduser('foo', 'bar', (error: any) => { + expect(error).toEqual(getForbidden(API_ERROR.BAD_USERNAME_PASSWORD)); + }); + }); + }); - test('add user should fail by default (default)', () => { - const plugin = getDefaultPlugins({ trace: jest.fn()}); - // @ts-ignore - plugin.adduser('foo', 'bar', (error: any) => { - expect(error).toEqual(getForbidden(API_ERROR.BAD_USERNAME_PASSWORD)); - }); - }); - }); - - describe('getAuthenticatedMessage', () => { - test('should generate user message token', () => { - expect(getAuthenticatedMessage('foo')).toEqual('you are authenticated as \'foo\''); - }); - }); + describe('getAuthenticatedMessage', () => { + test('should generate user message token', () => { + expect(getAuthenticatedMessage('foo')).toEqual("you are authenticated as 'foo'"); + }); + }); }); diff --git a/packages/utils/test/config-utils.spec.ts b/packages/utils/test/config-utils.spec.ts index 0075af062..0be0b2b3a 100644 --- a/packages/utils/test/config-utils.spec.ts +++ b/packages/utils/test/config-utils.spec.ts @@ -1,20 +1,13 @@ import path from 'path'; import _ from 'lodash'; -import {PACKAGE_ACCESS} from '@verdaccio/dev-commons'; +import { PACKAGE_ACCESS } from '@verdaccio/dev-commons'; -import {spliceURL} from '../src/string'; -import {parseConfigFile} from '../src/utils'; -import { - getMatchedPackagesSpec, - hasProxyTo, - normalisePackageAccess, - sanityCheckUplinksProps, - uplinkSanityCheck -} from '../src/config-utils'; +import { spliceURL } from '../src/string'; +import { parseConfigFile } from '../src/utils'; +import { getMatchedPackagesSpec, hasProxyTo, normalisePackageAccess, sanityCheckUplinksProps, uplinkSanityCheck } from '../src/config-utils'; describe('Config Utilities', () => { - const parseConfigurationFile = (conf) => { const { name, ext } = path.parse(conf); const format = ext.startsWith('.') ? ext.substring(1) : 'yaml'; @@ -23,38 +16,38 @@ describe('Config Utilities', () => { }; describe('uplinkSanityCheck', () => { - test('should test basic conversion', ()=> { + test('should test basic conversion', () => { const uplinks = uplinkSanityCheck(parseConfigFile(parseConfigurationFile('uplink-basic')).uplinks); expect(Object.keys(uplinks)).toContain('server1'); expect(Object.keys(uplinks)).toContain('server2'); }); - test('should throw error on blacklisted uplink name', ()=> { - const {uplinks} = parseConfigFile(parseConfigurationFile('uplink-wrong')); + test('should throw error on blacklisted uplink name', () => { + const { uplinks } = parseConfigFile(parseConfigurationFile('uplink-wrong')); expect(() => { - uplinkSanityCheck(uplinks) + uplinkSanityCheck(uplinks); }).toThrow('CONFIG: reserved uplink name: anonymous'); }); }); describe('sanityCheckUplinksProps', () => { - test('should fails if url prop is missing', ()=> { - const {uplinks} = parseConfigFile(parseConfigurationFile('uplink-wrong')); + test('should fails if url prop is missing', () => { + const { uplinks } = parseConfigFile(parseConfigurationFile('uplink-wrong')); expect(() => { - sanityCheckUplinksProps(uplinks) + sanityCheckUplinksProps(uplinks); }).toThrow('CONFIG: no url for uplink: none-url'); }); - test('should bypass an empty uplink list', ()=> { + test('should bypass an empty uplink list', () => { // @ts-ignore expect(sanityCheckUplinksProps([])).toHaveLength(0); }); }); describe('normalisePackageAccess', () => { - test('should test basic conversion', ()=> { - const {packages} = parseConfigFile(parseConfigurationFile('pkgs-basic')); + test('should test basic conversion', () => { + const { packages } = parseConfigFile(parseConfigurationFile('pkgs-basic')); const access = normalisePackageAccess(packages); expect(access).toBeDefined(); @@ -65,8 +58,8 @@ describe('Config Utilities', () => { expect(all).toBeDefined(); }); - test('should define an empty publish array even if is not defined in packages', ()=> { - const {packages} = parseConfigFile(parseConfigurationFile('pkgs-basic-no-publish')); + test('should define an empty publish array even if is not defined in packages', () => { + const { packages } = parseConfigFile(parseConfigurationFile('pkgs-basic-no-publish')); const access = normalisePackageAccess(packages); const scoped = access[`${PACKAGE_ACCESS.SCOPE}`]; @@ -78,8 +71,8 @@ describe('Config Utilities', () => { expect(all.publish).toHaveLength(0); }); - test('should define an empty access array even if is not defined in packages', ()=> { - const {packages} = parseConfigFile(parseConfigurationFile('pkgs-basic-no-access')); + test('should define an empty access array even if is not defined in packages', () => { + const { packages } = parseConfigFile(parseConfigurationFile('pkgs-basic-no-access')); const access = normalisePackageAccess(packages); const scoped = access[`${PACKAGE_ACCESS.SCOPE}`]; @@ -91,8 +84,8 @@ describe('Config Utilities', () => { expect(all.access).toHaveLength(0); }); - test('should define an empty proxy array even if is not defined in package', ()=> { - const {packages} = parseConfigFile(parseConfigurationFile('pkgs-basic-no-proxy')); + test('should define an empty proxy array even if is not defined in package', () => { + const { packages } = parseConfigFile(parseConfigurationFile('pkgs-basic-no-proxy')); const access = normalisePackageAccess(packages); const scoped = access[`${PACKAGE_ACCESS.SCOPE}`]; @@ -104,8 +97,8 @@ describe('Config Utilities', () => { expect(all.proxy).toHaveLength(0); }); - test('should test multi user group definition', ()=> { - const {packages} = parseConfigFile(parseConfigurationFile('pkgs-multi-group')); + test('should test multi user group definition', () => { + const { packages } = parseConfigFile(parseConfigurationFile('pkgs-multi-group')); const access = normalisePackageAccess(packages); expect(access).toBeDefined(); @@ -124,12 +117,10 @@ describe('Config Utilities', () => { expect(all.access).toContain('$all'); expect(all.publish).toHaveLength(1); expect(all.publish).toContain('admin'); - }); - - test('should normalize deprecated packages into the new ones (backward props compatible)', ()=> { - const {packages} = parseConfigFile(parseConfigurationFile('deprecated-pkgs-basic')); + test('should normalize deprecated packages into the new ones (backward props compatible)', () => { + const { packages } = parseConfigFile(parseConfigurationFile('deprecated-pkgs-basic')); const access = normalisePackageAccess(packages); expect(access).toBeDefined(); @@ -161,7 +152,7 @@ describe('Config Utilities', () => { expect(all.proxy).toBeDefined(); }); - test('should check not default packages access', ()=> { + test('should check not default packages access', () => { const { packages } = parseConfigFile(parseConfigurationFile('pkgs-empty')); const access = normalisePackageAccess(packages); expect(access).toBeDefined(); @@ -177,13 +168,12 @@ describe('Config Utilities', () => { expect(_.isArray(all.access)).toBeTruthy(); expect(all.publish).toBeDefined(); expect(_.isArray(all.publish)).toBeTruthy(); - }); }); describe('getMatchedPackagesSpec', () => { test('should test basic config', () => { - const {packages} = parseConfigFile(parseConfigurationFile('pkgs-custom')); + const { packages } = parseConfigFile(parseConfigurationFile('pkgs-custom')); // @ts-ignore expect(getMatchedPackagesSpec('react', packages).proxy).toMatch('facebook'); // @ts-ignore @@ -195,7 +185,7 @@ describe('Config Utilities', () => { }); test('should test no ** wildcard on config', () => { - const {packages} = parseConfigFile(parseConfigurationFile('pkgs-nosuper-wildcard-custom')); + const { packages } = parseConfigFile(parseConfigurationFile('pkgs-nosuper-wildcard-custom')); // @ts-ignore expect(getMatchedPackagesSpec('react', packages).proxy).toMatch('facebook'); // @ts-ignore @@ -278,13 +268,13 @@ describe('Config Utilities', () => { }); test('parse invalid.json', () => { - expect(function ( ) { + expect(function () { parseConfigFile(parseConfigurationFile('invalid.json')); }).toThrow(/Error/); }); test('parse not-exists.json', () => { - expect(function ( ) { + expect(function () { parseConfigFile(parseConfigurationFile('not-exists.json')); }).toThrow(/Error/); }); @@ -298,13 +288,13 @@ describe('Config Utilities', () => { }); test('parse invalid.js', () => { - expect(function ( ) { + expect(function () { parseConfigFile(parseConfigurationFile('invalid.js')); }).toThrow(/Error/); }); test('parse not-exists.js', () => { - expect(function ( ) { + expect(function () { parseConfigFile(parseConfigurationFile('not-exists.js')); }).toThrow(/Error/); }); diff --git a/packages/utils/test/crypto-utils.spec.ts b/packages/utils/test/crypto-utils.spec.ts index 3dffc23fe..a0d5e5f3c 100644 --- a/packages/utils/test/crypto-utils.spec.ts +++ b/packages/utils/test/crypto-utils.spec.ts @@ -1,14 +1,14 @@ -import {aesDecrypt, aesEncrypt, convertPayloadToBase64} from '../src'; +import { aesDecrypt, aesEncrypt, convertPayloadToBase64 } from '../src'; describe('test crypto utils', () => { - describe('default encryption', () => { - test('decrypt payload flow', () => { - const payload = 'juan'; - const token = aesEncrypt(Buffer.from(payload), '12345').toString('base64'); + describe('default encryption', () => { + test('decrypt payload flow', () => { + const payload = 'juan'; + const token = aesEncrypt(Buffer.from(payload), '12345').toString('base64'); - const data = aesDecrypt(convertPayloadToBase64(token), '12345').toString('utf8'); + const data = aesDecrypt(convertPayloadToBase64(token), '12345').toString('utf8'); - expect(payload).toEqual(data); - }); - }); + expect(payload).toEqual(data); + }); + }); }); diff --git a/packages/utils/test/parseAddress.spec.ts b/packages/utils/test/parseAddress.spec.ts index 2910a04e8..dca4642e5 100644 --- a/packages/utils/test/parseAddress.spec.ts +++ b/packages/utils/test/parseAddress.spec.ts @@ -1,7 +1,7 @@ import _ from 'lodash'; -import {DEFAULT_DOMAIN, DEFAULT_PORT} from '@verdaccio/dev-commons'; +import { DEFAULT_DOMAIN, DEFAULT_PORT } from '@verdaccio/dev-commons'; -import {parseAddress as parse} from '../src/utils'; +import { parseAddress as parse } from '../src/utils'; describe('Parse listen address', () => { const useCases: any[] = []; diff --git a/packages/utils/test/tag.version.spec.ts b/packages/utils/test/tag.version.spec.ts index 47b363a92..82c4ac925 100644 --- a/packages/utils/test/tag.version.spec.ts +++ b/packages/utils/test/tag.version.spec.ts @@ -1,47 +1,46 @@ import assert from 'assert'; import { tagVersion } from '../src/utils'; - describe('tagVersion', () => { test('add new one', () => { let pkg = { versions: {}, - 'dist-tags': {} + 'dist-tags': {}, }; // @ts-ignore assert(tagVersion(pkg, '1.1.1', 'foo', {})); assert.deepEqual(pkg, { versions: {}, - 'dist-tags': { foo: '1.1.1' } + 'dist-tags': { foo: '1.1.1' }, }); }); test('add (compat)', () => { const x = { versions: {}, - 'dist-tags': { foo: '1.1.0' } + 'dist-tags': { foo: '1.1.0' }, }; // @ts-ignore assert(tagVersion(x, '1.1.1', 'foo')); assert.deepEqual(x, { versions: {}, - 'dist-tags': { foo: '1.1.1' } + 'dist-tags': { foo: '1.1.1' }, }); }); test('add fresh tag', () => { let x = { versions: {}, - 'dist-tags': { foo: '1.1.0' } + 'dist-tags': { foo: '1.1.0' }, }; // @ts-ignore assert(tagVersion(x, '1.1.1', 'foo')); assert.deepEqual(x, { versions: {}, - 'dist-tags': { foo: '1.1.1' } + 'dist-tags': { foo: '1.1.1' }, }); }); }); diff --git a/packages/utils/test/utils.spec.ts b/packages/utils/test/utils.spec.ts index 54f6c1a45..92d777f0f 100644 --- a/packages/utils/test/utils.spec.ts +++ b/packages/utils/test/utils.spec.ts @@ -1,6 +1,5 @@ - -import fs from "fs"; -import path from "path"; +import fs from 'fs'; +import path from 'path'; import { DIST_TAGS, DEFAULT_USER } from '@verdaccio/dev-commons'; import { spliceURL, @@ -19,29 +18,27 @@ import { isHTTPProtocol, } from '../src/index'; - const readmeFile = (fileName = 'markdown.md') => { return fs.readFileSync(path.join(__dirname, `./partials/readme/${fileName}`)); -} +}; describe('Utilities', () => { - const buildURI = (host, version) => - `http://${host}/npm_test/-/npm_test-${version}.tgz`; + const buildURI = (host, version) => `http://${host}/npm_test/-/npm_test-${version}.tgz`; const fakeHost = 'fake.com'; const metadata: any = { name: 'npm_test', versions: { '1.0.0': { dist: { - tarball: 'http://registry.org/npm_test/-/npm_test-1.0.0.tgz' - } + tarball: 'http://registry.org/npm_test/-/npm_test-1.0.0.tgz', + }, }, '1.0.1': { dist: { - tarball: 'http://registry.org/npm_test/-/npm_test-1.0.1.tgz' - } - } - } + tarball: 'http://registry.org/npm_test/-/npm_test-1.0.1.tgz', + }, + }, + }, }; const cloneMetadata = (pkg = metadata) => Object.assign({}, pkg); @@ -50,40 +47,40 @@ describe('Utilities', () => { describe('Sort packages', () => { const packages = [ { - name: 'ghc' + name: 'ghc', }, { - name: 'abc' + name: 'abc', }, { - name: 'zxy' - } + name: 'zxy', + }, ]; test('should order ascending', () => { expect(sortByName(packages)).toEqual([ { - name: 'abc' + name: 'abc', }, { - name: 'ghc' + name: 'ghc', }, { - name: 'zxy' - } + name: 'zxy', + }, ]); }); test('should order descending', () => { expect(sortByName(packages, false)).toEqual([ { - name: 'zxy' + name: 'zxy', }, { - name: 'ghc' + name: 'ghc', }, { - name: 'abc' - } + name: 'abc', + }, ]); }); }); @@ -98,49 +95,47 @@ describe('Utilities', () => { }); test('should have header priority over request protocol', () => { - expect(getWebProtocol("https", 'http')).toBe('https'); + expect(getWebProtocol('https', 'http')).toBe('https'); }); test('should have handle empty protocol', () => { - expect(getWebProtocol("https", '')).toBe('https'); + expect(getWebProtocol('https', '')).toBe('https'); }); describe('getWebProtocol and HAProxy variant', () => { // https://github.com/verdaccio/verdaccio/issues/695 test('should handle http', () => { - expect(getWebProtocol("http,http", 'https')).toBe('http'); + expect(getWebProtocol('http,http', 'https')).toBe('http'); }); test('should handle https', () => { - expect(getWebProtocol("https,https", 'http')).toBe('https'); + expect(getWebProtocol('https,https', 'http')).toBe('https'); }); }); }); describe('convertDistRemoteToLocalTarballUrls', () => { test('should build a URI for dist tarball based on new domain', () => { - const convertDist = convertDistRemoteToLocalTarballUrls(cloneMetadata(), - { - headers: { - host: fakeHost - }, - // @ts-ignore - get: () => 'http', - protocol: 'http' - }); + const convertDist = convertDistRemoteToLocalTarballUrls(cloneMetadata(), { + headers: { + host: fakeHost, + }, + // @ts-ignore + get: () => 'http', + protocol: 'http', + }); expect(convertDist.versions['1.0.0'].dist.tarball).toEqual(buildURI(fakeHost, '1.0.0')); expect(convertDist.versions['1.0.1'].dist.tarball).toEqual(buildURI(fakeHost, '1.0.1')); }); test('should return same URI whether host is missing', () => { - const convertDist = convertDistRemoteToLocalTarballUrls(cloneMetadata(), - { - headers: {}, - // @ts-ignore - get: () => 'http', - protocol: 'http' - }); + const convertDist = convertDistRemoteToLocalTarballUrls(cloneMetadata(), { + headers: {}, + // @ts-ignore + get: () => 'http', + protocol: 'http', + }); expect(convertDist.versions['1.0.0'].dist.tarball).toEqual(convertDist.versions['1.0.0'].dist.tarball); }); }); @@ -149,10 +144,10 @@ describe('Utilities', () => { test('should delete a invalid latest version', () => { const pkg = cloneMetadata(); pkg[DIST_TAGS] = { - latest: '20000' + latest: '20000', }; - normalizeDistTags(pkg) + normalizeDistTags(pkg); expect(Object.keys(pkg[DIST_TAGS])).toHaveLength(0); }); @@ -161,31 +156,31 @@ describe('Utilities', () => { const pkg = cloneMetadata(); pkg[DIST_TAGS] = {}; - normalizeDistTags(pkg) + normalizeDistTags(pkg); - expect(pkg[DIST_TAGS]).toEqual({latest: '1.0.1'}); + expect(pkg[DIST_TAGS]).toEqual({ latest: '1.0.1' }); }); test('should define last published version as latest with a custom dist-tag', () => { const pkg = cloneMetadata(); pkg[DIST_TAGS] = { - beta: '1.0.1' + beta: '1.0.1', }; normalizeDistTags(pkg); - expect(pkg[DIST_TAGS]).toEqual({beta: '1.0.1', latest: '1.0.1'}); + expect(pkg[DIST_TAGS]).toEqual({ beta: '1.0.1', latest: '1.0.1' }); }); test('should convert any array of dist-tags to a plain string', () => { const pkg = cloneMetadata(); pkg[DIST_TAGS] = { - latest: ['1.0.1'] + latest: ['1.0.1'], }; normalizeDistTags(pkg); - expect(pkg[DIST_TAGS]).toEqual({latest: '1.0.1'}); + expect(pkg[DIST_TAGS]).toEqual({ latest: '1.0.1' }); }); }); @@ -202,37 +197,36 @@ describe('Utilities', () => { expect(getVersion(cloneMetadata(), undefined)).toBeUndefined(); expect(getVersion(cloneMetadata(), null)).toBeUndefined(); expect(getVersion(cloneMetadata(), 2)).toBeUndefined(); - }) + }); }); describe('combineBaseUrl', () => { test('should create a URI', () => { - expect(combineBaseUrl("http", 'domain')).toEqual('http://domain'); + expect(combineBaseUrl('http', 'domain')).toEqual('http://domain'); }); test('should create a base url for registry', () => { - expect(combineBaseUrl("http", 'domain', '')).toEqual('http://domain'); - expect(combineBaseUrl("http", 'domain', '/')).toEqual('http://domain'); - expect(combineBaseUrl("http", 'domain', '/prefix/')).toEqual('http://domain/prefix'); - expect(combineBaseUrl("http", 'domain', '/prefix/deep')).toEqual('http://domain/prefix/deep'); - expect(combineBaseUrl("http", 'domain', 'only-prefix')).toEqual('only-prefix'); + expect(combineBaseUrl('http', 'domain', '')).toEqual('http://domain'); + expect(combineBaseUrl('http', 'domain', '/')).toEqual('http://domain'); + expect(combineBaseUrl('http', 'domain', '/prefix/')).toEqual('http://domain/prefix'); + expect(combineBaseUrl('http', 'domain', '/prefix/deep')).toEqual('http://domain/prefix/deep'); + expect(combineBaseUrl('http', 'domain', 'only-prefix')).toEqual('only-prefix'); }); - }); describe('validatePackage', () => { test('should validate package names', () => { - expect(validatePackage("package-name")).toBeTruthy(); - expect(validatePackage("@scope/package-name")).toBeTruthy(); + expect(validatePackage('package-name')).toBeTruthy(); + expect(validatePackage('@scope/package-name')).toBeTruthy(); }); test('should fails on validate package names', () => { - expect(validatePackage("package-name/test/fake")).toBeFalsy(); - expect(validatePackage("@/package-name")).toBeFalsy(); - expect(validatePackage("$%$%#$%$#%#$%$#")).toBeFalsy(); - expect(validatePackage("node_modules")).toBeFalsy(); - expect(validatePackage("__proto__")).toBeFalsy(); - expect(validatePackage("favicon.ico")).toBeFalsy(); + expect(validatePackage('package-name/test/fake')).toBeFalsy(); + expect(validatePackage('@/package-name')).toBeFalsy(); + expect(validatePackage('$%$%#$%$#%#$%$#')).toBeFalsy(); + expect(validatePackage('node_modules')).toBeFalsy(); + expect(validatePackage('__proto__')).toBeFalsy(); + expect(validatePackage('favicon.ico')).toBeFalsy(); }); describe('validateName', () => { @@ -294,7 +288,7 @@ describe('Utilities', () => { }); test('should fails the assertions is not an object', () => { - expect(function ( ) { + expect(function () { // @ts-ignore validateMetadata(''); // @ts-ignore @@ -302,9 +296,9 @@ describe('Utilities', () => { }); test('should fails the assertions is name does not match', () => { - expect(function ( ) { + expect(function () { // @ts-ignore - validateMetadata({}, "no-name"); + validateMetadata({}, 'no-name'); // @ts-ignore }).toThrow(expect.hasAssertions()); }); @@ -312,17 +306,17 @@ describe('Utilities', () => { describe('getVersionFromTarball', () => { test('should get the right version', () => { - const simpleName = 'test-name-4.2.12.tgz' - const complexName = 'test-5.6.4-beta.2.tgz' - const otherComplexName = 'test-3.5.0-6.tgz' - expect(getVersionFromTarball(simpleName)).toEqual('4.2.12') - expect(getVersionFromTarball(complexName)).toEqual('5.6.4-beta.2') - expect(getVersionFromTarball(otherComplexName)).toEqual('3.5.0-6') - }) + const simpleName = 'test-name-4.2.12.tgz'; + const complexName = 'test-5.6.4-beta.2.tgz'; + const otherComplexName = 'test-3.5.0-6.tgz'; + expect(getVersionFromTarball(simpleName)).toEqual('4.2.12'); + expect(getVersionFromTarball(complexName)).toEqual('5.6.4-beta.2'); + expect(getVersionFromTarball(otherComplexName)).toEqual('3.5.0-6'); + }); - test('should don\'n fall at incorrect tarball name', () => { - expect(getVersionFromTarball('incorrectName')).toBeUndefined() - }) + test("should don'n fall at incorrect tarball name", () => { + expect(getVersionFromTarball('incorrectName')).toBeUndefined(); + }); }); }); @@ -363,12 +357,8 @@ describe('Utilities', () => { describe('parseReadme', () => { test('should parse makrdown text to html template', () => { const markdown = '# markdown'; - expect(parseReadme('testPackage', markdown)).toEqual( - '

markdown

' - ); - expect( - parseReadme('testPackage', String(readmeFile('markdown.md'))) - ).toMatchSnapshot(); + expect(parseReadme('testPackage', markdown)).toEqual('

markdown

'); + expect(parseReadme('testPackage', String(readmeFile('markdown.md')))).toMatchSnapshot(); }); test('should pass for conversion of non-ascii to markdown text', () => { @@ -376,30 +366,19 @@ describe('Utilities', () => { const randomText = '%%%%%**##=='; const randomTextMarkdown = 'simple text \n # markdown'; - expect(parseReadme('testPackage', randomText)).toEqual( - '

%%%%%**##==

' - ); - expect(parseReadme('testPackage', simpleText)).toEqual( - '

simple text

' - ); - expect(parseReadme('testPackage', randomTextMarkdown)).toEqual( - '

simple text

\n

markdown

' - ); + expect(parseReadme('testPackage', randomText)).toEqual('

%%%%%**##==

'); + expect(parseReadme('testPackage', simpleText)).toEqual('

simple text

'); + expect(parseReadme('testPackage', randomTextMarkdown)).toEqual('

simple text

\n

markdown

'); }); test('should show error for no readme data', () => { const noData = ''; const loggerError = jest.fn(); const logger = { - error: loggerError + error: loggerError, }; - expect(parseReadme('testPackage', noData, logger)).toEqual( - '

ERROR: No README data found!

' - ); - expect(loggerError).toHaveBeenCalledWith( - { packageName: 'testPackage' }, - '@{packageName}: No readme found' - ); + expect(parseReadme('testPackage', noData, logger)).toEqual('

ERROR: No README data found!

'); + expect(loggerError).toHaveBeenCalledWith({ packageName: 'testPackage' }, '@{packageName}: No readme found'); }); }); @@ -412,7 +391,7 @@ describe('Utilities', () => { const user = { name: 'Verdaccion NPM', email: 'verdaccio@verdaccio.org', - url: 'https://verdaccio.org' + url: 'https://verdaccio.org', }; expect(formatAuthor(user).url).toEqual(user.url); expect(formatAuthor(user).email).toEqual(user.email); diff --git a/packages/verdaccio/test/functional/adduser/adduser.js b/packages/verdaccio/test/functional/adduser/adduser.js index b25a2058a..6f38665b2 100644 --- a/packages/verdaccio/test/functional/adduser/adduser.js +++ b/packages/verdaccio/test/functional/adduser/adduser.js @@ -1,12 +1,13 @@ -import {API_ERROR, HTTP_STATUS} from "@verdaccio/dev-commons"; +import { API_ERROR, HTTP_STATUS } from '@verdaccio/dev-commons'; -export default function(server) { +export default function (server) { describe('npm adduser', () => { const user = String(Math.random()); const pass = String(Math.random()); - beforeAll(function() { - return server.auth(user, pass) + beforeAll(function () { + return server + .auth(user, pass) .status(HTTP_STATUS.CREATED) .body_ok(/user .* created/); }); @@ -14,15 +15,14 @@ export default function(server) { test('should create new user', () => {}); test('should log in', () => { - return server.auth(user, pass) + return server + .auth(user, pass) .status(HTTP_STATUS.CREATED) .body_ok(/you are authenticated as/); }); test('should not register more users', () => { - return server.auth(String(Math.random()), String(Math.random())) - .status(HTTP_STATUS.CONFLICT) - .body_error(API_ERROR.MAX_USERS_REACHED); + return server.auth(String(Math.random()), String(Math.random())).status(HTTP_STATUS.CONFLICT).body_error(API_ERROR.MAX_USERS_REACHED); }); }); } diff --git a/packages/verdaccio/test/functional/adduser/logout.js b/packages/verdaccio/test/functional/adduser/logout.js index 856c23bed..3a8d70642 100644 --- a/packages/verdaccio/test/functional/adduser/logout.js +++ b/packages/verdaccio/test/functional/adduser/logout.js @@ -1,10 +1,10 @@ -import {HTTP_STATUS} from "@verdaccio/dev-commons"; - -export default function(server) { +import { HTTP_STATUS } from '@verdaccio/dev-commons'; +export default function (server) { describe('logout', () => { test('should log out', () => { - return server.logout('some-token') + return server + .logout('some-token') .status(HTTP_STATUS.OK) .body_ok(/Logged out/); }); diff --git a/packages/verdaccio/test/functional/basic/basic.ts b/packages/verdaccio/test/functional/basic/basic.ts index 796e2f7e2..796a1e76d 100644 --- a/packages/verdaccio/test/functional/basic/basic.ts +++ b/packages/verdaccio/test/functional/basic/basic.ts @@ -1,9 +1,9 @@ import fs from 'fs'; import path from 'path'; -import {createTarballHash} from "@verdaccio/utils"; -import { HTTP_STATUS, DIST_TAGS} from "@verdaccio/dev-commons"; +import { createTarballHash } from '@verdaccio/utils'; +import { HTTP_STATUS, DIST_TAGS } from '@verdaccio/dev-commons'; -import {CREDENTIALS, DOMAIN_SERVERS, PORT_SERVER_1, PORT_SERVER_2, TARBALL} from "../config.functional"; +import { CREDENTIALS, DOMAIN_SERVERS, PORT_SERVER_1, PORT_SERVER_2, TARBALL } from '../config.functional'; import whoIam from './whoIam'; import ping from './ping'; import fixturePkg from '../fixtures/package'; @@ -16,14 +16,14 @@ function getPackage(name) { return fixturePkg(name); } -export default function(server: any, server2: any) { +export default function (server: any, server2: any) { describe('basic test endpoints', () => { - const PKG_NAME = 'testpkg'; const PKG_VERSION = '0.0.1'; - beforeAll(function() { - return server.auth(CREDENTIALS.user, CREDENTIALS.password) + beforeAll(function () { + return server + .auth(CREDENTIALS.user, CREDENTIALS.password) .status(HTTP_STATUS.CREATED) .body_ok(/'test'/); }); @@ -32,7 +32,6 @@ export default function(server: any, server2: any) { ping(server); describe('handling packages', () => { - beforeAll(function () { return server.addPackage(PKG_NAME); }); @@ -41,11 +40,13 @@ export default function(server: any, server2: any) { return server.addPackage('testpkg-single-tarball'); }); - test('creating new package', () => {/* test for before() */ + test('creating new package', () => { + /* test for before() */ }); test('downloading non-existent tarball', () => { - return server.getTarball(PKG_NAME, TARBALL) + return server + .getTarball(PKG_NAME, TARBALL) .status(HTTP_STATUS.NOT_FOUND) .body_error(/no such file/); }); @@ -55,17 +56,12 @@ export default function(server: any, server2: any) { }); describe('publishing package', () => { - beforeAll(function () { - return server.putTarball(PKG_NAME, TARBALL, readfile('../fixtures/binary')) - .status(HTTP_STATUS.CREATED) - .body_ok(/.*/); + return server.putTarball(PKG_NAME, TARBALL, readfile('../fixtures/binary')).status(HTTP_STATUS.CREATED).body_ok(/.*/); }); beforeAll(function () { - return server.putTarball('testpkg-single-tarball', 'single', readfile('../fixtures/binary')) - .status(HTTP_STATUS.CREATED) - .body_ok(/.*/); + return server.putTarball('testpkg-single-tarball', 'single', readfile('../fixtures/binary')).status(HTTP_STATUS.CREATED).body_ok(/.*/); }); afterAll(function () { @@ -97,7 +93,8 @@ export default function(server: any, server2: any) { // testexp-incomplete test('downloading newly created tarball', () => { - return server.getTarball(PKG_NAME, TARBALL) + return server + .getTarball(PKG_NAME, TARBALL) .status(200) .then(function (body) { expect(body).toEqual(readfile('../fixtures/binary')); @@ -108,88 +105,88 @@ export default function(server: any, server2: any) { let pkg = getPackage(PKG_NAME); pkg.dist.shasum = createTarballHash().update('fake').digest('hex'); - return server.putVersion(PKG_NAME, PKG_VERSION, pkg) + return server + .putVersion(PKG_NAME, PKG_VERSION, pkg) .status(HTTP_STATUS.BAD_REQUEST) .body_error(/shasum error/); }); describe('publishing version', () => { - beforeAll(function () { const pkg = getPackage(PKG_NAME); pkg.dist.shasum = createTarballHash().update(readfile('../fixtures/binary')).digest('hex'); - return server.putVersion(PKG_NAME, PKG_VERSION, pkg) + return server + .putVersion(PKG_NAME, PKG_VERSION, pkg) .status(HTTP_STATUS.CREATED) .body_ok(/published/); }); describe('should download a package', () => { - beforeAll(function() { - return server.auth(CREDENTIALS.user, CREDENTIALS.password) - .status(HTTP_STATUS.CREATED) - .body_ok(new RegExp(CREDENTIALS.user)); + beforeAll(function () { + return server.auth(CREDENTIALS.user, CREDENTIALS.password).status(HTTP_STATUS.CREATED).body_ok(new RegExp(CREDENTIALS.user)); }); test('should download a newly created package from server1', () => { - return server.getPackage(PKG_NAME) + return server + .getPackage(PKG_NAME) .status(HTTP_STATUS.OK) .then(function (body) { expect(body.name).toEqual(PKG_NAME); expect(body.versions[PKG_VERSION].name).toEqual(PKG_NAME); expect(body.versions[PKG_VERSION].dist.tarball).toEqual(`http://${DOMAIN_SERVERS}:${PORT_SERVER_1}/${PKG_NAME}/-/${TARBALL}`); expect(body[DIST_TAGS]).toEqual({ - latest: PKG_VERSION + latest: PKG_VERSION, }); }); }); test('should downloading a package from server2', () => { - return server2.getPackage(PKG_NAME) + return server2 + .getPackage(PKG_NAME) .status(HTTP_STATUS.OK) .then(function (body) { expect(body.name).toEqual(PKG_NAME); expect(body.versions[PKG_VERSION].name).toEqual(PKG_NAME); expect(body.versions[PKG_VERSION].dist.tarball).toEqual(`http://${DOMAIN_SERVERS}:${PORT_SERVER_2}/${PKG_NAME}/-/${TARBALL}`); expect(body[DIST_TAGS]).toEqual({ - latest: PKG_VERSION + latest: PKG_VERSION, }); }); }); - }); - }); }); }); describe('handle failures on endpoints', () => { - test('should fails trying to fetch non-existent package', () => { - return server.getPackage(PKG_NAME).status(HTTP_STATUS.NOT_FOUND).body_error(/no such package/); + return server + .getPackage(PKG_NAME) + .status(HTTP_STATUS.NOT_FOUND) + .body_error(/no such package/); }); - test( - 'should fails on publish a version for non existing package', - () => { - return server.putVersion('testpxg', PKG_VERSION, getPackage('testpxg')) - .status(HTTP_STATUS.NOT_FOUND) - .body_error(/no such package/); - } - ); + test('should fails on publish a version for non existing package', () => { + return server + .putVersion('testpxg', PKG_VERSION, getPackage('testpxg')) + .status(HTTP_STATUS.NOT_FOUND) + .body_error(/no such package/); + }); test('should be a package not found', () => { - return server.putTarball('nonExistingPackage', TARBALL, readfile('../fixtures/binary')) + return server + .putTarball('nonExistingPackage', TARBALL, readfile('../fixtures/binary')) .status(HTTP_STATUS.NOT_FOUND) .body_error(/no such/); }); test('should fails on publish package in a bad uplink', () => { - return server.putPackage('baduplink', getPackage('baduplink')) + return server + .putPackage('baduplink', getPackage('baduplink')) .status(HTTP_STATUS.SERVICE_UNAVAILABLE) .body_error(/one of the uplinks is down, refuse to publish/); }); - }); }); } diff --git a/packages/verdaccio/test/functional/config.functional.js b/packages/verdaccio/test/functional/config.functional.js index 5fc094358..f74c68003 100644 --- a/packages/verdaccio/test/functional/config.functional.js +++ b/packages/verdaccio/test/functional/config.functional.js @@ -1,8 +1,8 @@ -import {DOMAIN_SERVERS as localhost} from '../test.conf'; +import { DOMAIN_SERVERS as localhost } from '../test.conf'; export const CREDENTIALS = { user: 'test', - password: 'test' + password: 'test', }; export const TARBALL = 'tarball-blahblah-file.name'; diff --git a/packages/verdaccio/test/functional/index.spec.ts b/packages/verdaccio/test/functional/index.spec.ts index 8ac83f59a..c181f8813 100644 --- a/packages/verdaccio/test/functional/index.spec.ts +++ b/packages/verdaccio/test/functional/index.spec.ts @@ -27,7 +27,7 @@ import middleware from './plugins/middleware'; import upLinkCache from './uplinks/cache'; import uplinkTimeout from './uplinks/timeout'; -describe('functional test verdaccio', function() { +describe('functional test verdaccio', function () { jest.setTimeout(20000); // @ts-ignore const server1: IServerBridge = global.__SERVERS__[0]; @@ -63,13 +63,12 @@ describe('functional test verdaccio', function() { adduser(server1); logout(server1); basic(server1, server2); - simpleSearch(server1, server2, app) - + simpleSearch(server1, server2, app); }); -process.on('unhandledRejection', function(err) { - console.error("unhandledRejection", err); - process.nextTick(function() { +process.on('unhandledRejection', function (err) { + console.error('unhandledRejection', err); + process.nextTick(function () { throw err; }); }); diff --git a/packages/verdaccio/test/functional/lib/environment.ts b/packages/verdaccio/test/functional/lib/environment.ts index e98aaeea5..6ad007b7d 100644 --- a/packages/verdaccio/test/functional/lib/environment.ts +++ b/packages/verdaccio/test/functional/lib/environment.ts @@ -1,9 +1,9 @@ import { yellow, green, blue, magenta } from 'kleur'; import path from 'path'; import NodeEnvironment from 'jest-environment-node'; -import {mockServer} from '@verdaccio/mock'; +import { mockServer } from '@verdaccio/mock'; import ExpressServer from './simple_server'; -import {PORT_SERVER_1, PORT_SERVER_2, PORT_SERVER_3} from '../config.functional'; +import { PORT_SERVER_1, PORT_SERVER_2, PORT_SERVER_3 } from '../config.functional'; const EXPRESS_PORT = 55550; @@ -11,7 +11,7 @@ class FunctionalEnvironment extends NodeEnvironment { public config: any; public constructor(config: any) { - super(config) + super(config); } public async startWeb() { @@ -20,7 +20,6 @@ class FunctionalEnvironment extends NodeEnvironment { return await express.start(EXPRESS_PORT); } - public async setup() { // const SILENCE_LOG = !process.env.VERDACCIO_PROCESS_SILENCE || false; // @ts-ignore @@ -33,18 +32,18 @@ class FunctionalEnvironment extends NodeEnvironment { { port: PORT_SERVER_1, config: '/config-1.yaml', - storage: '/server1' + storage: '/server1', }, { port: PORT_SERVER_2, config: '/config-2.yaml', - storage: '/server2' + storage: '/server2', }, { port: PORT_SERVER_3, config: '/config-3.yaml', - storage: '/server3' - } + storage: '/server3', + }, ]; console.log(green('Setup Verdaccio Servers')); @@ -58,7 +57,7 @@ class FunctionalEnvironment extends NodeEnvironment { const server = mockServer(serverConf.port, { storePath, configPath, - silence: false + silence: false, }); const fork = await server.init(binPath); @@ -80,7 +79,7 @@ class FunctionalEnvironment extends NodeEnvironment { console.log(yellow('Teardown Test Environment.')); // @ts-ignore if (!this.global.__SERVERS_PROCESS__) { - throw new Error("There are no servers to stop"); + throw new Error('There are no servers to stop'); } // shutdown verdaccio @@ -95,7 +94,7 @@ class FunctionalEnvironment extends NodeEnvironment { // @ts-ignore public runScript(script: string) { - // @ts-ignore + // @ts-ignore return super.runScript(script); } } diff --git a/packages/verdaccio/test/functional/lib/simple_server.ts b/packages/verdaccio/test/functional/lib/simple_server.ts index 3a9e13337..9708be8ec 100644 --- a/packages/verdaccio/test/functional/lib/simple_server.ts +++ b/packages/verdaccio/test/functional/lib/simple_server.ts @@ -28,7 +28,7 @@ export default class ExpressServer { this.app.use(bodyParser.json()); this.app.use( bodyParser.urlencoded({ - extended: true + extended: true, }) ); diff --git a/packages/verdaccio/test/functional/notifications/notify.ts b/packages/verdaccio/test/functional/notifications/notify.ts index d76eef07b..2fa8b15f9 100644 --- a/packages/verdaccio/test/functional/notifications/notify.ts +++ b/packages/verdaccio/test/functional/notifications/notify.ts @@ -1,30 +1,31 @@ import _ from 'lodash'; -import {HEADERS} from '@verdaccio/dev-commons'; -import {notify} from '@verdaccio/hooks'; -import {DOMAIN_SERVERS, PORT_SERVER_APP} from '../config.functional'; +import { HEADERS } from '@verdaccio/dev-commons'; +import { notify } from '@verdaccio/hooks'; +import { DOMAIN_SERVERS, PORT_SERVER_APP } from '../config.functional'; import { RemoteUser } from '@verdaccio/types'; -export default function(express) { +export default function (express) { const config = { notify: { method: 'POST', - headers: [{ - 'Content-Type': HEADERS.JSON - }], + headers: [ + { + 'Content-Type': HEADERS.JSON, + }, + ], endpoint: `http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/api/notify`, - content: `{"color":"green","message":"New package published: * {{ name }}*. Publisher name: * {{ publisher.name }} *.","notify":true,"message_format":"text"}` - } + content: `{"color":"green","message":"New package published: * {{ name }}*. Publisher name: * {{ publisher.name }} *.","notify":true,"message_format":"text"}`, + }, }; const publisherInfo: RemoteUser = { - name: "publisher-name-test", + name: 'publisher-name-test', real_groups: [], - groups: [] + groups: [], }; describe('notifications', () => { - function parseBody(notification) { const jsonBody = JSON.parse(notification); @@ -41,116 +42,126 @@ export default function(express) { }); }); - test('notification should be send', done => { - const metadata = { - name: "pkg-test" - }; - - // @ts-ignore - notify(metadata, config, publisherInfo, 'foo').then(function (body) { - const jsonBody = parseBody(body); - expect( - `New package published: * ${metadata.name}*. Publisher name: * ${publisherInfo.name} *.`).toBe(jsonBody.message); - done(); - }, function (err) { - expect(err).toBeDefined(); - done(); - }); - }); - - test('notification should be send single header', done => { - const metadata = { - name: "pkg-test" - }; - - const configMultipleHeader = _.cloneDeep(config); - configMultipleHeader.notify.headers = { - // @ts-ignore - 'Content-Type': HEADERS.JSON - }; - - // @ts-ignore - notify(metadata, configMultipleHeader, publisherInfo).then(function (body) { - const jsonBody = parseBody(body); - expect(`New package published: * ${metadata.name}*. Publisher name: * ${publisherInfo.name} *.`).toBe(jsonBody.message); - done(); - }, function (err) { - expect(err).toBeDefined(); - done(); - }); - }); - - test('notification should be send multiple notifications endpoints', done => { - const metadata = { - name: "pkg-test" - }; - // let notificationsCounter = 0; - - const multipleNotificationsEndpoint = { - notify: [] - }; - - for (let i = 0; i < 10; i++) { - const notificationSettings = _.cloneDeep(config.notify); - // basically we allow al notifications - // @ts-ignore - notificationSettings.packagePattern = /^pkg-test$/; - // notificationSettings.packagePatternFlags = 'i'; - // @ts-ignore - multipleNotificationsEndpoint.notify.push(notificationSettings); - } - - // @ts-ignore - notify(metadata, multipleNotificationsEndpoint, publisherInfo).then(function (body) { - body.forEach(function(notification) { - const jsonBody = parseBody(notification); - expect(`New package published: * ${metadata.name}*. Publisher name: * ${publisherInfo.name} *.`).toBe(jsonBody.message); - }); - done(); - }, function (err) { - expect(err).toBeDefined(); - done(); - }); - }); - - test('notification should fails', done => { - const metadata = { - name: "pkg-test" - }; - const configFail = _.cloneDeep(config); - configFail.notify.endpoint = `http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/api/notify/bad`; - - // @ts-ignore - notify(metadata, configFail, publisherInfo).then(function () { - expect(false).toBe('This service should fails with status code 400'); - done(); - }, function (err) { - expect(err).toEqual('bad response'); - done(); - }); - }); - - test('publisher property should not be overridden if it exists in metadata', done => { + test('notification should be send', (done) => { const metadata = { name: 'pkg-test', - publisher: { - name: 'existing-publisher-name' - } }; // @ts-ignore - notify(metadata, config, publisherInfo).then( - function(body) { + notify(metadata, config, publisherInfo, 'foo').then( + function (body) { const jsonBody = parseBody(body); - expect(`New package published: * ${metadata.name}*. Publisher name: * ${metadata.publisher.name} *.`).toBe(jsonBody.message); + expect(`New package published: * ${metadata.name}*. Publisher name: * ${publisherInfo.name} *.`).toBe(jsonBody.message); done(); }, - function(err) { + function (err) { expect(err).toBeDefined(); done(); } ); }); + test('notification should be send single header', (done) => { + const metadata = { + name: 'pkg-test', + }; + + const configMultipleHeader = _.cloneDeep(config); + configMultipleHeader.notify.headers = { + // @ts-ignore + 'Content-Type': HEADERS.JSON, + }; + + // @ts-ignore + notify(metadata, configMultipleHeader, publisherInfo).then( + function (body) { + const jsonBody = parseBody(body); + expect(`New package published: * ${metadata.name}*. Publisher name: * ${publisherInfo.name} *.`).toBe(jsonBody.message); + done(); + }, + function (err) { + expect(err).toBeDefined(); + done(); + } + ); + }); + + test('notification should be send multiple notifications endpoints', (done) => { + const metadata = { + name: 'pkg-test', + }; + // let notificationsCounter = 0; + + const multipleNotificationsEndpoint = { + notify: [], + }; + + for (let i = 0; i < 10; i++) { + const notificationSettings = _.cloneDeep(config.notify); + // basically we allow al notifications + // @ts-ignore + notificationSettings.packagePattern = /^pkg-test$/; + // notificationSettings.packagePatternFlags = 'i'; + // @ts-ignore + multipleNotificationsEndpoint.notify.push(notificationSettings); + } + + // @ts-ignore + notify(metadata, multipleNotificationsEndpoint, publisherInfo).then( + function (body) { + body.forEach(function (notification) { + const jsonBody = parseBody(notification); + expect(`New package published: * ${metadata.name}*. Publisher name: * ${publisherInfo.name} *.`).toBe(jsonBody.message); + }); + done(); + }, + function (err) { + expect(err).toBeDefined(); + done(); + } + ); + }); + + test('notification should fails', (done) => { + const metadata = { + name: 'pkg-test', + }; + const configFail = _.cloneDeep(config); + configFail.notify.endpoint = `http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/api/notify/bad`; + + // @ts-ignore + notify(metadata, configFail, publisherInfo).then( + function () { + expect(false).toBe('This service should fails with status code 400'); + done(); + }, + function (err) { + expect(err).toEqual('bad response'); + done(); + } + ); + }); + + test('publisher property should not be overridden if it exists in metadata', (done) => { + const metadata = { + name: 'pkg-test', + publisher: { + name: 'existing-publisher-name', + }, + }; + + // @ts-ignore + notify(metadata, config, publisherInfo).then( + function (body) { + const jsonBody = parseBody(body); + expect(`New package published: * ${metadata.name}*. Publisher name: * ${metadata.publisher.name} *.`).toBe(jsonBody.message); + done(); + }, + function (err) { + expect(err).toBeDefined(); + done(); + } + ); + }); }); } diff --git a/packages/verdaccio/test/functional/package/access.ts b/packages/verdaccio/test/functional/package/access.ts index 49c6799d6..8a8befcf7 100644 --- a/packages/verdaccio/test/functional/package/access.ts +++ b/packages/verdaccio/test/functional/package/access.ts @@ -1,14 +1,13 @@ -import {buildToken} from "@verdaccio/utils"; -import {API_ERROR, HTTP_STATUS, TOKEN_BASIC} from "@verdaccio/dev-commons"; +import { buildToken } from '@verdaccio/utils'; +import { API_ERROR, HTTP_STATUS, TOKEN_BASIC } from '@verdaccio/dev-commons'; -import {CREDENTIALS} from "../config.functional"; +import { CREDENTIALS } from '../config.functional'; import fixturePkg from '../fixtures/package'; -export default function(server) { - +export default function (server) { describe('package access control', () => { const buildAccesToken = (auth) => { - return buildToken(TOKEN_BASIC, `${(Buffer.from(auth).toString('base64'))}`); + return buildToken(TOKEN_BASIC, `${new Buffer(auth).toString('base64')}`); }; /** @@ -18,18 +17,16 @@ export default function(server) { * @param status {boolean} */ function checkAccess(auth, pkg, status) { - test( - `${(status ? 'allows' : 'forbids')} access ${auth} to ${pkg}`, () => { - server.authstr = auth ? buildAccesToken(auth) : undefined; - const req = server.getPackage(pkg); + test(`${status ? 'allows' : 'forbids'} access ${auth} to ${pkg}`, () => { + server.authstr = auth ? buildAccesToken(auth) : undefined; + const req = server.getPackage(pkg); - if (status === HTTP_STATUS.NOT_FOUND) { - return req.status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); - } else if (status === HTTP_STATUS.FORBIDDEN) { - return req.status(HTTP_STATUS.FORBIDDEN).body_error(API_ERROR.NOT_ALLOWED); - } + if (status === HTTP_STATUS.NOT_FOUND) { + return req.status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); + } else if (status === HTTP_STATUS.FORBIDDEN) { + return req.status(HTTP_STATUS.FORBIDDEN).body_error(API_ERROR.NOT_ALLOWED); } - ); + }); } /** @@ -39,7 +36,7 @@ export default function(server) { * @param status {boolean} */ function checkPublish(auth, pkg, status) { - test(`${(status ? 'allows' : 'forbids')} publish ${auth} to ${pkg}`, () => { + test(`${status ? 'allows' : 'forbids'} publish ${auth} to ${pkg}`, () => { server.authstr = auth ? buildAccesToken(auth) : undefined; const req = server.putPackage(pkg, fixturePkg(pkg)); if (status === HTTP_STATUS.NOT_FOUND) { diff --git a/packages/verdaccio/test/functional/package/gzip.ts b/packages/verdaccio/test/functional/package/gzip.ts index fdfaaaf9b..e9a2cb69a 100644 --- a/packages/verdaccio/test/functional/package/gzip.ts +++ b/packages/verdaccio/test/functional/package/gzip.ts @@ -1,21 +1,22 @@ import zlib from 'zlib'; -import {readFile} from '../lib/test.utils'; -import {HEADER_TYPE, HEADERS, HTTP_STATUS, CHARACTER_ENCODING} from "@verdaccio/dev-commons"; +import { readFile } from '../lib/test.utils'; +import { HEADER_TYPE, HEADERS, HTTP_STATUS, CHARACTER_ENCODING } from '@verdaccio/dev-commons'; -export default function(server, express) { +export default function (server, express) { const PKG_NAME = 'testexp_gzip'; const PKG_VERSION = '0.0.1'; const PKG_BAD_DATA = 'testexp_baddata'; const VERSION_TOTAL = 4; - describe('test gzip support', () => { - beforeAll(function() { - express.get(`/${PKG_NAME}`, function(req, res) { - const pkg = JSON.parse(readFile('../fixtures/publish.json5') - .toString(CHARACTER_ENCODING.UTF8) - .replace(/__NAME__/g, PKG_NAME) - .replace(/__VERSION__/g, PKG_VERSION)); + beforeAll(function () { + express.get(`/${PKG_NAME}`, function (req, res) { + const pkg = JSON.parse( + readFile('../fixtures/publish.json5') + .toString(CHARACTER_ENCODING.UTF8) + .replace(/__NAME__/g, PKG_NAME) + .replace(/__VERSION__/g, PKG_VERSION) + ); // overcoming compress threshold for (let i = 1; i <= VERSION_TOTAL; i++) { @@ -30,7 +31,7 @@ export default function(server, express) { }); }); - express.get(`/${PKG_BAD_DATA}`, function(req, res) { + express.get(`/${PKG_BAD_DATA}`, function (req, res) { expect(req).toBeDefined(); expect(res).toBeDefined(); expect(req.headers[HEADER_TYPE.ACCEPT_ENCODING]).toBe(HEADERS.GZIP); @@ -44,37 +45,41 @@ export default function(server, express) { }); test('should understand non gzipped data from uplink', () => { - return server.getPackage(PKG_NAME) + return server + .getPackage(PKG_NAME) .status(HTTP_STATUS.OK) .response((res) => { expect(res.headers[HEADER_TYPE.CONTENT_ENCODING]).toBeUndefined(); - }).then(body => { + }) + .then((body) => { expect(body.name).toBe(PKG_NAME); expect(Object.keys(body.versions)).toHaveLength(VERSION_TOTAL); }); }); test('should serve gzipped data', () => { - return server.request({ - uri: `/${PKG_NAME}`, - encoding: null, - headers: { - [HEADER_TYPE.ACCEPT_ENCODING]: HEADERS.GZIP, - }, - json: false, - }).status(HTTP_STATUS.OK) - .response(function(res) { + return server + .request({ + uri: `/${PKG_NAME}`, + encoding: null, + headers: { + [HEADER_TYPE.ACCEPT_ENCODING]: HEADERS.GZIP, + }, + json: false, + }) + .status(HTTP_STATUS.OK) + .response(function (res) { expect(res.headers[HEADER_TYPE.CONTENT_ENCODING]).toBe(HEADERS.GZIP); }) - .then(async function(body) { + .then(async function (body) { // should fails since is zipped - expect(function() { + expect(function () { JSON.parse(body.toString(CHARACTER_ENCODING.UTF8)); }).toThrow(/Unexpected/); // we unzip content and check content - await new Promise(function(resolve) { - zlib.gunzip(body, function(err, buffer) { + await new Promise(function (resolve) { + zlib.gunzip(body, function (err, buffer) { expect(err).toBeNull(); expect(buffer).not.toBeNull(); const unzipedBody = JSON.parse(buffer.toString()); diff --git a/packages/verdaccio/test/functional/package/scoped.ts b/packages/verdaccio/test/functional/package/scoped.ts index 16689927a..8b46cb29f 100644 --- a/packages/verdaccio/test/functional/package/scoped.ts +++ b/packages/verdaccio/test/functional/package/scoped.ts @@ -1,33 +1,36 @@ -import {DOMAIN_SERVERS, PORT_SERVER_1, PORT_SERVER_2} from '../config.functional'; -import {generateSha} from '../lib/test.utils'; +import { DOMAIN_SERVERS, PORT_SERVER_1, PORT_SERVER_2 } from '../config.functional'; +import { generateSha } from '../lib/test.utils'; -import {HEADERS, HTTP_STATUS} from '@verdaccio/dev-commons'; -import {DIST_TAGS} from "@verdaccio/dev-commons"; +import { HEADERS, HTTP_STATUS } from '@verdaccio/dev-commons'; +import { DIST_TAGS } from '@verdaccio/dev-commons'; -export default function(server, server2) { +export default function (server, server2) { const SCOPE = '@test/scoped'; const PKG_VERSION = '1.0.0'; const PKG_NAME = 'scoped'; describe('test-scoped', () => { - beforeAll(function() { - return server.request({ - uri: '/@test%2fscoped', - headers: { - 'content-type': HEADERS.JSON, - }, - method: 'PUT', - json: require('./scoped.json'), - }).status(HTTP_STATUS.CREATED); + beforeAll(function () { + return server + .request({ + uri: '/@test%2fscoped', + headers: { + 'content-type': HEADERS.JSON, + }, + method: 'PUT', + json: require('./scoped.json'), + }) + .status(HTTP_STATUS.CREATED); }); test('should publish scope package', () => {}); describe('should get scoped packages tarball', () => { const uploadScopedTarBall = (server) => { - return server.getTarball(SCOPE, `${PKG_NAME}-${PKG_VERSION}.tgz`) + return server + .getTarball(SCOPE, `${PKG_NAME}-${PKG_VERSION}.tgz`) .status(HTTP_STATUS.OK) - .then(function(body) { + .then(function (body) { // not real sha due to utf8 conversion expect(generateSha(body)).toEqual('6e67b14e2c0e450b942e2bc8086b49e90f594790'); }); @@ -40,19 +43,19 @@ export default function(server, server2) { test('should be a scoped tarball from server2', () => { return uploadScopedTarBall(server2); }); - }); describe('should retrieve scoped packages', () => { - const testScopePackage = (server, port) => server.getPackage(SCOPE) - .status(HTTP_STATUS.OK) - .then(function(body) { - expect(body.name).toBe(SCOPE); - expect(body.versions[PKG_VERSION].name).toBe(SCOPE); - expect(body.versions[PKG_VERSION].dist.tarball).toBe( - `http://${DOMAIN_SERVERS}:${port}/@test%2fscoped/-/${PKG_NAME}-${PKG_VERSION}.tgz`); - expect(body[DIST_TAGS]).toEqual({latest: PKG_VERSION}); - }); + const testScopePackage = (server, port) => + server + .getPackage(SCOPE) + .status(HTTP_STATUS.OK) + .then(function (body) { + expect(body.name).toBe(SCOPE); + expect(body.versions[PKG_VERSION].name).toBe(SCOPE); + expect(body.versions[PKG_VERSION].dist.tarball).toBe(`http://${DOMAIN_SERVERS}:${port}/@test%2fscoped/-/${PKG_NAME}-${PKG_VERSION}.tgz`); + expect(body[DIST_TAGS]).toEqual({ latest: PKG_VERSION }); + }); test('scoped package on server1', () => testScopePackage(server, PORT_SERVER_1)); test('scoped package on server2', () => testScopePackage(server2, PORT_SERVER_2)); @@ -60,13 +63,14 @@ export default function(server, server2) { describe('should retrieve a scoped packages under nginx', () => { test('should work nginx workaround', () => { - return server2.request({ - uri: '/@test/scoped/1.0.0' - }).status(HTTP_STATUS.OK) - .then(function(body) { + return server2 + .request({ + uri: '/@test/scoped/1.0.0', + }) + .status(HTTP_STATUS.OK) + .then(function (body) { expect(body.name).toEqual(SCOPE); - expect(body.dist.tarball).toEqual( - `http://${DOMAIN_SERVERS}:${PORT_SERVER_2}/@test%2fscoped/-/${PKG_NAME}-${PKG_VERSION}.tgz`); + expect(body.dist.tarball).toEqual(`http://${DOMAIN_SERVERS}:${PORT_SERVER_2}/@test%2fscoped/-/${PKG_NAME}-${PKG_VERSION}.tgz`); }); }); }); diff --git a/packages/verdaccio/test/functional/performance/race.ts b/packages/verdaccio/test/functional/performance/race.ts index a54b9661b..cbac801a4 100644 --- a/packages/verdaccio/test/functional/performance/race.ts +++ b/packages/verdaccio/test/functional/performance/race.ts @@ -1,11 +1,10 @@ import async from 'async'; -import { HTTP_STATUS } from "@verdaccio/dev-commons"; +import { HTTP_STATUS } from '@verdaccio/dev-commons'; let okTotalSum = 0; -import racePkg from '../fixtures/package'; - -export default function(server) { +import racePkg from '../fixtures/package'; +export default function (server) { describe('should test race condition on publish packages', () => { const MAX_COUNT = 20; const PKG_NAME = 'race'; @@ -14,14 +13,15 @@ export default function(server) { const UNAVAILABLE = 'unavailable'; beforeAll(function () { - return server.putPackage(PKG_NAME, racePkg(PKG_NAME)) + return server + .putPackage(PKG_NAME, racePkg(PKG_NAME)) .status(HTTP_STATUS.CREATED) .body_ok(/created new package/); }); test('creating new package', () => {}); - test('should uploading 10 same versions and ignore 9', callback => { + test('should uploading 10 same versions and ignore 9', (callback) => { let listOfRequest = []; for (let i = 0; i < MAX_COUNT; i++) { // @ts-ignore @@ -30,11 +30,14 @@ export default function(server) { data.rand = Math.random(); let _res; - server.putVersion(PKG_NAME, '0.0.1', data).response(function (res) { - _res = res; - }).then(function (body) { - callback(null, [_res, body]); - }); + server + .putVersion(PKG_NAME, '0.0.1', data) + .response(function (res) { + _res = res; + }) + .then(function (body) { + callback(null, [_res, body]); + }); }); } @@ -71,14 +74,15 @@ export default function(server) { }); }); - test('shoul uploading 10 diff versions and accept 10', callback => { + test('shoul uploading 10 diff versions and accept 10', (callback) => { const listofRequest = []; for (let i = 0; i < MAX_COUNT; i++) { // @ts-ignore listofRequest.push(function (callback) { let _res; - server.putVersion(PKG_NAME, '0.1.' + String(i), racePkg(PKG_NAME)) + server + .putVersion(PKG_NAME, '0.1.' + String(i), racePkg(PKG_NAME)) .response(function (res) { _res = res; }) @@ -120,10 +124,13 @@ export default function(server) { }); }); - afterAll(function() { - return server.getPackage(PKG_NAME).status(HTTP_STATUS.OK).then(function (body) { - expect(Object.keys(body.versions)).toHaveLength(okTotalSum); - }); + afterAll(function () { + return server + .getPackage(PKG_NAME) + .status(HTTP_STATUS.OK) + .then(function (body) { + expect(Object.keys(body.versions)).toHaveLength(okTotalSum); + }); }); }); } diff --git a/packages/verdaccio/test/functional/plugins/auth.ts b/packages/verdaccio/test/functional/plugins/auth.ts index 27bfdbc21..1397bc133 100644 --- a/packages/verdaccio/test/functional/plugins/auth.ts +++ b/packages/verdaccio/test/functional/plugins/auth.ts @@ -1,6 +1,6 @@ -import {HTTP_STATUS, API_ERROR} from "@verdaccio/dev-commons"; +import { HTTP_STATUS, API_ERROR } from '@verdaccio/dev-commons'; -export default function(server2) { +export default function (server2) { // credentials const USER1 = 'authtest'; const USER2 = 'authtest2'; @@ -13,39 +13,38 @@ export default function(server2) { const UNEXISTING_PKG_NAME = 'test-auth-allow'; const requestAuthFail = (user, pass, message, statusCode) => { - return server2.auth(user, pass) + return server2 + .auth(user, pass) .status(statusCode) .body_error(message) - .then(function() { + .then(function () { return server2.whoami(); }) - .then(function(username) { + .then(function (username) { expect(username).toBeUndefined(); }); }; const requestAuthOk = (user, pass, regex, statusCode) => { - return server2.auth(user, pass) + return server2 + .auth(user, pass) .status(statusCode) .body_ok(regex) - .then(function() { + .then(function () { return server2.whoami(); }) - .then(function(username) { + .then(function (username) { expect(username).toBe(user); }); - }; describe('plugin authentication', () => { - describe('test users authentication', () => { - test('should not authenticate user1 with wrong password', () => { - return requestAuthFail(USER1, WRONG_PASSWORD, 'i don\'t like your password', HTTP_STATUS.UNAUTHORIZED); + return requestAuthFail(USER1, WRONG_PASSWORD, "i don't like your password", HTTP_STATUS.UNAUTHORIZED); }); test('should not authenticate user2 with wrong password', () => { - return requestAuthFail(USER2, WRONG_PASSWORD, 'i don\'t like your password', HTTP_STATUS.UNAUTHORIZED); + return requestAuthFail(USER2, WRONG_PASSWORD, "i don't like your password", HTTP_STATUS.UNAUTHORIZED); }); test('should right user2 password handled by plugin', () => { @@ -55,63 +54,44 @@ export default function(server2) { test('should right user1 password handled by plugin', () => { return requestAuthOk(USER1, CORRECT_PASSWORD, new RegExp(USER1), HTTP_STATUS.CREATED); }); - }); describe('test package access authorization', () => { - describe(`access with user ${USER1} on server2`, () => { - beforeAll(function() { - return server2.auth(USER1, CORRECT_PASSWORD) - .status(HTTP_STATUS.CREATED) - .body_ok(new RegExp(USER1)); + beforeAll(function () { + return server2.auth(USER1, CORRECT_PASSWORD).status(HTTP_STATUS.CREATED).body_ok(new RegExp(USER1)); }); test(`should fails (404) on access ${UNEXISTING_PKG_NAME}`, () => { - return server2.getPackage(UNEXISTING_PKG_NAME) - .status(HTTP_STATUS.NOT_FOUND) - .body_error(API_ERROR.NO_PACKAGE); + return server2.getPackage(UNEXISTING_PKG_NAME).status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); }); test(`should fails (403) access ${ONLY_ACCESS_BY_USER_2}`, () => { - return server2.getPackage(ONLY_ACCESS_BY_USER_2) - .status(HTTP_STATUS.FORBIDDEN) - .body_error(API_ERROR.NOT_ALLOWED); + return server2.getPackage(ONLY_ACCESS_BY_USER_2).status(HTTP_STATUS.FORBIDDEN).body_error(API_ERROR.NOT_ALLOWED); }); test(`should fails (404) access ${AUTH_PKG_ACCESS_NAME}`, () => { - return server2.getPackage(AUTH_PKG_ACCESS_NAME) - .status(HTTP_STATUS.NOT_FOUND) - .body_error(API_ERROR.NO_PACKAGE); + return server2.getPackage(AUTH_PKG_ACCESS_NAME).status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); }); }); describe(`access with user ${USER2} on server2`, () => { - beforeAll(function() { - return server2.auth(USER2, CORRECT_PASSWORD) - .status(HTTP_STATUS.CREATED) - .body_ok(new RegExp(USER2)); + beforeAll(function () { + return server2.auth(USER2, CORRECT_PASSWORD).status(HTTP_STATUS.CREATED).body_ok(new RegExp(USER2)); }); test(`should fails (403) on access ${UNEXISTING_PKG_NAME}`, () => { - return server2.getPackage(UNEXISTING_PKG_NAME) - .status(HTTP_STATUS.FORBIDDEN) - .body_error(API_ERROR.NOT_ALLOWED); + return server2.getPackage(UNEXISTING_PKG_NAME).status(HTTP_STATUS.FORBIDDEN).body_error(API_ERROR.NOT_ALLOWED); }); test(`should fails (403) on access ${DENY_PKG_NAME}`, () => { - return server2.getPackage(DENY_PKG_NAME) - .status(HTTP_STATUS.FORBIDDEN) - .body_error(API_ERROR.NOT_ALLOWED); + return server2.getPackage(DENY_PKG_NAME).status(HTTP_STATUS.FORBIDDEN).body_error(API_ERROR.NOT_ALLOWED); }); test(`should fails (404) access ${AUTH_PKG_ACCESS_NAME}`, () => { - return server2.getPackage(AUTH_PKG_ACCESS_NAME) - .status(HTTP_STATUS.NOT_FOUND) - .body_error(API_ERROR.NO_PACKAGE); + return server2.getPackage(AUTH_PKG_ACCESS_NAME).status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); }); }); - }); }); } diff --git a/packages/verdaccio/test/functional/plugins/middleware.ts b/packages/verdaccio/test/functional/plugins/middleware.ts index 18ffeef2c..f50334acf 100644 --- a/packages/verdaccio/test/functional/plugins/middleware.ts +++ b/packages/verdaccio/test/functional/plugins/middleware.ts @@ -1,23 +1,25 @@ -import {HTTP_STATUS} from "@verdaccio/dev-commons"; +import { HTTP_STATUS } from '@verdaccio/dev-commons'; export default function (server2) { describe('test plugin middlewares', () => { test('should serve the registered route ES5', () => { - return server2.request({ - uri: '/test/route', - method: 'GET' - }) + return server2 + .request({ + uri: '/test/route', + method: 'GET', + }) .status(HTTP_STATUS.OK) - .body_ok('this is a custom route') + .body_ok('this is a custom route'); }); test('should serve the registered route ES6', () => { - return server2.request({ - uri: '/test/route/es6', - method: 'GET' - }) + return server2 + .request({ + uri: '/test/route/es6', + method: 'GET', + }) .status(HTTP_STATUS.OK) - .body_ok('this is a custom route es6') + .body_ok('this is a custom route es6'); }); - }) + }); } diff --git a/packages/verdaccio/test/functional/pre-setup.js b/packages/verdaccio/test/functional/pre-setup.js index 19decbf84..31af75e4d 100644 --- a/packages/verdaccio/test/functional/pre-setup.js +++ b/packages/verdaccio/test/functional/pre-setup.js @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-var-requires */ require('@babel/register')({ - extensions: [".ts", ".js"] + extensions: ['.ts', '.js'], }); module.exports = require('./lib/setup'); diff --git a/packages/verdaccio/test/functional/readme/readme.ts b/packages/verdaccio/test/functional/readme/readme.ts index d245e480f..de222a5ad 100644 --- a/packages/verdaccio/test/functional/readme/readme.ts +++ b/packages/verdaccio/test/functional/readme/readme.ts @@ -1,32 +1,31 @@ -import {DEFAULT_NO_README, HTTP_STATUS} from '@verdaccio/dev-commons'; +import { DEFAULT_NO_README, HTTP_STATUS } from '@verdaccio/dev-commons'; import pkgReadmeJSON from './pkg-readme.json'; import pkgNoReadmeJSON from './pkg-no-readme.json'; export default function (server, server2) { - describe('should test readme', () => { const README_PKG1 = 'readme-test'; const README_PKG2 = 'readme-test-no-readme'; const README_MESSAGE = 'this is a readme'; - beforeAll(async function() { - await server.putPackage('readme-test', pkgReadmeJSON) - .status(HTTP_STATUS.CREATED); - await server.putPackage(README_PKG2, pkgNoReadmeJSON) - .status(HTTP_STATUS.CREATED); + beforeAll(async function () { + await server.putPackage('readme-test', pkgReadmeJSON).status(HTTP_STATUS.CREATED); + await server.putPackage(README_PKG2, pkgNoReadmeJSON).status(HTTP_STATUS.CREATED); }); test('add pkg', () => {}); describe('should check readme file', () => { const matchReadme = (serverRef, pkgName = README_PKG1, readmeMessage = README_MESSAGE) => { - return serverRef.request({ - uri: `/-/verdaccio/package/readme/${pkgName}` - }).status(HTTP_STATUS.OK).then(function(body) { - - expect(body).toEqual(`

${readmeMessage}

`); - }); + return serverRef + .request({ + uri: `/-/verdaccio/package/readme/${pkgName}`, + }) + .status(HTTP_STATUS.OK) + .then(function (body) { + expect(body).toEqual(`

${readmeMessage}

`); + }); }; test('should fetch server2 over uplink server1', () => { @@ -44,8 +43,6 @@ export default function (server, server2) { test.skip('should fetch not found readme package on local server1', () => { return matchReadme(server2, README_PKG2, DEFAULT_NO_README); }); - - }); }); } diff --git a/packages/verdaccio/test/functional/sanity/incomplete.ts b/packages/verdaccio/test/functional/sanity/incomplete.ts index 75a6bdf5c..e37ea8b35 100644 --- a/packages/verdaccio/test/functional/sanity/incomplete.ts +++ b/packages/verdaccio/test/functional/sanity/incomplete.ts @@ -1,24 +1,24 @@ -import {API_ERROR, HEADER_TYPE, HTTP_STATUS} from '@verdaccio/dev-commons'; +import { API_ERROR, HEADER_TYPE, HTTP_STATUS } from '@verdaccio/dev-commons'; -import {DOMAIN_SERVERS, PORT_SERVER_APP} from '../config.functional'; +import { DOMAIN_SERVERS, PORT_SERVER_APP } from '../config.functional'; const defaultPkg = { - 'name': 'testexp-incomplete', - 'versions': { + name: 'testexp-incomplete', + versions: { '0.1.0': { - 'name': 'testexp_tags', - 'version': '0.1.0', - 'dist': { - 'shasum': 'fake', - 'tarball': `http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/testexp-incomplete/-/content-length.tar.gz`, + name: 'testexp_tags', + version: '0.1.0', + dist: { + shasum: 'fake', + tarball: `http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/testexp-incomplete/-/content-length.tar.gz`, }, }, '0.1.1': { - 'name': 'testexp_tags', - 'version': '0.1.1', - 'dist': { - 'shasum': 'fake', - 'tarball': `http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/testexp-incomplete/-/chunked.tar.gz`, + name: 'testexp_tags', + version: '0.1.1', + dist: { + shasum: 'fake', + tarball: `http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/testexp-incomplete/-/chunked.tar.gz`, }, }, }, @@ -28,7 +28,6 @@ export default function (server, express) { const listofCalls = [HEADER_TYPE.CONTENT_LENGTH, 'chunked']; describe('test send incomplete packages', () => { - beforeAll(function () { express.get('/testexp-incomplete', function (_, res) { res.send(defaultPkg); @@ -36,7 +35,7 @@ export default function (server, express) { }); listofCalls.forEach((type) => { - test(`should not store tarballs / ${type}`, callback => { + test(`should not store tarballs / ${type}`, (callback) => { let called; express.get(`/testexp-incomplete/-/${type}.tar.gz`, function (_, response) { if (called) { @@ -57,18 +56,21 @@ export default function (server, express) { }, 10); }); - server.request({uri: '/testexp-incomplete/-/' + type + '.tar.gz'}) + server + .request({ uri: '/testexp-incomplete/-/' + type + '.tar.gz' }) .status(HTTP_STATUS.OK) .response(function (res) { if (type !== 'chunked') { expect(parseInt(res.headers[HEADER_TYPE.CONTENT_LENGTH], 10)).toBe(1e6); } - }).then(function (body) { + }) + .then(function (body) { expect(body).toMatch(/test test test/); }); function cb() { - server.request({uri: '/testexp-incomplete/-/' + type + '.tar.gz'}) + server + .request({ uri: '/testexp-incomplete/-/' + type + '.tar.gz' }) .body_error(API_ERROR.INTERNAL_SERVER_ERROR) .then(function () { callback(); diff --git a/packages/verdaccio/test/functional/sanity/mirror.ts b/packages/verdaccio/test/functional/sanity/mirror.ts index 12b89c10b..644ab93cd 100644 --- a/packages/verdaccio/test/functional/sanity/mirror.ts +++ b/packages/verdaccio/test/functional/sanity/mirror.ts @@ -1,16 +1,17 @@ -import {API_MESSAGE, HTTP_STATUS} from "@verdaccio/dev-commons"; +import { API_MESSAGE, HTTP_STATUS } from '@verdaccio/dev-commons'; -import generatePkg from '../fixtures/package'; -import {readFile} from '../lib/test.utils'; -import {TARBALL} from '../config.functional'; +import generatePkg from '../fixtures/package'; +import { readFile } from '../lib/test.utils'; +import { TARBALL } from '../config.functional'; -const getBinary = () => readFile('../fixtures/binary'); +const getBinary = () => readFile('../fixtures/binary'); export default function (server, server2) { - describe('anti-loop testing', () => { test('testing anti-loop', () => { - return server2.getPackage('testloop').status(HTTP_STATUS.NOT_FOUND) + return server2 + .getPackage('testloop') + .status(HTTP_STATUS.NOT_FOUND) .body_error(/no such package/); }); }); @@ -24,16 +25,15 @@ export default function (server, server2) { describe(`testing mirror for ${pkg}`, () => { beforeAll(function () { - return server2.putPackage(pkg, generatePkg(pkg)) - .status(HTTP_STATUS.CREATED) - .body_ok(API_MESSAGE.PKG_CREATED); + return server2.putPackage(pkg, generatePkg(pkg)).status(HTTP_STATUS.CREATED).body_ok(API_MESSAGE.PKG_CREATED); }); test(prefix + 'creating new package', () => {}); describe(`${pkg}`, () => { beforeAll(function () { - return server2.putVersion(pkg, '0.1.1', generatePkg(pkg)) + return server2 + .putVersion(pkg, '0.1.1', generatePkg(pkg)) .status(HTTP_STATUS.CREATED) .body_ok(/published/); }); @@ -46,15 +46,14 @@ export default function (server, server2) { describe('should put a tarball', () => { beforeAll(function () { - return server2.putTarball(pkg, TARBALL, getBinary()) - .status(HTTP_STATUS.CREATED) - .body_ok(/.*/); + return server2.putTarball(pkg, TARBALL, getBinary()).status(HTTP_STATUS.CREATED).body_ok(/.*/); }); test(`should ${prefix} uploading new tarball`, () => {}); test(`should ${prefix} downloading tarball from server2`, () => { - return server2.getTarball(pkg, TARBALL) + return server2 + .getTarball(pkg, TARBALL) .status(HTTP_STATUS.OK) .then(function (body) { expect(body).toEqual(getBinary()); @@ -66,7 +65,8 @@ export default function (server, server2) { }); test(`should ${prefix} downloading tarball from server1`, () => { - return server.getTarball(pkg, TARBALL) + return server + .getTarball(pkg, TARBALL) .status(HTTP_STATUS.OK) .then(function (body) { expect(body).toEqual(getBinary()); diff --git a/packages/verdaccio/test/functional/sanity/nullstorage.ts b/packages/verdaccio/test/functional/sanity/nullstorage.ts index 443d5ae94..57ab39b8f 100644 --- a/packages/verdaccio/test/functional/sanity/nullstorage.ts +++ b/packages/verdaccio/test/functional/sanity/nullstorage.ts @@ -1,73 +1,79 @@ -import {createTarballHash} from "@verdaccio/utils"; -import {API_ERROR, HTTP_STATUS} from "@verdaccio/dev-commons"; -import {DIST_TAGS} from '@verdaccio/dev-commons'; +import { createTarballHash } from '@verdaccio/utils'; +import { API_ERROR, HTTP_STATUS } from '@verdaccio/dev-commons'; +import { DIST_TAGS } from '@verdaccio/dev-commons'; -import {DOMAIN_SERVERS, PORT_SERVER_1, TARBALL} from '../config.functional'; -import generatePkg from '../fixtures/package'; -import {readFile} from '../lib/test.utils'; +import { DOMAIN_SERVERS, PORT_SERVER_1, TARBALL } from '../config.functional'; +import generatePkg from '../fixtures/package'; +import { readFile } from '../lib/test.utils'; function getBinary() { return readFile('../fixtures/binary'); } export default function (server, server2) { - const PKG_NAME = 'test-nullstorage2'; const PKG_VERSION = '0.0.1'; // const TARBALL = `${PKG_NAME}-file.name`; describe('should test a scenario when tarball is being fetch from uplink', () => { - describe(`should check whether ${PKG_NAME} is on server1`, () => { test('should fails on fetch non-existent package on server1', () => { - return server.getPackage('test-nullstorage-nonexist').status(HTTP_STATUS.NOT_FOUND) - .body_error(API_ERROR.NO_PACKAGE); + return server.getPackage('test-nullstorage-nonexist').status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); }); }); describe(`should check whether ${PKG_NAME} is on server2`, () => { - beforeAll(function() { + beforeAll(function () { return server2.addPackage(PKG_NAME); }); - test('should create a new package on server2', () => {/* test for before() */}); + test('should create a new package on server2', () => { + /* test for before() */ + }); test('should fails on download a non existent tarball from server1', () => { - return server.getTarball(PKG_NAME, TARBALL) + return server + .getTarball(PKG_NAME, TARBALL) .status(HTTP_STATUS.NOT_FOUND) .body_error(/no such file/); }); describe(`should succesfully publish ${PKG_NAME} package on server2`, () => { - beforeAll(function() { + beforeAll(function () { return server2.putTarball(PKG_NAME, TARBALL, getBinary()).status(HTTP_STATUS.CREATED).body_ok(/.*/); }); - beforeAll(function() { + beforeAll(function () { let pkg = generatePkg(PKG_NAME); pkg.dist.shasum = createTarballHash().update(getBinary()).digest('hex'); - return server2.putVersion(PKG_NAME, PKG_VERSION, pkg) - .status(HTTP_STATUS.CREATED).body_ok(/published/); + return server2 + .putVersion(PKG_NAME, PKG_VERSION, pkg) + .status(HTTP_STATUS.CREATED) + .body_ok(/published/); }); - test(`should publish a new version for ${PKG_NAME} on server 2`, () => {/* test for before() */}); + test(`should publish a new version for ${PKG_NAME} on server 2`, () => { + /* test for before() */ + }); test(`should fetch the newly created published tarball for ${PKG_NAME} from server1 on server2`, () => { - return server.getTarball(PKG_NAME, TARBALL) + return server + .getTarball(PKG_NAME, TARBALL) .status(HTTP_STATUS.OK) - .then(function(body) { + .then(function (body) { expect(body).toEqual(getBinary()); }); }); test(`should fetch metadata for ${PKG_NAME} match from server1`, () => { - return server.getPackage(PKG_NAME) + return server + .getPackage(PKG_NAME) .status(HTTP_STATUS.OK) - .then(function(body) { + .then(function (body) { expect(body.name).toBe(PKG_NAME); expect(body.versions[PKG_VERSION].name).toBe(PKG_NAME); expect(body.versions[PKG_VERSION].dist.tarball).toBe(`http://${DOMAIN_SERVERS}:${PORT_SERVER_1}/${PKG_NAME}/-/${TARBALL}`); - expect(body[DIST_TAGS]).toEqual({latest: PKG_VERSION}); + expect(body[DIST_TAGS]).toEqual({ latest: PKG_VERSION }); }); }); }); diff --git a/packages/verdaccio/test/functional/sanity/racycrash.ts b/packages/verdaccio/test/functional/sanity/racycrash.ts index 8a750e89c..634f5f5ad 100644 --- a/packages/verdaccio/test/functional/sanity/racycrash.ts +++ b/packages/verdaccio/test/functional/sanity/racycrash.ts @@ -1,38 +1,37 @@ -import {DOMAIN_SERVERS, PORT_SERVER_APP} from '../config.functional'; -import {API_ERROR, HEADER_TYPE, HTTP_STATUS} from '@verdaccio/dev-commons'; - -export default function(server, express) { +import { DOMAIN_SERVERS, PORT_SERVER_APP } from '../config.functional'; +import { API_ERROR, HEADER_TYPE, HTTP_STATUS } from '@verdaccio/dev-commons'; +export default function (server, express) { describe('shoul test for unexpected client hangs', () => { let handleResponseTarball; - beforeAll(function() { - express.get('/testexp-racycrash', function(request, response) { + beforeAll(function () { + express.get('/testexp-racycrash', function (request, response) { response.send({ - 'name': 'testexp-racycrash', - 'versions': { + name: 'testexp-racycrash', + versions: { '0.1.0': { - 'name': 'testexp_tags', - 'version': '0.1.0', - 'dist': { - 'shasum': 'fake', - 'tarball': `http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/testexp-racycrash/-/test.tar.gz`, + name: 'testexp_tags', + version: '0.1.0', + dist: { + shasum: 'fake', + tarball: `http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/testexp-racycrash/-/test.tar.gz`, }, }, }, }); }); - express.get('/testexp-racycrash/-/test.tar.gz', function(request, response) { + express.get('/testexp-racycrash/-/test.tar.gz', function (request, response) { handleResponseTarball(response); }); }); - test('should not crash on error if client disconnects', callback => { - handleResponseTarball = function(res) { + test('should not crash on error if client disconnects', (callback) => { + handleResponseTarball = function (res) { res.header(HEADER_TYPE.CONTENT_LENGTH, 1e6); res.write('test test test'); - setTimeout(function() { + setTimeout(function () { res.write('-'); // destroy the connection res.socket.destroy(); @@ -40,28 +39,27 @@ export default function(server, express) { }, HTTP_STATUS.OK); }; - server.request({uri: '/testexp-racycrash/-/test.tar.gz'}) - .then(function(body) { - expect(body).toEqual('test test test'); - }); + server.request({ uri: '/testexp-racycrash/-/test.tar.gz' }).then(function (body) { + expect(body).toEqual('test test test'); + }); function cb() { // test for NOT crashing - server.request({uri: '/testexp-racycrash'}) + server + .request({ uri: '/testexp-racycrash' }) .status(HTTP_STATUS.OK) - .then(function() { + .then(function () { callback(); }); } }); test('should not store tarball', () => { - handleResponseTarball = function(res) { + handleResponseTarball = function (res) { res.socket.destroy(); }; - return server.request({uri: '/testexp-racycrash/-/test.tar.gz'}) - .body_error(API_ERROR.INTERNAL_SERVER_ERROR); + return server.request({ uri: '/testexp-racycrash/-/test.tar.gz' }).body_error(API_ERROR.INTERNAL_SERVER_ERROR); }); }); } diff --git a/packages/verdaccio/test/functional/sanity/security.ts b/packages/verdaccio/test/functional/sanity/security.ts index b707433e3..389efe4d6 100644 --- a/packages/verdaccio/test/functional/sanity/security.ts +++ b/packages/verdaccio/test/functional/sanity/security.ts @@ -1,67 +1,71 @@ import _ from 'lodash'; -import {HTTP_STATUS} from '@verdaccio/dev-commons'; - -export default function(server) { +import { HTTP_STATUS } from '@verdaccio/dev-commons'; +export default function (server) { describe('should test security on endpoints', () => { beforeAll(function () { return server.addPackage('testpkg-sec'); }); test('should fails on fetch bad pkg #1', () => { - return server.getPackage('__proto__') + return server + .getPackage('__proto__') .status(HTTP_STATUS.FORBIDDEN) .body_error(/invalid package/); }); test('should fails on fetch bad pkg #2', () => { - return server.getPackage('__proto__') + return server + .getPackage('__proto__') .status(HTTP_STATUS.FORBIDDEN) .body_error(/invalid package/); }); test('should do not fails on __proto__, connect stuff', () => { - return server.request({uri: '/testpkg-sec?__proto__=1'}) - .then(function (body) { - // test for NOT outputting stack trace - expect(_.isNil(body) || _.isObject(body) || body.indexOf('node_modules')).toBeTruthy(); + return server.request({ uri: '/testpkg-sec?__proto__=1' }).then(function (body) { + // test for NOT outputting stack trace + expect(_.isNil(body) || _.isObject(body) || body.indexOf('node_modules')).toBeTruthy(); - // test for NOT crashing - return server.request({uri: '/testpkg-sec'}).status(HTTP_STATUS.OK); - }); + // test for NOT crashing + return server.request({ uri: '/testpkg-sec' }).status(HTTP_STATUS.OK); + }); }); test('should fails and do not return __proto__ as an attachment', () => { - return server.request({uri: '/testpkg-sec/-/__proto__'}) + return server + .request({ uri: '/testpkg-sec/-/__proto__' }) .status(HTTP_STATUS.FORBIDDEN) .body_error(/invalid filename/); }); test('should fails on fetch silly things - reading #1', () => { - return server.request({uri: '/testpkg-sec/-/../../../../../../../../etc/passwd'}) - .status(HTTP_STATUS.NOT_FOUND); + return server.request({ uri: '/testpkg-sec/-/../../../../../../../../etc/passwd' }).status(HTTP_STATUS.NOT_FOUND); }); test('should fails on fetch silly things - reading #2', () => { - return server.request({uri: '/testpkg-sec/-/%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd'}) + return server + .request({ uri: '/testpkg-sec/-/%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd' }) .status(HTTP_STATUS.FORBIDDEN) .body_error(/invalid filename/); }); test('should fails on fetch silly things - writing #1', () => { - return server.putTarball('testpkg-sec', '__proto__', '{}') + return server + .putTarball('testpkg-sec', '__proto__', '{}') .status(HTTP_STATUS.FORBIDDEN) .body_error(/invalid filename/); }); test('should fails on fetch silly things - writing #3', () => { - return server.putTarball('testpkg-sec', 'node_modules', '{}') + return server + .putTarball('testpkg-sec', 'node_modules', '{}') .status(HTTP_STATUS.FORBIDDEN) .body_error(/invalid filename/); }); test('should fails on fetch silly things - writing #4', () => { - return server.putTarball('testpkg-sec', '../testpkg.tgz', '{}') + return server + .putTarball('testpkg-sec', '../testpkg.tgz', '{}') .status(HTTP_STATUS.FORBIDDEN) .body_error(/invalid filename/); }); diff --git a/packages/verdaccio/test/functional/scenarios/gh29.ts b/packages/verdaccio/test/functional/scenarios/gh29.ts index fb65d3f96..90c55a67a 100644 --- a/packages/verdaccio/test/functional/scenarios/gh29.ts +++ b/packages/verdaccio/test/functional/scenarios/gh29.ts @@ -1,13 +1,13 @@ import fs from 'fs'; import path from 'path'; -import {HTTP_STATUS} from "@verdaccio/dev-commons"; -import {createTarballHash} from "@verdaccio/utils"; +import { HTTP_STATUS } from '@verdaccio/dev-commons'; +import { createTarballHash } from '@verdaccio/utils'; -import {TARBALL} from '../config.functional'; +import { TARBALL } from '../config.functional'; import requirePackage from '../fixtures/package'; function readfile(filePath) { - const folder = path.join(__dirname , filePath); + const folder = path.join(__dirname, filePath); return fs.readFileSync(folder); } @@ -18,15 +18,17 @@ const pkgName = 'testpkg-gh29'; export default function (server, server2) { describe('pkg-gh29 #1', () => { test('downloading non-existent tarball #1 / srv2', () => { - return server2.getTarball(pkgName, TARBALL) + return server2 + .getTarball(pkgName, TARBALL) .status(HTTP_STATUS.NOT_FOUND) .body_error(/no such package/); }); }); describe('pkg-gh29 #2', () => { - beforeAll(function() { - return server.putPackage(pkgName, requirePackage(pkgName)) + beforeAll(function () { + return server + .putPackage(pkgName, requirePackage(pkgName)) .status(HTTP_STATUS.CREATED) .body_ok(/created new package/); }); @@ -34,25 +36,25 @@ export default function (server, server2) { test('creating new package / srv1', () => {}); test('downloading non-existent tarball #2 / srv2', () => { - return server2.getTarball(pkgName, TARBALL) + return server2 + .getTarball(pkgName, TARBALL) .status(HTTP_STATUS.NOT_FOUND) .body_error(/no such file available/); }); describe('tarball', () => { - beforeAll(function() { - return server.putTarball(pkgName, TARBALL, readfile(binary)) - .status(HTTP_STATUS.CREATED) - .body_ok(/.*/); + beforeAll(function () { + return server.putTarball(pkgName, TARBALL, readfile(binary)).status(HTTP_STATUS.CREATED).body_ok(/.*/); }); test('uploading new tarball / srv1', () => {}); describe('pkg version', () => { - beforeAll(function() { + beforeAll(function () { const pkg = requirePackage(pkgName); pkg.dist.shasum = createTarballHash().update(readfile(binary)).digest('hex'); - return server.putVersion(pkgName, '0.0.1', pkg) + return server + .putVersion(pkgName, '0.0.1', pkg) .status(HTTP_STATUS.CREATED) .body_ok(/published/); }); @@ -60,9 +62,10 @@ export default function (server, server2) { test('uploading new package version / srv1', () => {}); test('downloading newly created tarball / srv2', () => { - return server2.getTarball(pkgName, TARBALL) + return server2 + .getTarball(pkgName, TARBALL) .status(HTTP_STATUS.OK) - .then(function(body) { + .then(function (body) { expect(body).toEqual(readfile(binary)); }); }); diff --git a/packages/verdaccio/test/functional/search/simple.search.ts b/packages/verdaccio/test/functional/search/simple.search.ts index df1817d8b..98db389d9 100644 --- a/packages/verdaccio/test/functional/search/simple.search.ts +++ b/packages/verdaccio/test/functional/search/simple.search.ts @@ -1,63 +1,58 @@ -import {API_MESSAGE, HTTP_STATUS} from '@verdaccio/dev-commons'; +import { API_MESSAGE, HTTP_STATUS } from '@verdaccio/dev-commons'; import pkgExample from './search.json'; -export default function(server, server2, express) { - +export default function (server, server2, express) { describe('should test search a published package', () => { const PKG_NAME = 'testpkg-search'; - beforeAll(function() { - return server.putPackage(PKG_NAME, pkgExample) - .status(HTTP_STATUS.CREATED) - .body_ok(API_MESSAGE.PKG_CREATED); + beforeAll(function () { + return server.putPackage(PKG_NAME, pkgExample).status(HTTP_STATUS.CREATED).body_ok(API_MESSAGE.PKG_CREATED); }); describe('should test simple search', () => { const check = (medatada) => { medatada[PKG_NAME].time.modified = '2014-10-02T07:07:51.000Z'; - expect(medatada[PKG_NAME]).toEqual( - { - 'name': PKG_NAME, - 'description': '', - 'author': '', - 'license': 'ISC', - 'dist-tags': { - latest: '0.0.1' - }, - 'maintainers': [{ + expect(medatada[PKG_NAME]).toEqual({ + name: PKG_NAME, + description: '', + author: '', + license: 'ISC', + 'dist-tags': { + latest: '0.0.1', + }, + maintainers: [ + { name: 'alex', - email: 'user@domain.com' - }], - 'readmeFilename': '', - 'time': { - modified: '2014-10-02T07:07:51.000Z' + email: 'user@domain.com', }, - 'versions': { - "0.0.1": "latest" - }, - 'repository': { - type: 'git', url: ''} - }); + ], + readmeFilename: '', + time: { + modified: '2014-10-02T07:07:51.000Z', + }, + versions: { + '0.0.1': 'latest', + }, + repository: { + type: 'git', + url: '', + }, + }); }; - beforeAll(function() { + beforeAll(function () { express.get('/-/all', (req, res) => { res.send({}); }); }); test('server1 - search', () => { - return server.request({uri: '/-/all'}) - .status(HTTP_STATUS.OK) - .then(check); + return server.request({ uri: '/-/all' }).status(HTTP_STATUS.OK).then(check); }); test('server2 - search', () => { - return server2.request({uri: '/-/all'}) - .status(HTTP_STATUS.OK) - .then(check); + return server2.request({ uri: '/-/all' }).status(HTTP_STATUS.OK).then(check); }); - }); }); } diff --git a/packages/verdaccio/test/functional/tags/addtag.ts b/packages/verdaccio/test/functional/tags/addtag.ts index 1de80d882..c1f6c01a0 100644 --- a/packages/verdaccio/test/functional/tags/addtag.ts +++ b/packages/verdaccio/test/functional/tags/addtag.ts @@ -1,47 +1,51 @@ -import {API_ERROR, HTTP_STATUS, CHARACTER_ENCODING} from "@verdaccio/dev-commons"; +import { API_ERROR, HTTP_STATUS, CHARACTER_ENCODING } from '@verdaccio/dev-commons'; -import {readFile} from '../lib/test.utils'; +import { readFile } from '../lib/test.utils'; const readTags = () => readFile('../fixtures/publish.json5'); -export default function(server) { - +export default function (server) { describe('should test add tag', () => { - const PKG_NAME = 'testpkg-tag'; const PKG_VERSION = '0.0.1'; test('should fails on add tag to non existing package', () => { - return server.addTag(PKG_NAME, 'tagtagtag', PKG_VERSION) - .status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); + return server.addTag(PKG_NAME, 'tagtagtag', PKG_VERSION).status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); }); describe('should test add tag to a package', () => { - beforeAll(function() { - return server.putPackage(PKG_NAME, - JSON.parse(readTags().toString(CHARACTER_ENCODING.UTF8).replace(/__NAME__/g, PKG_NAME) - .replace(/__VERSION__/g, PKG_VERSION)) - ).status(HTTP_STATUS.CREATED); + beforeAll(function () { + return server + .putPackage( + PKG_NAME, + JSON.parse( + readTags() + .toString(CHARACTER_ENCODING.UTF8) + .replace(/__NAME__/g, PKG_NAME) + .replace(/__VERSION__/g, PKG_VERSION) + ) + ) + .status(HTTP_STATUS.CREATED); }); describe('should test valid formats tags', () => { test('should fails on add a tag that do not exist', () => { - return server.addTag(PKG_NAME, 'tagtagtag', '4.0.0-no-exist') - .status(HTTP_STATUS.NOT_FOUND) - .body_error(API_ERROR.VERSION_NOT_EXIST); + return server.addTag(PKG_NAME, 'tagtagtag', '4.0.0-no-exist').status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.VERSION_NOT_EXIST); }); test('should add tag succesfully minor version', () => { - return server.addTag(PKG_NAME, 'tagtagtag', PKG_VERSION) + return server + .addTag(PKG_NAME, 'tagtagtag', PKG_VERSION) .status(HTTP_STATUS.CREATED) .body_ok(/tagged/); }); }); describe('should test handle invalid tag and version names', () => { - const INVALID_TAG ='tag/tag/tag'; - const handleInvalidTag = function(tag, version) { - return server.addTag(PKG_NAME, tag, version) + const INVALID_TAG = 'tag/tag/tag'; + const handleInvalidTag = function (tag, version) { + return server + .addTag(PKG_NAME, tag, version) .status(HTTP_STATUS.FORBIDDEN) .body_error(/invalid tag/); }; diff --git a/packages/verdaccio/test/functional/tags/dist-tags-merge.ts b/packages/verdaccio/test/functional/tags/dist-tags-merge.ts index c57ca6cc3..e0ce7a7f0 100644 --- a/packages/verdaccio/test/functional/tags/dist-tags-merge.ts +++ b/packages/verdaccio/test/functional/tags/dist-tags-merge.ts @@ -1,28 +1,25 @@ -import {API_MESSAGE, HTTP_STATUS} from '@verdaccio/dev-commons'; -import {DIST_TAGS} from '@verdaccio/dev-commons'; +import { API_MESSAGE, HTTP_STATUS } from '@verdaccio/dev-commons'; +import { DIST_TAGS } from '@verdaccio/dev-commons'; -import {DOMAIN_SERVERS, PORT_SERVER_1, PORT_SERVER_2, PORT_SERVER_3} from '../config.functional'; -import {generateSha} from '../lib/test.utils'; +import { DOMAIN_SERVERS, PORT_SERVER_1, PORT_SERVER_2, PORT_SERVER_3 } from '../config.functional'; +import { generateSha } from '../lib/test.utils'; import pkgExample from './dist-tags-merge.json'; -export default function(server, server2, server3) { - +export default function (server, server2, server3) { describe('should test preserve tags when publishing something', () => { const PKG_NAME = 'testpkg-preserve'; const PKG_VERSION = '0.0.1'; - beforeAll(function() { - return server.putPackage(PKG_NAME, pkgExample) - .status(HTTP_STATUS.CREATED) - .body_ok(API_MESSAGE.PKG_CREATED); + beforeAll(function () { + return server.putPackage(PKG_NAME, pkgExample).status(HTTP_STATUS.CREATED).body_ok(API_MESSAGE.PKG_CREATED); }); describe('should check sha integrity', () => { - const matchTarBallSha = (server) => { - return server.getTarball(PKG_NAME, `${PKG_NAME}-${PKG_VERSION}.tgz`) + return server + .getTarball(PKG_NAME, `${PKG_NAME}-${PKG_VERSION}.tgz`) .status(HTTP_STATUS.OK) - .then(function(body) { + .then(function (body) { // not real sha due to utf8 conversion expect(generateSha(body)).toBe(pkgExample.versions[PKG_VERSION].dist.shasum); }); @@ -30,21 +27,21 @@ export default function(server, server2, server3) { test('server1 should match with sha key from published package', () => matchTarBallSha(server)); test('server2 should match with sha key from published package', () => matchTarBallSha(server2)); - }); describe('should match dist-tags', () => { const matchDisTags = (verdaccioServer, port) => { - return verdaccioServer.getPackage(PKG_NAME) + return verdaccioServer + .getPackage(PKG_NAME) .status(HTTP_STATUS.OK) - .then(function(body) { + .then(function (body) { expect(body.name).toBe(PKG_NAME); expect(body.time).toBeDefined(); expect(body.time[PKG_VERSION]).toBeDefined(); expect(body.time).toBeDefined(); expect(body.versions[PKG_VERSION].name).toBe(PKG_NAME); expect(body.versions[PKG_VERSION].dist.tarball).toBe(`http://${DOMAIN_SERVERS}:${port}/${PKG_NAME}/-/${PKG_NAME}-${PKG_VERSION}.tgz`); - expect(body[DIST_TAGS]).toEqual({foo: PKG_VERSION, latest: PKG_VERSION}); + expect(body[DIST_TAGS]).toEqual({ foo: PKG_VERSION, latest: PKG_VERSION }); }); }; diff --git a/packages/verdaccio/test/functional/tags/tags.ts b/packages/verdaccio/test/functional/tags/tags.ts index bcd165d99..738f9f6c8 100644 --- a/packages/verdaccio/test/functional/tags/tags.ts +++ b/packages/verdaccio/test/functional/tags/tags.ts @@ -1,31 +1,36 @@ import _ from 'lodash'; import { HTTP_STATUS } from '@verdaccio/dev-commons'; -import {readFile} from '../lib/test.utils'; +import { readFile } from '../lib/test.utils'; const readTags = () => readFile('../fixtures/tags.json'); -export default function(server, express) { - +export default function (server, express) { test('tags - testing for 404', () => { - return server.getPackage('testexp_tags') - // shouldn't exist yet - .status(HTTP_STATUS.NOT_FOUND) - .body_error(/no such package/); + return ( + server + .getPackage('testexp_tags') + // shouldn't exist yet + .status(HTTP_STATUS.NOT_FOUND) + .body_error(/no such package/) + ); }); describe('tags', () => { - beforeAll(function() { - express.get('/testexp_tags', function(req, res) { - let f = readTags().toString().replace(/__NAME__/g, 'testexp_tags'); + beforeAll(function () { + express.get('/testexp_tags', function (req, res) { + let f = readTags() + .toString() + .replace(/__NAME__/g, 'testexp_tags'); res.send(JSON.parse(f)); }); }); test('fetching package again', () => { - return server.getPackage('testexp_tags') + return server + .getPackage('testexp_tags') .status(200) - .then(function(body) { + .then(function (body) { expect(_.isObject(body.versions['1.1.0'])).toBe(true); // note: 5.4.3 is invalid tag, 0.1.3alpha is highest semver expect(body['dist-tags'].latest).toEqual('1.1.0'); @@ -35,11 +40,12 @@ export default function(server, express) { const versions = ['0.1.1alpha', '0.1.1-alpha', '0000.00001.001-alpha']; - versions.forEach(function(ver) { - test('fetching '+ver, () => { - return server.request({uri: '/testexp_tags/'+ver}) + versions.forEach(function (ver) { + test('fetching ' + ver, () => { + return server + .request({ uri: '/testexp_tags/' + ver }) .status(200) - .then(function(body) { + .then(function (body) { expect(body.version).toEqual('0.1.1alpha'); }); }); @@ -47,117 +53,146 @@ export default function(server, express) { }); describe('dist-tags methods', () => { - - beforeAll(function() { - - express.get('/testexp_tags2', function(req, res) { - let f = readTags().toString().replace(/__NAME__/g, 'testexp_tags2'); + beforeAll(function () { + express.get('/testexp_tags2', function (req, res) { + let f = readTags() + .toString() + .replace(/__NAME__/g, 'testexp_tags2'); res.send(JSON.parse(f)); }); - }); // populate cache - beforeAll(function() { + beforeAll(function () { return server.getPackage('testexp_tags2').status(200); }); test('fetching tags', () => { - return server.request({ - method: 'GET', - uri: '/-/package/testexp_tags2/dist-tags', - }).status(200).then(function(body) { - const expected = { - latest: "1.1.0" - }; + return server + .request({ + method: 'GET', + uri: '/-/package/testexp_tags2/dist-tags', + }) + .status(200) + .then(function (body) { + const expected = { + latest: '1.1.0', + }; - expect(body).toEqual(expected); - }); + expect(body).toEqual(expected); + }); }); test('merging tags', () => { - return server.request({ - method: 'POST', - uri: '/-/package/testexp_tags2/dist-tags', - json: { - foo: '0.1.2', - quux: '0.1.0', - }, - }).status(201).body_ok(/updated/).then(function() { - return server.request({ - method: 'GET', + return server + .request({ + method: 'POST', uri: '/-/package/testexp_tags2/dist-tags', - }).status(200).then(function(body) { - const expected = { - "latest": "1.1.0", - "foo": "0.1.2", - "quux": "0.1.0" - }; + json: { + foo: '0.1.2', + quux: '0.1.0', + }, + }) + .status(201) + .body_ok(/updated/) + .then(function () { + return server + .request({ + method: 'GET', + uri: '/-/package/testexp_tags2/dist-tags', + }) + .status(200) + .then(function (body) { + const expected = { + latest: '1.1.0', + foo: '0.1.2', + quux: '0.1.0', + }; - expect(body).toEqual(expected); + expect(body).toEqual(expected); + }); }); - }); }); test('should add a dist-tag called foo', () => { - return server.request({ - method: 'PUT', - uri: '/-/package/testexp_tags2/dist-tags/foo', - json: '0.1.3alpha', - }).status(201).body_ok(/tagged/).then(function() { - return server.request({ - method: 'GET', - uri: '/-/package/testexp_tags2/dist-tags', - }).status(200).then(function(body) { - const expected = { - foo: '0.1.3alpha', - quux: '0.1.0', - latest: '1.1.0' - }; + return server + .request({ + method: 'PUT', + uri: '/-/package/testexp_tags2/dist-tags/foo', + json: '0.1.3alpha', + }) + .status(201) + .body_ok(/tagged/) + .then(function () { + return server + .request({ + method: 'GET', + uri: '/-/package/testexp_tags2/dist-tags', + }) + .status(200) + .then(function (body) { + const expected = { + foo: '0.1.3alpha', + quux: '0.1.0', + latest: '1.1.0', + }; - expect(body).toEqual(expected); + expect(body).toEqual(expected); + }); }); - }); }); test('should remove a dis-tag called quux', () => { - return server.request({ - method: 'DELETE', - uri: '/-/package/testexp_tags2/dist-tags/latest', - }).status(201).body_ok(/removed/).then(function() { - return server.request({ - method: 'GET', - uri: '/-/package/testexp_tags2/dist-tags', - }).status(200).then(function(body) { - const expected = { - latest: '1.1.0', - "quux": "0.1.0", - foo: "0.1.3alpha" - }; + return server + .request({ + method: 'DELETE', + uri: '/-/package/testexp_tags2/dist-tags/latest', + }) + .status(201) + .body_ok(/removed/) + .then(function () { + return server + .request({ + method: 'GET', + uri: '/-/package/testexp_tags2/dist-tags', + }) + .status(200) + .then(function (body) { + const expected = { + latest: '1.1.0', + quux: '0.1.0', + foo: '0.1.3alpha', + }; - expect(body).toEqual(expected); + expect(body).toEqual(expected); + }); }); - }); }); test('should remove a dis-tag called foo', () => { - return server.request({ - method: 'DELETE', - uri: '/-/package/testexp_tags2/dist-tags/foo', - }).status(201).body_ok(/removed/).then(function() { - return server.request({ - method: 'GET', - uri: '/-/package/testexp_tags2/dist-tags', - }).status(200).then(function(body) { - const expected = { - latest: '1.1.0', - "quux": "0.1.0" - }; + return server + .request({ + method: 'DELETE', + uri: '/-/package/testexp_tags2/dist-tags/foo', + }) + .status(201) + .body_ok(/removed/) + .then(function () { + return server + .request({ + method: 'GET', + uri: '/-/package/testexp_tags2/dist-tags', + }) + .status(200) + .then(function (body) { + const expected = { + latest: '1.1.0', + quux: '0.1.0', + }; - expect(body).toEqual(expected); + expect(body).toEqual(expected); + }); }); - }); }); - }); } diff --git a/packages/verdaccio/test/functional/teardown.js b/packages/verdaccio/test/functional/teardown.js index e5392aeea..9c56fae71 100644 --- a/packages/verdaccio/test/functional/teardown.js +++ b/packages/verdaccio/test/functional/teardown.js @@ -1,4 +1,4 @@ -module.exports = async function() { +module.exports = async function () { // console.log(green('Teardown Verdaccio Functional')); // console.log(blue('Teardown:: all server were closed')); }; diff --git a/packages/verdaccio/test/functional/test-environment.js b/packages/verdaccio/test/functional/test-environment.js index 4f37edfd8..7a01efc0b 100644 --- a/packages/verdaccio/test/functional/test-environment.js +++ b/packages/verdaccio/test/functional/test-environment.js @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-var-requires */ require('@babel/register')({ - extensions: [".ts", ".js"] + extensions: ['.ts', '.js'], }); module.exports = require('./lib/environment'); diff --git a/packages/verdaccio/test/functional/uplinks/cache.ts b/packages/verdaccio/test/functional/uplinks/cache.ts index 094e95a09..19dd585ad 100644 --- a/packages/verdaccio/test/functional/uplinks/cache.ts +++ b/packages/verdaccio/test/functional/uplinks/cache.ts @@ -1,10 +1,10 @@ import fs from 'fs'; import path from 'path'; import crypto from 'crypto'; -import {HTTP_STATUS} from "@verdaccio/dev-commons"; +import { HTTP_STATUS } from '@verdaccio/dev-commons'; import { createTarballHash } from '@verdaccio/utils'; -import {TARBALL} from '../config.functional'; +import { TARBALL } from '../config.functional'; import { readFile } from '../lib/test.utils'; import requirePackage from '../fixtures/package'; @@ -24,25 +24,22 @@ function isCached(pkgName, tarballName) { } export default function (server, server2, server3) { - describe('storage tarball cache test', () => { - // more info #131 beforeAll(function () { return server.addPackage(PKG_GH131); }); beforeAll(function () { - return server.putTarball(PKG_GH131, TARBALL, getBinary()) - .status(HTTP_STATUS.CREATED) - .body_ok(/.*/); + return server.putTarball(PKG_GH131, TARBALL, getBinary()).status(HTTP_STATUS.CREATED).body_ok(/.*/); }); beforeAll(function () { const pkg = requirePackage(PKG_GH131); pkg.dist.shasum = crypto.createHash('sha1').update(getBinary()).digest('hex'); - return server.putVersion(PKG_GH131, '0.0.1', pkg) + return server + .putVersion(PKG_GH131, '0.0.1', pkg) .status(HTTP_STATUS.CREATED) .body_ok(/published/); }); @@ -52,8 +49,7 @@ export default function (server, server2, server3) { }); beforeAll(function () { - return server3.getTarball(PKG_GH131, TARBALL) - .status(HTTP_STATUS.OK); + return server3.getTarball(PKG_GH131, TARBALL).status(HTTP_STATUS.OK); }); test.skip('should be caching packages from uplink server1', () => { @@ -65,33 +61,29 @@ export default function (server, server2, server3) { }); beforeAll(function () { - return server2.putTarball(PKG_GH1312, TARBALL, getBinary()) - .status(HTTP_STATUS.CREATED) - .body_ok(/.*/); + return server2.putTarball(PKG_GH1312, TARBALL, getBinary()).status(HTTP_STATUS.CREATED).body_ok(/.*/); }); beforeAll(function () { const pkg = requirePackage(PKG_GH1312); pkg.dist.shasum = createTarballHash().update(getBinary()).digest('hex'); - return server2.putVersion(PKG_GH1312, '0.0.1', pkg) + return server2 + .putVersion(PKG_GH1312, '0.0.1', pkg) .status(HTTP_STATUS.CREATED) .body_ok(/published/); }); beforeAll(function () { - return server3.getPackage(PKG_GH1312) - .status(HTTP_STATUS.OK); + return server3.getPackage(PKG_GH1312).status(HTTP_STATUS.OK); }); beforeAll(function () { - return server3.getTarball(PKG_GH1312, TARBALL) - .status(HTTP_STATUS.OK); + return server3.getTarball(PKG_GH1312, TARBALL).status(HTTP_STATUS.OK); }); test('must not be caching packages from uplink server2', () => { expect(isCached(PKG_GH1312, TARBALL)).toEqual(false); }); - }); } diff --git a/packages/verdaccio/test/functional/uplinks/timeout.ts b/packages/verdaccio/test/functional/uplinks/timeout.ts index b5f0efca3..26b521def 100644 --- a/packages/verdaccio/test/functional/uplinks/timeout.ts +++ b/packages/verdaccio/test/functional/uplinks/timeout.ts @@ -1,12 +1,10 @@ -import {HTTP_STATUS} from "@verdaccio/dev-commons"; +import { HTTP_STATUS } from '@verdaccio/dev-commons'; const PKG_SINGLE_UPLINK = 'test-uplink-timeout-single'; const PKG_MULTIPLE_UPLINKS = 'test-uplink-timeout-multiple'; export default function (server, server2, server3) { - describe('uplink connection timeouts', () => { - // more info: https://github.com/verdaccio/verdaccio/pull/1331 jest.setTimeout(20000); @@ -22,10 +20,8 @@ export default function (server, server2, server3) { }); test('200 response even though one uplink timeout', () => { - return server.getPackage(PKG_MULTIPLE_UPLINKS).status(HTTP_STATUS.OK) + return server.getPackage(PKG_MULTIPLE_UPLINKS).status(HTTP_STATUS.OK); }); }); - }); - } diff --git a/packages/verdaccio/test/jest.config.functional.js b/packages/verdaccio/test/jest.config.functional.js index cf896b04a..9c42538f4 100644 --- a/packages/verdaccio/test/jest.config.functional.js +++ b/packages/verdaccio/test/jest.config.functional.js @@ -27,5 +27,5 @@ module.exports = { '/../build', '/../.vscode/', ], - collectCoverage: false + collectCoverage: false, }; diff --git a/packages/verdaccio/test/lib/helper/verdaccio-test b/packages/verdaccio/test/lib/helper/verdaccio-test index d2c06b6df..fa17a4792 100755 --- a/packages/verdaccio/test/lib/helper/verdaccio-test +++ b/packages/verdaccio/test/lib/helper/verdaccio-test @@ -1,5 +1,5 @@ #!/usr/bin/env node require('@babel/register')({ - extensions: [".ts", ".js"] + extensions: ['.ts', '.js'], }); require('@verdaccio/cli'); diff --git a/packages/verdaccio/test/types-test/plugins/middleware/example.middleware.plugin.ts b/packages/verdaccio/test/types-test/plugins/middleware/example.middleware.plugin.ts index 8195903f8..c15a2fbf5 100644 --- a/packages/verdaccio/test/types-test/plugins/middleware/example.middleware.plugin.ts +++ b/packages/verdaccio/test/types-test/plugins/middleware/example.middleware.plugin.ts @@ -4,43 +4,37 @@ import Config from '../../../../packages/config/src/config'; import { generatePackageTemplate } from '@verdaccio/store'; -import {readFile} from '../../../functional/lib/test.utils'; +import { readFile } from '../../../functional/lib/test.utils'; import { Package } from '@verdaccio/types'; const readMetadata = (fileName: string): Package => JSON.parse(readFile(`../../unit/partials/${fileName}`).toString()) as Package; -import { - Config as AppConfig, - IPluginMiddleware, - IStorageManager, - RemoteUser, - IBasicAuth, -} from '@verdaccio/types'; +import { Config as AppConfig, IPluginMiddleware, IStorageManager, RemoteUser, IBasicAuth } from '@verdaccio/types'; import { IUploadTarball, IReadTarball } from '@verdaccio/streams'; -import { generateVersion } from "../../../unit/__helper/utils"; +import { generateVersion } from '../../../unit/__helper/utils'; export default class ExampleMiddlewarePlugin implements IPluginMiddleware<{}> { register_middlewares(app: any, auth: IBasicAuth<{}>, storage: IStorageManager<{}>): void { const remoteUser: RemoteUser = { groups: [], real_groups: [], - name: 'test' + name: 'test', }; auth.authenticate('user', 'password', () => {}); - auth.allow_access({packageName: 'packageName'}, remoteUser, () => {}); + auth.allow_access({ packageName: 'packageName' }, remoteUser, () => {}); auth.add_user('user', 'password', () => {}); auth.aesEncrypt(Buffer.from('pass')); // storage storage.addPackage('name', generatePackageTemplate('test'), () => {}); storage.addVersion('name', 'version', generateVersion('name', '1.0.0'), 'tag', () => {}); - storage.mergeTags('name', {'latest': '1.0.0'}, () => {}); + storage.mergeTags('name', { latest: '1.0.0' }, () => {}); storage.changePackage('name', readMetadata('metadata'), 'revision', () => {}); storage.removePackage('name', () => {}); - storage.mergeTags('name', {'latest': '1.0.0'}, () => {}); + storage.mergeTags('name', { latest: '1.0.0' }, () => {}); storage.removeTarball('name', 'filename', 'revision', () => {}); const config1: AppConfig = new Config({ storage: './storage', - self_path: '/home/sotrage' + self_path: '/home/sotrage', }); const add: IUploadTarball = storage.addTarball('name', 'filename'); storage.getTarball('name', 'filename'); @@ -48,4 +42,3 @@ export default class ExampleMiddlewarePlugin implements IPluginMiddleware<{}> { const search: IReadTarball = storage.search('test', {}); } } - diff --git a/packages/verdaccio/test/types-test/plugins/storage/example.storage.plugin.ts b/packages/verdaccio/test/types-test/plugins/storage/example.storage.plugin.ts index 03848c0ff..763c0c506 100644 --- a/packages/verdaccio/test/types-test/plugins/storage/example.storage.plugin.ts +++ b/packages/verdaccio/test/types-test/plugins/storage/example.storage.plugin.ts @@ -1,24 +1,12 @@ // this file is not aim to be tested, just to check typescript definitions -import { - Callback, - Config as AppConfig, - Logger, - Package, - Token, - TokenFilter, - IUploadTarball, IReadTarball -} from '@verdaccio/types'; +import { Callback, Config as AppConfig, Logger, Package, Token, TokenFilter, IUploadTarball, IReadTarball } from '@verdaccio/types'; -import { - IPluginStorage, - IPackageStorageManager, - IPackageStorage -} from '@verdaccio/types'; -import { UploadTarball, ReadTarball} from '@verdaccio/streams'; +import { IPluginStorage, IPackageStorageManager, IPackageStorage } from '@verdaccio/types'; +import { UploadTarball, ReadTarball } from '@verdaccio/streams'; import Config from '../../../../packages/config/src/config'; -import {logger} from '../../../../packages/logger/src/logger'; +import { logger } from '../../../../packages/logger/src/logger'; import { generatePackageTemplate } from '@verdaccio/store'; class PackageStorage implements IPackageStorageManager { @@ -30,10 +18,7 @@ class PackageStorage implements IPackageStorageManager { this.logger = logger; } - updatePackage(name: string, updateHandler: Callback, - onWrite: Callback, - transformPackage: Function, - onEnd: Callback) { + updatePackage(name: string, updateHandler: Callback, onWrite: Callback, transformPackage: Function, onEnd: Callback) { onEnd(); } @@ -58,7 +43,7 @@ class PackageStorage implements IPackageStorageManager { } writeTarball(name): IUploadTarball { - this.logger.debug({name}, 'some name @name'); + this.logger.debug({ name }, 'some name @name'); const uploadStream = new UploadTarball({}); uploadStream.on('close', () => {}); if (uploadStream.abort) { @@ -73,7 +58,7 @@ class PackageStorage implements IPackageStorageManager { } readTarball(name): IReadTarball { - this.logger.debug({name}, 'some name @name'); + this.logger.debug({ name }, 'some name @name'); const readTarballStream: IReadTarball = new ReadTarball({}); if (readTarballStream.abort) { @@ -94,9 +79,9 @@ class ExampleStoragePlugin implements IPluginStorage<{}> { } saveToken(token: Token): Promise { - return Promise.resolve(token) + return Promise.resolve(token); } - deleteToken(user: string, tokenKey: string): Promise{ + deleteToken(user: string, tokenKey: string): Promise { return Promise.resolve([user, tokenKey]); } @@ -106,8 +91,8 @@ class ExampleStoragePlugin implements IPluginStorage<{}> { key: '12312', token: '12321', // pragma: allowlist secret readonly: false, - created: '123232' - } + created: '123232', + }; return Promise.resolve([token, token]); } @@ -116,7 +101,8 @@ class ExampleStoragePlugin implements IPluginStorage<{}> { return Promise.resolve(); } - setSecret(secret: string): Promise { // pragma: allowlist secret + setSecret(secret: string): Promise { + // pragma: allowlist secret return Promise.resolve(secret); // pragma: allowlist secret } @@ -145,17 +131,20 @@ export default ExampleStoragePlugin; const config1: AppConfig = new Config({ storage: './storage', - self_path: '/home/sotrage' + self_path: '/home/sotrage', }); - const storage = new ExampleStoragePlugin(config1, logger.child()); storage.add('test', () => {}); storage.remove('test', () => {}); storage.getSecret().then(() => {}); storage.setSecret('newSecret').then(() => {}); -storage.search(() => {}, () => {}, 'validateName'); +storage.search( + () => {}, + () => {}, + 'validateName' +); storage.get(() => {}); const storageManager: IPackageStorage = storage.getPackageStorage('test'); @@ -164,7 +153,13 @@ if (storageManager) { storageManager.createPackage('test', generatePackageTemplate('test'), () => {}); storageManager.savePackage('fileName', generatePackageTemplate('test'), () => {}); // @ts-ignore - storageManager.updatePackage('pkgFileName', () => {}, () => {}, () => {}, () => {}); + storageManager.updatePackage( + 'pkgFileName', + () => {}, + () => {}, + () => {}, + () => {} + ); storageManager.deletePackage('test', () => {}); storageManager.removePackage(() => {}); storageManager.readPackage('test', () => {}); diff --git a/packages/verdaccio/test/unit/__helper/__template/api.__test.ts b/packages/verdaccio/test/unit/__helper/__template/api.__test.ts index 0159314ae..fe842fccd 100644 --- a/packages/verdaccio/test/unit/__helper/__template/api.__test.ts +++ b/packages/verdaccio/test/unit/__helper/__template/api.__test.ts @@ -12,12 +12,12 @@ import path from 'path'; import rimraf from 'rimraf'; import endPointAPI from '@verdaccio/server'; -import {mockServer} from '../../__helper/mock'; -import {DOMAIN_SERVERS} from '../../../functional/config.functional'; -import {parseConfigFile} from '@verdaccio/utils/src/utils'; -import {parseConfigurationFile} from '../../__helper'; -import {addUser} from '../../__helper/api'; -import {setup} from '@verdaccio/logger'; +import { mockServer } from '../../__helper/mock'; +import { DOMAIN_SERVERS } from '../../../functional/config.functional'; +import { parseConfigFile } from '@verdaccio/utils/src/utils'; +import { parseConfigurationFile } from '../../__helper'; +import { addUser } from '../../__helper/api'; +import { setup } from '@verdaccio/logger'; // we must start logging without output setup([]); @@ -33,7 +33,7 @@ describe('endpoint example unit test', () => { let app; let mockRegistry; - beforeAll(function(done) { + beforeAll(function (done) { // 1. We create a route for a custom storage folder for this test const store = path.join(__dirname, '../../partials/store/test-template-storage'); // 2. The port must be unique (at this point this is not automated, need to be checked manually) @@ -47,17 +47,17 @@ describe('endpoint example unit test', () => { storage: store, uplinks: { npmjs: { - url: `http://${DOMAIN_SERVERS}:${mockServerPort}` - } + url: `http://${DOMAIN_SERVERS}:${mockServerPort}`, + }, }, // 6. The self_path is important be the same as the store self_path: store, // 7. Define the location of the .htpasswd file, this is relative to self_path. auth: { htpasswd: { - file: './test-jwt-storage/.htpasswd' - } - } + file: './test-jwt-storage/.htpasswd', + }, + }, }); // 8. Use the helper `endPointAPI` to mock the API @@ -68,7 +68,7 @@ describe('endpoint example unit test', () => { }); }); - afterAll(function(done) { + afterAll(function (done) { // 10. Do not forget to stop the API, or it will run forever. mockRegistry[0].stop(); done(); diff --git a/packages/verdaccio/test/unit/__helper/api.ts b/packages/verdaccio/test/unit/__helper/api.ts index 6ebd2855c..701a3b9f9 100644 --- a/packages/verdaccio/test/unit/__helper/api.ts +++ b/packages/verdaccio/test/unit/__helper/api.ts @@ -1,12 +1,12 @@ import _ from 'lodash'; import request from 'supertest'; -import {HEADER_TYPE, HEADERS, HTTP_STATUS, TOKEN_BEARER} from '@verdaccio/dev-commons'; -import {buildToken, encodeScopedUri} from '@verdaccio/utils'; -import {generateRandomHexString} from "@verdaccio/utils"; +import { HEADER_TYPE, HEADERS, HTTP_STATUS, TOKEN_BEARER } from '@verdaccio/dev-commons'; +import { buildToken, encodeScopedUri } from '@verdaccio/utils'; +import { generateRandomHexString } from '@verdaccio/utils'; import { Package } from '@verdaccio/types'; -import {getTaggedVersionFromPackage} from "./expects"; +import { getTaggedVersionFromPackage } from './expects'; // API Helpers @@ -16,56 +16,43 @@ import {getTaggedVersionFromPackage} from "./expects"; // - Encourage using constants or create new ones if it's needed // - // @ts-ignore or any is fine if there is no other way -export function putPackage( - request: any, - pkgName: string, - publishMetadata: Package, - token?: string): Promise { +export function putPackage(request: any, pkgName: string, publishMetadata: Package, token?: string): Promise { return new Promise((resolve) => { - let put = request.put(pkgName) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) - .send(JSON.stringify(publishMetadata)); + let put = request.put(pkgName).set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON).send(JSON.stringify(publishMetadata)); - if (_.isEmpty(token) === false ) { - expect(token).toBeDefined(); - put.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token as string)) + if (_.isEmpty(token) === false) { + expect(token).toBeDefined(); + put.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token as string)); } - put.set('accept', 'gzip') - .set('accept-encoding', HEADERS.JSON) - .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { - resolve([err, res]); - }); - }); -} - -export function deletePackage( - request: any, - pkgName: string, - token?: string -): Promise { - return new Promise((resolve) => { - let del = request.put(`/${encodeScopedUri(pkgName)}/-rev/${generateRandomHexString(8)}`) - .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); - - if (_.isNil(token) === false ) { - del.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token as string)) - } - - del.set('accept-encoding', HEADERS.JSON) + put + .set('accept', 'gzip') + .set('accept-encoding', HEADERS.JSON) .expect(HTTP_STATUS.CREATED) - .end(function(err, res) { + .end(function (err, res) { resolve([err, res]); }); }); } -export function getPackage( - request: any, - token: string, - pkgName: string, - statusCode: number = HTTP_STATUS.OK): Promise { +export function deletePackage(request: any, pkgName: string, token?: string): Promise { + return new Promise((resolve) => { + let del = request.put(`/${encodeScopedUri(pkgName)}/-rev/${generateRandomHexString(8)}`).set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); + + if (_.isNil(token) === false) { + del.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token as string)); + } + + del + .set('accept-encoding', HEADERS.JSON) + .expect(HTTP_STATUS.CREATED) + .end(function (err, res) { + resolve([err, res]); + }); + }); +} + +export function getPackage(request: any, token: string, pkgName: string, statusCode: number = HTTP_STATUS.OK): Promise { return new Promise((resolve) => { let getRequest = request.get(`/${pkgName}`); @@ -77,39 +64,36 @@ export function getPackage( getRequest .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(statusCode) - .end(function(err, res) { + .end(function (err, res) { resolve([err, res]); }); }); } -export function loginUserToken(request: any, - user: string, - credentials: any, - token: string, - statusCode: number = HTTP_STATUS.CREATED): Promise { +export function loginUserToken(request: any, user: string, credentials: any, token: string, statusCode: number = HTTP_STATUS.CREATED): Promise { // $FlowFixMe return new Promise((resolve) => { - request.put(`/-/user/org.couchdb.user:${user}`) + request + .put(`/-/user/org.couchdb.user:${user}`) .send(credentials) .set('authorization', buildToken(TOKEN_BEARER, token)) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(statusCode) - .end(function(err, res) { + .end(function (err, res) { return resolve([err, res]); }); }); } -export function addUser(request: any, user: string, credentials: any, - statusCode: number = HTTP_STATUS.CREATED): Promise { +export function addUser(request: any, user: string, credentials: any, statusCode: number = HTTP_STATUS.CREATED): Promise { // $FlowFixMe return new Promise((resolve) => { - request.put(`/-/user/org.couchdb.user:${user}`) + request + .put(`/-/user/org.couchdb.user:${user}`) .send(credentials) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(statusCode) - .end(function(err, res) { + .end(function (err, res) { return resolve([err, res]); }); }); @@ -120,7 +104,7 @@ export async function getNewToken(request: any, credentials: any): Promise { const [err, res] = await addUser(request, credentials.name, credentials); expect(err).toBeNull(); - const {token, ok} = res.body; + const { token, ok } = res.body; expect(ok).toBeDefined(); expect(token).toBeDefined(); expect(typeof token).toBe('string'); @@ -128,28 +112,30 @@ export async function getNewToken(request: any, credentials: any): Promise { +export function getProfile(request: any, token: string, statusCode: number = HTTP_STATUS.OK): Promise { // $FlowFixMe return new Promise((resolve) => { - request.get(`/-/npm/v1/user`) + request + .get(`/-/npm/v1/user`) .set('authorization', buildToken(TOKEN_BEARER, token)) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(statusCode) - .end(function(err, res) { + .end(function (err, res) { return resolve([err, res]); }); }); } -export function postProfile(request: any, body: any, token: string, statusCode: number = HTTP_STATUS.OK): Promise { +export function postProfile(request: any, body: any, token: string, statusCode: number = HTTP_STATUS.OK): Promise { // $FlowFixMe return new Promise((resolve) => { - request.post(`/-/npm/v1/user`) + request + .post(`/-/npm/v1/user`) .send(body) .set(HEADERS.AUTHORIZATION, `Bearer ${token}`) .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) .expect(statusCode) - .end(function(err, res) { + .end(function (err, res) { return resolve([err, res]); }); }); @@ -157,7 +143,7 @@ export function postProfile(request: any, body: any, token: string, statusCode: export async function fetchPackageByVersionAndTag(app, encodedPkgName, pkgName, version, tag = 'latest') { // we retrieve the package to verify - const [err, resp]= await getPackage(request(app), '', encodedPkgName); + const [err, resp] = await getPackage(request(app), '', encodedPkgName); expect(err).toBeNull(); @@ -166,13 +152,13 @@ export async function fetchPackageByVersionAndTag(app, encodedPkgName, pkgName, } export async function isExistPackage(app, packageName) { - const [err]= await getPackage(request(app), '', encodeScopedUri(packageName), HTTP_STATUS.OK); + const [err] = await getPackage(request(app), '', encodeScopedUri(packageName), HTTP_STATUS.OK); return _.isNull(err); } export async function verifyPackageVersionDoesExist(app, packageName, version, token?: string) { - const [, res]= await getPackage(request(app), token as string, encodeScopedUri(packageName), HTTP_STATUS.OK); + const [, res] = await getPackage(request(app), token as string, encodeScopedUri(packageName), HTTP_STATUS.OK); const { versions } = res.body; const versionsKeys = Object.keys(versions); diff --git a/packages/verdaccio/test/unit/__helper/expects.ts b/packages/verdaccio/test/unit/__helper/expects.ts index 7dfdb579f..676f62ca9 100644 --- a/packages/verdaccio/test/unit/__helper/expects.ts +++ b/packages/verdaccio/test/unit/__helper/expects.ts @@ -1,20 +1,19 @@ -import {DIST_TAGS, LATEST} from "@verdaccio/dev-commons"; - +import { DIST_TAGS, LATEST } from '@verdaccio/dev-commons'; /** * Verify whether the package tag match with the desired version. */ export function getTaggedVersionFromPackage(pkg, pkgName, tag: string = LATEST, version: string) { - // extract the tagged version - const taggedVersion = pkg[DIST_TAGS][tag]; - expect(taggedVersion).toBeDefined(); - expect(taggedVersion).toEqual(version); + // extract the tagged version + const taggedVersion = pkg[DIST_TAGS][tag]; + expect(taggedVersion).toBeDefined(); + expect(taggedVersion).toEqual(version); - // the version must exist - const latestPkg = pkg.versions[taggedVersion]; - expect(latestPkg).toBeDefined(); - // the name must match - expect(latestPkg.name).toEqual(pkgName); + // the version must exist + const latestPkg = pkg.versions[taggedVersion]; + expect(latestPkg).toBeDefined(); + // the name must match + expect(latestPkg.name).toEqual(pkgName); - return latestPkg; + return latestPkg; } diff --git a/packages/verdaccio/test/unit/__helper/utils.ts b/packages/verdaccio/test/unit/__helper/utils.ts index 919138af1..f8d4b17b0 100644 --- a/packages/verdaccio/test/unit/__helper/utils.ts +++ b/packages/verdaccio/test/unit/__helper/utils.ts @@ -1,44 +1,45 @@ -import { Package } from "@verdaccio/types"; +import { Package } from '@verdaccio/types'; export function generateAttachment() { - return { - "content_type": "application\/octet-stream", - "data": "H4sIAAAAAAAAE+2W32vbMBDH85y\/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo\/\/79KPeQsnIw5KUDX\/9IOvurLuz\/DHSjK\/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1aW8eML+Vv10m9oF\/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0ScCdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI\/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yoEHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS\/pLQe+D+FIv\/agIWI6GX66kFuIhT+1gDjrp\/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0\/jWiAK8OcMjt8MW3OlfQppcuhhQ6k+2OgkK2Q8DssFPi\/IHpU9fz3\/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6\/f88f\/Pu47zomiPk2Lv\/dOv8h+P\/34\/D\/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=", - "length": 512 - } + return { + content_type: 'application/octet-stream', + data: + 'H4sIAAAAAAAAE+2W32vbMBDH85y/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo//79KPeQsnIw5KUDX/9IOvurLuz/DHSjK/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1aW8eML+Vv10m9oF/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0ScCdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yoEHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS/pLQe+D+FIv/agIWI6GX66kFuIhT+1gDjrp/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0/jWiAK8OcMjt8MW3OlfQppcuhhQ6k+2OgkK2Q8DssFPi/IHpU9fz3/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6/f88f/Pu47zomiPk2Lv/dOv8h+P/34/D/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=', + length: 512, + }; } export function generateVersion(pkgName, version) { - return { - "name": pkgName, - "version": version, - "description": "some foo dependency", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": { - "name": "User NPM", - "email": "user@domain.com" - }, - "license": "ISC", - "dependencies": { - "verdaccio": "^4.0.0" - }, - "readme": "# test", - "readmeFilename": "README.md", - "_id": `${pkgName}@${version}`, - "_npmVersion": "5.5.1", - "_npmUser": { - 'name': 'foo', - }, - "dist": { - "integrity": "sha512-6gHiERpiDgtb3hjqpQH5\/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==", - "shasum": "2c03764f651a9f016ca0b7620421457b619151b9", // pragma: allowlist secret - "tarball": `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz` - } - } + return { + name: pkgName, + version: version, + description: 'some foo dependency', + main: 'index.js', + scripts: { + test: 'echo "Error: no test specified" && exit 1', + }, + keywords: [], + author: { + name: 'User NPM', + email: 'user@domain.com', + }, + license: 'ISC', + dependencies: { + verdaccio: '^4.0.0', + }, + readme: '# test', + readmeFilename: 'README.md', + _id: `${pkgName}@${version}`, + _npmVersion: '5.5.1', + _npmUser: { + name: 'foo', + }, + dist: { + integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + shasum: '2c03764f651a9f016ca0b7620421457b619151b9', // pragma: allowlist secret + tarball: `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz`, + }, + }; } /** @@ -47,27 +48,26 @@ export function generateVersion(pkgName, version) { * if you intent to to generate a complete metadata include multiple versions. */ export function generatePackageBody(pkgName: string, _versions: string[] = ['1.0.0']): Package { - const latest: string = _versions[_versions.length - 1]; - const versions = _versions.reduce((cat, version) => { - cat[version] = generateVersion(pkgName, version); - return cat; - }, {}); + const latest: string = _versions[_versions.length - 1]; + const versions = _versions.reduce((cat, version) => { + cat[version] = generateVersion(pkgName, version); + return cat; + }, {}); - const attachtment = _versions.reduce((cat, version) => { - cat[`${pkgName}-${version}.tgz`] = generateAttachment(); - return cat; - }, {}); + const attachtment = _versions.reduce((cat, version) => { + cat[`${pkgName}-${version}.tgz`] = generateAttachment(); + return cat; + }, {}); - // @ts-ignore - return { - "_id": pkgName, - "name": pkgName, - "readme": "# test", - "dist-tags": { - "latest": latest - }, - "versions": versions, - "_attachments": attachtment - } + // @ts-ignore + return { + _id: pkgName, + name: pkgName, + readme: '# test', + 'dist-tags': { + latest: latest, + }, + versions: versions, + _attachments: attachtment, + }; } - diff --git a/packages/web/src/endpoint/package.ts b/packages/web/src/endpoint/package.ts index 1f5ff2a14..0e5f894dd 100644 --- a/packages/web/src/endpoint/package.ts +++ b/packages/web/src/endpoint/package.ts @@ -22,34 +22,28 @@ const getOrder = (order = 'asc') => { return order === 'asc'; }; -export type PackcageExt = Package & { author: any, dist?: {tarball: string} }; +export type PackcageExt = Package & { author: any; dist?: { tarball: string } }; function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth, config: Config): void { const can = allow(auth); const checkAllow = (name, remoteUser): Promise => - new Promise( - (resolve, reject): void => { - try { - auth.allow_access( - { packageName: name }, - remoteUser, - (err, allowed): void => { - if (err) { - resolve(false); - } - resolve(allowed); - } - ); - } catch (err) { - reject(err); - } + new Promise((resolve, reject): void => { + try { + auth.allow_access({ packageName: name }, remoteUser, (err, allowed): void => { + if (err) { + resolve(false); + } + resolve(allowed); + }); + } catch (err) { + reject(err); } - ); + }); // Get list of all visible package - route.get('/packages', function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { - storage.getLocalDatabase(async function(err, packages): Promise { + route.get('/packages', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + storage.getLocalDatabase(async function (err, packages): Promise { if (err) { throw err; } @@ -88,14 +82,14 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth, }); // Get package readme - route.get('/package/readme/(@:scope/)?:package/:version?', can('access'), function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + route.get('/package/readme/(@:scope/)?:package/:version?', can('access'), function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { const packageName = req.params.scope ? addScope(req.params.scope, req.params.package) : req.params.package; storage.getPackage({ name: packageName, uplinksLook: true, req, - callback: function(err, info): void { + callback: function (err, info): void { if (err) { return next(err); } @@ -106,7 +100,7 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth, }); }); - route.get('/sidebar/(@:scope/)?:package', can('access'), function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + route.get('/sidebar/(@:scope/)?:package', can('access'), function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { const packageName: string = req.params.scope ? addScope(req.params.scope, req.params.package) : req.params.package; storage.getPackage({ @@ -114,37 +108,31 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth, uplinksLook: true, keepUpLinkData: true, req, - callback: function(err: Error, info: $SidebarPackage): void { + callback: function (err: Error, info: $SidebarPackage): void { if (_.isNil(err)) { - const {v} = req.query; + const { v } = req.query; let sideBarInfo: any = _.clone(info); sideBarInfo.versions = convertDistRemoteToLocalTarballUrls(info, req, config.url_prefix).versions; if (isVersionValid(info, v)) { // @ts-ignore sideBarInfo.latest = sideBarInfo.versions[v]; sideBarInfo.latest.author = formatAuthor(sideBarInfo.latest.author); - } else { - sideBarInfo.latest = sideBarInfo.versions[info[DIST_TAGS].latest]; - if (sideBarInfo?.latest) { - sideBarInfo.latest.author = formatAuthor(sideBarInfo.latest.author); - } else { - res.status(HTTP_STATUS.NOT_FOUND); - res.end(); - return; - } - } - sideBarInfo = deleteProperties(['readme', '_attachments', '_rev', 'name'], sideBarInfo); - if (config.web) { - sideBarInfo = addGravatarSupport(sideBarInfo, config.web.gravatar); - } else { - sideBarInfo = addGravatarSupport(sideBarInfo); - } - next(sideBarInfo); } else { - res.status(HTTP_STATUS.NOT_FOUND); - res.end(); + sideBarInfo.latest = sideBarInfo.versions[info[DIST_TAGS].latest]; + sideBarInfo.latest.author = formatAuthor(sideBarInfo.latest.author); } + sideBarInfo = deleteProperties(['readme', '_attachments', '_rev', 'name'], sideBarInfo); + if (config.web) { + sideBarInfo = addGravatarSupport(sideBarInfo, config.web.gravatar); + } else { + sideBarInfo = addGravatarSupport(sideBarInfo); + } + next(sideBarInfo); + } else { + res.status(HTTP_STATUS.NOT_FOUND); + res.end(); } + }, }); }); } diff --git a/packages/web/src/endpoint/search.ts b/packages/web/src/endpoint/search.ts index c6ecb874d..51fe566d9 100644 --- a/packages/web/src/endpoint/search.ts +++ b/packages/web/src/endpoint/search.ts @@ -1,8 +1,3 @@ -/** - * @prettier - * @flow - */ - import { SearchInstance } from '@verdaccio/store'; import { DIST_TAGS } from '@verdaccio/dev-commons'; import { Router } from 'express'; @@ -11,18 +6,18 @@ import { Package } from '@verdaccio/types'; function addSearchWebApi(route: Router, storage: IStorageHandler, auth: IAuth): void { // Search package - route.get('/search/:anything', function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + route.get('/search/:anything', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { const results: any = SearchInstance.query(req.params.anything); // FUTURE: figure out here the correct type const packages: any[] = []; - const getPackageInfo = function(i): void { + const getPackageInfo = function (i): void { storage.getPackage({ name: results[i].ref, uplinksLook: false, callback: (err, entry: Package): void => { if (!err && entry) { - auth.allow_access({ packageName: entry.name }, req.remote_user, function(err, allowed): void { + auth.allow_access({ packageName: entry.name }, req.remote_user, function (err, allowed): void { if (err || !allowed) { return; } diff --git a/packages/web/src/endpoint/user.ts b/packages/web/src/endpoint/user.ts index 3fe02c91b..fcaf301ce 100644 --- a/packages/web/src/endpoint/user.ts +++ b/packages/web/src/endpoint/user.ts @@ -9,7 +9,7 @@ import { validatePassword, ErrorCode } from '@verdaccio/utils'; import { getSecurity } from '@verdaccio/auth'; function addUserAuthApi(route: Router, auth: IAuth, config: Config): void { - route.post('/login', function(req: Request, res: Response, next: $NextFunctionVer): void { + route.post('/login', function (req: Request, res: Response, next: $NextFunctionVer): void { const { username, password } = req.body; auth.authenticate( @@ -32,7 +32,7 @@ function addUserAuthApi(route: Router, auth: IAuth, config: Config): void { ); }); - route.put('/reset_password', function(req: Request, res: Response, next: $NextFunctionVer): void { + route.put('/reset_password', function (req: Request, res: Response, next: $NextFunctionVer): void { if (_.isNil(req.remote_user.name)) { res.status(HTTP_STATUS.UNAUTHORIZED); return next({ diff --git a/packages/web/src/render-web.ts b/packages/web/src/render-web.ts index e3e6aa672..b796729fb 100644 --- a/packages/web/src/render-web.ts +++ b/packages/web/src/render-web.ts @@ -21,7 +21,7 @@ export function loadTheme(config) { config, config.theme, {}, - function(plugin) { + function (plugin) { return _.isString(plugin); }, 'verdaccio-theme' @@ -39,7 +39,7 @@ export function validatePrimaryColor(primaryColor) { return primaryColor; } -const sendFileCallback = next => err => { +const sendFileCallback = (next) => (err) => { if (!err) { return; } @@ -69,13 +69,13 @@ export function renderWebMiddleware(config, auth, storage): any { // Note: `path.join` will break on Windows, because it transforms `/` to `\` // Use POSIX version `path.posix.join` instead. logoURI = path.posix.join('/-/static/', path.basename(logoURI)); - router.get(logoURI, function(req, res, next) { + router.get(logoURI, function (req, res, next) { res.sendFile(path.resolve(config.web.logo), sendFileCallback(next)); }); } // Static - router.get('/-/static/*', function(req, res, next) { + router.get('/-/static/*', function (req, res, next) { const filename = req.params[0]; const file = `${themePath}/${filename}`; res.sendFile(file, sendFileCallback(next)); @@ -120,11 +120,11 @@ export function renderWebMiddleware(config, auth, storage): any { res.send(webPage); } - router.get('/-/web/:section/*', function(req, res) { + router.get('/-/web/:section/*', function (req, res) { renderHTML(req, res); }); - router.get('/', function(req, res) { + router.get('/', function (req, res) { renderHTML(req, res); }); diff --git a/packages/web/src/user.ts b/packages/web/src/user.ts index 028e8ffab..1f81ba4bf 100644 --- a/packages/web/src/user.ts +++ b/packages/web/src/user.ts @@ -1,27 +1,28 @@ import _ from 'lodash'; -import {stringToMD5} from '@verdaccio/utils'; +import { stringToMD5 } from '@verdaccio/utils'; // this is a generic avatar // https://www.iconfinder.com/icons/403017/anonym_avatar_default_head_person_unknown_user_icon // license: free commercial usage -export const GENERIC_AVATAR = 'data:image/svg+xml;utf8,' + -encodeURIComponent( -'' -); +export const GENERIC_AVATAR = + 'data:image/svg+xml;utf8,' + + encodeURIComponent( + '' + ); /** * Generate gravatar url from email address diff --git a/packages/web/src/web-utils.ts b/packages/web/src/web-utils.ts index 598d91276..37f8d8fe7 100644 --- a/packages/web/src/web-utils.ts +++ b/packages/web/src/web-utils.ts @@ -1,57 +1,57 @@ import _ from 'lodash'; -import { isObject } from "@verdaccio/utils"; +import { isObject } from '@verdaccio/utils'; import { Package, Author } from '@verdaccio/types'; import { normalizeContributors } from '@verdaccio/store'; import { AuthorAvatar } from '@verdaccio/dev-types'; -import {generateGravatarUrl, GENERIC_AVATAR} from "./user"; +import { generateGravatarUrl, GENERIC_AVATAR } from './user'; export function addGravatarSupport(pkgInfo: Package, online = true): AuthorAvatar { - const pkgInfoCopy = { ...pkgInfo } as any; - const author: any = _.get(pkgInfo, 'latest.author', null) as any; - const contributors: AuthorAvatar[] = normalizeContributors(_.get(pkgInfo, 'latest.contributors', [])); - const maintainers = _.get(pkgInfo, 'latest.maintainers', []); + const pkgInfoCopy = { ...pkgInfo } as any; + const author: any = _.get(pkgInfo, 'latest.author', null) as any; + const contributors: AuthorAvatar[] = normalizeContributors(_.get(pkgInfo, 'latest.contributors', [])); + const maintainers = _.get(pkgInfo, 'latest.maintainers', []); - // for author. - if (author && _.isObject(author)) { - const { email } = author as Author; - pkgInfoCopy.latest.author.avatar = generateGravatarUrl(email, online); - } + // for author. + if (author && _.isObject(author)) { + const { email } = author as Author; + pkgInfoCopy.latest.author.avatar = generateGravatarUrl(email, online); + } - if (author && _.isString(author)) { - pkgInfoCopy.latest.author = { - avatar: GENERIC_AVATAR, - email: '', - author, - }; - } + if (author && _.isString(author)) { + pkgInfoCopy.latest.author = { + avatar: GENERIC_AVATAR, + email: '', + author, + }; + } - // for contributors - if (_.isEmpty(contributors) === false) { - pkgInfoCopy.latest.contributors = contributors.map( - (contributor): AuthorAvatar => { - if (isObject(contributor)) { - contributor.avatar = generateGravatarUrl(contributor.email, online); - } else if (_.isString(contributor)) { - contributor = { - avatar: GENERIC_AVATAR, - email: contributor, - name: contributor, - }; - } + // for contributors + if (_.isEmpty(contributors) === false) { + pkgInfoCopy.latest.contributors = contributors.map( + (contributor): AuthorAvatar => { + if (isObject(contributor)) { + contributor.avatar = generateGravatarUrl(contributor.email, online); + } else if (_.isString(contributor)) { + contributor = { + avatar: GENERIC_AVATAR, + email: contributor, + name: contributor, + }; + } - return contributor; - } - ); - } + return contributor; + } + ); + } - // for maintainers - if (_.isEmpty(maintainers) === false) { - pkgInfoCopy.latest.maintainers = maintainers.map((maintainer): void => { - maintainer.avatar = generateGravatarUrl(maintainer.email, online); - return maintainer; - }); - } + // for maintainers + if (_.isEmpty(maintainers) === false) { + pkgInfoCopy.latest.maintainers = maintainers.map((maintainer): void => { + maintainer.avatar = generateGravatarUrl(maintainer.email, online); + return maintainer; + }); + } - return pkgInfoCopy; + return pkgInfoCopy; } diff --git a/packages/web/test/utils.spec.ts b/packages/web/test/utils.spec.ts index 1cabb60d6..93eea9bff 100644 --- a/packages/web/test/utils.spec.ts +++ b/packages/web/test/utils.spec.ts @@ -1,5 +1,5 @@ import { addGravatarSupport } from '../src/web-utils'; -import { generateGravatarUrl, GENERIC_AVATAR } from '../src/user'; +import { generateGravatarUrl, GENERIC_AVATAR } from '../src/user'; describe('Utilities', () => { describe('User utilities', () => { @@ -25,7 +25,7 @@ describe('Utilities', () => { test('author, contributors and maintainers fields are not present', () => { const packageInfo = { - latest: {} + latest: {}, }; // @ts-ignore @@ -41,16 +41,16 @@ describe('Utilities', () => { test('author field is a string type', () => { const packageInfo = { - latest: { author: 'user@verdccio.org' } + latest: { author: 'user@verdccio.org' }, }; const result = { latest: { author: { author: 'user@verdccio.org', avatar: GENERIC_AVATAR, - email: '' - } - } + email: '', + }, + }, }; // @ts-ignore @@ -59,17 +59,16 @@ describe('Utilities', () => { test('author field is an object type with author information', () => { const packageInfo = { - latest: { author: { name: 'verdaccio', email: 'user@verdccio.org' } } + latest: { author: { name: 'verdaccio', email: 'user@verdccio.org' } }, }; const result = { latest: { author: { - avatar: - 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7', + avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7', email: 'user@verdccio.org', - name: 'verdaccio' - } - } + name: 'verdaccio', + }, + }, }; // @ts-ignore @@ -79,42 +78,40 @@ describe('Utilities', () => { test('contributor field is a blank array', () => { const packageInfo = { latest: { - contributors: [] - } + contributors: [], + }, }; // @ts-ignore expect(addGravatarSupport(packageInfo)).toEqual(packageInfo); }); - describe("contributors", () => { + describe('contributors', () => { test('contributors field has contributors', () => { const packageInfo = { latest: { contributors: [ { name: 'user', email: 'user@verdccio.org' }, - { name: 'user1', email: 'user1@verdccio.org' } - ] - } + { name: 'user1', email: 'user1@verdccio.org' }, + ], + }, }; const result = { latest: { contributors: [ { - avatar: - 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7', + avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7', email: 'user@verdccio.org', - name: 'user' + name: 'user', }, { - avatar: - 'https://www.gravatar.com/avatar/51105a49ce4a9c2bfabf0f6a2cba3762', + avatar: 'https://www.gravatar.com/avatar/51105a49ce4a9c2bfabf0f6a2cba3762', email: 'user1@verdccio.org', - name: 'user1' - } - ] - } + name: 'user1', + }, + ], + }, }; // @ts-ignore @@ -124,8 +121,8 @@ describe('Utilities', () => { test('contributors field is an object', () => { const packageInfo = { latest: { - contributors: { name: 'user', email: 'user@verdccio.org' } - } + contributors: { name: 'user', email: 'user@verdccio.org' }, + }, }; const result = { @@ -134,10 +131,10 @@ describe('Utilities', () => { { avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7', email: 'user@verdccio.org', - name: 'user' - } - ] - } + name: 'user', + }, + ], + }, }; // @ts-ignore @@ -148,8 +145,8 @@ describe('Utilities', () => { const contributor = 'Barney Rubble (http://barnyrubble.tumblr.com/)'; const packageInfo = { latest: { - contributors: contributor - } + contributors: contributor, + }, }; const result = { @@ -158,10 +155,10 @@ describe('Utilities', () => { { avatar: GENERIC_AVATAR, email: contributor, - name: contributor - } - ] - } + name: contributor, + }, + ], + }, }; // @ts-ignore @@ -172,8 +169,8 @@ describe('Utilities', () => { test('maintainers field is a blank array', () => { const packageInfo = { latest: { - maintainers: [] - } + maintainers: [], + }, }; // @ts-ignore @@ -185,33 +182,30 @@ describe('Utilities', () => { latest: { maintainers: [ { name: 'user', email: 'user@verdccio.org' }, - { name: 'user1', email: 'user1@verdccio.org' } - ] - } + { name: 'user1', email: 'user1@verdccio.org' }, + ], + }, }; const result = { latest: { maintainers: [ { - avatar: - 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7', + avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7', email: 'user@verdccio.org', - name: 'user' + name: 'user', }, { - avatar: - 'https://www.gravatar.com/avatar/51105a49ce4a9c2bfabf0f6a2cba3762', + avatar: 'https://www.gravatar.com/avatar/51105a49ce4a9c2bfabf0f6a2cba3762', email: 'user1@verdccio.org', - name: 'user1' - } - ] - } + name: 'user1', + }, + ], + }, }; // @ts-ignore expect(addGravatarSupport(packageInfo)).toEqual(result); }); }); - }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 28f6d3c38..e9656714b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,7 +57,7 @@ importers: eslint-plugin-import: 2.22.0_eslint@7.5.0 eslint-plugin-jest: 23.8.0_eslint@7.5.0+typescript@3.9.5 eslint-plugin-jsx-a11y: 6.3.1_eslint@7.5.0 - eslint-plugin-prettier: 3.1.2_eslint@7.5.0+prettier@1.19.1 + eslint-plugin-prettier: 3.1.2_eslint@7.5.0+prettier@2.0.5 eslint-plugin-react: 7.20.5_eslint@7.5.0 eslint-plugin-react-hooks: 4.0.8_eslint@7.5.0 eslint-plugin-simple-import-sort: 5.0.2_eslint@7.5.0 @@ -72,7 +72,7 @@ importers: kleur: 3.0.3 lint-staged: 8.2.1 nock: 12.0.3 - prettier: 1.19.1 + prettier: 2.0.5 rimraf: 3.0.2 selfsigned: 1.10.7 standard-version: 8.0.0 @@ -153,7 +153,7 @@ importers: kleur: 3.0.3 lint-staged: 8.2.1 nock: 12.0.3 - prettier: 1.19.1 + prettier: 2.0.5 rimraf: 3.0.2 selfsigned: 1.10.7 standard-version: 8.0.0 @@ -4775,10 +4775,10 @@ packages: eslint: ^3 || ^4 || ^5 || ^6 || ^7 resolution: integrity: sha512-i1S+P+c3HOlBJzMFORRbC58tHa65Kbo8b52/TwCwSKLohwvpfT5rm2GjGWzOHTEuq4xxf2aRlHHTtmExDQOP+g== - /eslint-plugin-prettier/3.1.2_eslint@7.5.0+prettier@1.19.1: + /eslint-plugin-prettier/3.1.2_eslint@7.5.0+prettier@2.0.5: dependencies: eslint: 7.5.0 - prettier: 1.19.1 + prettier: 2.0.5 prettier-linter-helpers: 1.0.0 dev: true engines: @@ -8578,13 +8578,13 @@ packages: node: '>=6.0.0' resolution: integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - /prettier/1.19.1: + /prettier/2.0.5: dev: true engines: - node: '>=4' + node: '>=10.13.0' hasBin: true resolution: - integrity: sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== + integrity: sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== /pretty-format/25.5.0: dependencies: '@jest/types': 25.5.0 diff --git a/website/.prettierrc.json b/website/.prettierrc.json deleted file mode 100644 index 9c2e3eabc..000000000 --- a/website/.prettierrc.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "endOfLine": "auto", - "useTabs": false, - "printWidth": 180, - "tabWidth": 2, - "singleQuote": true, - "bracketSpacing": true, - "jsxBracketSameLine": true, - "trailingComma": "es5", - "semi": true, - "parser": "typescript" -}