diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d62e13d6..64f3b83b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,35 @@ All notable changes to this project will be documented in this file. See [standa * verdaccio update notification on CLI ([#988](https://github.com/verdaccio/verdaccio/issues/988)) ([#998](https://github.com/verdaccio/verdaccio/issues/998)) ([bc04703](https://github.com/verdaccio/verdaccio/commit/bc04703)) + +# [3.10.0](https://github.com/verdaccio/verdaccio/compare/v3.9.0...v3.10.0) (2018-12-06) + + +### Bug Fixes + +* update docker node to 10.14.1 ([#1148](https://github.com/verdaccio/verdaccio/issues/1148)) ([68165ca](https://github.com/verdaccio/verdaccio/commit/68165ca)) + + +### Features + +* allows package.json as package name ([#1149](https://github.com/verdaccio/verdaccio/issues/1149)) ([6554973](https://github.com/verdaccio/verdaccio/commit/6554973)) + + + + +# [3.9.0](https://github.com/verdaccio/verdaccio/compare/v3.8.6...v3.9.0) (2018-12-04) + + +### Bug Fixes + +* update node within Dockerfile ([#1139](https://github.com/verdaccio/verdaccio/issues/1139)) ([24e9121](https://github.com/verdaccio/verdaccio/commit/24e9121)) + + +### Features + +* display package peer deps ([#1144](https://github.com/verdaccio/verdaccio/issues/1144)) ([9b52b1d](https://github.com/verdaccio/verdaccio/commit/9b52b1d)) + + ## [3.8.6](https://github.com/verdaccio/verdaccio/compare/v3.8.5...v3.8.6) (2018-11-15) @@ -86,6 +115,7 @@ All notable changes to this project will be documented in this file. See [standa * don't exit if using https and pfx is enabled ([#1061](https://github.com/verdaccio/verdaccio/issues/1061)) ([#1062](https://github.com/verdaccio/verdaccio/issues/1062)) ([315a3b2](https://github.com/verdaccio/verdaccio/commit/315a3b2)) + ## [3.8.2](https://github.com/verdaccio/verdaccio/compare/v3.8.1...v3.8.2) (2018-09-27) @@ -711,7 +741,7 @@ All notable changes to this project will be documented in this file. See [standa - Improve Docker Build - [#181](https://github.com/verdaccio/verdaccio/pull/181) - Bugfix #73 `npm-latest` support - [#228](https://github.com/verdaccio/verdaccio/pull/228) -- Add [documentation](https://github.com/verdaccio/verdaccio/tree/master/wiki) - [#229](https://github.com/verdaccio/verdaccio/pull/229) +- Add [documentation](https://github.com/verdaccio/verdaccio/tree/master/wiki) - [#229](https://github.com/verdaccio/verdaccio/pull/229) ## 2.2.1 (June 17, 2017) @@ -733,7 +763,7 @@ All notable changes to this project will be documented in this file. See [standa - Fix upstream search not work with gzip - ([@Meeeeow](https://github.com/Meeeeow) in [#170](https://github.com/verdaccio/verdaccio/pull/170)) - Add additional requirement to output message - ([@marnel ](https://github.com/marnel) in [#184](https://github.com/verdaccio/verdaccio/pull/184)) - Implement npm ping endpoint - ([@juanpicado]((https://github.com/juanpicado))) in [#179](https://github.com/verdaccio/verdaccio/pull/179) -- Add support for multiple notification endpoints to existing webhook - ([@ryan-codingintrigue]((https://github.com/ryan-codingintrigue))) +- Add support for multiple notification endpoints to existing webhook - ([@ryan-codingintrigue]((https://github.com/ryan-codingintrigue))) in [#108](https://github.com/verdaccio/verdaccio/pull/108) @@ -769,9 +799,9 @@ in [#108](https://github.com/verdaccio/verdaccio/pull/108) - rename clean up ([@juanpicado](https://github.com/juanpicado) in [#114](https://github.com/verdaccio/verdaccio/issues/114)) - _npmUser / author not showing up ([@juanpicado](https://github.com/juanpicado) in [#65](https://github.com/verdaccio/verdaccio/issues/65)) - Docs: correct config attribute `proxy_access` ([@robertgroh](https://github.com/robertgroh) in [#96](https://github.com/verdaccio/verdaccio/pull/96)) -- Problem with docker.yaml ([@josedepaz](https://github.com/josedepaz) in [#72](https://github.com/verdaccio/verdaccio/pull/72)) +- Problem with docker.yaml ([@josedepaz](https://github.com/josedepaz) in [#72](https://github.com/verdaccio/verdaccio/pull/72)) - Prevent logging of user and password ([@tlvince](https://github.com/tlvince) in [#94](https://github.com/verdaccio/verdaccio/pull/94)) -- Updated README.md to reflect the availability of the docker image ([@jmwilkinson](https://github.com/jmwilkinson)) in [#71](https://github.com/verdaccio/verdaccio/pull/71)) +- Updated README.md to reflect the availability of the docker image ([@jmwilkinson](https://github.com/jmwilkinson)) in [#71](https://github.com/verdaccio/verdaccio/pull/71)) ## 2.1.0 (October 11, 2016) @@ -845,7 +875,7 @@ in [#108](https://github.com/verdaccio/verdaccio/pull/108) ## 25 Nov 2014, version 1.0.0-alpha -- Config file is now created in `$XDG_CONFIG_HOME` instead of current directory. +- Config file is now created in `$XDG_CONFIG_HOME` instead of current directory. It is printed to stdout each time sinopia starts, so you hopefully won't have any trouble locating it. diff --git a/Dockerfile b/Dockerfile index 36c2e7ad1..9fdb1d632 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:10.7-alpine as builder +FROM node:10.14.1-alpine as builder ENV NODE_ENV=production \ VERDACCIO_BUILD_REGISTRY=https://registry.npmjs.org/ diff --git a/docs/where-are-docs.md b/docs/where-are-docs.md new file mode 100644 index 000000000..c30bbe410 --- /dev/null +++ b/docs/where-are-docs.md @@ -0,0 +1,5 @@ +## Where are the docs now? + +The documentation was relocated to the following website: + +https://github.com/verdaccio/website diff --git a/src/lib/local-storage.js b/src/lib/local-storage.js index 0a0295592..59bcd4068 100644 --- a/src/lib/local-storage.js +++ b/src/lib/local-storage.js @@ -403,7 +403,7 @@ class LocalStorage implements IStorage { _transform.apply(uploadStream, appliedData); }; - if (name === STORAGE.PACKAGE_FILE_NAME || name === '__proto__') { + if (name === '__proto__') { process.nextTick(() => { uploadStream.emit('error', ErrorCode.getForbidden()); }); diff --git a/src/lib/utils.js b/src/lib/utils.js index ce16e5dd5..d34d87394 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -69,7 +69,6 @@ export function validateName(name: string): boolean { normalizedName.charAt(0) === '-' || // "-" is reserved by couchdb normalizedName === 'node_modules' || normalizedName === '__proto__' || - normalizedName === 'package.json' || normalizedName === 'favicon.ico' ); } @@ -209,14 +208,14 @@ export function getVersion(pkg: Package, version: any) { /** * Parse an internet address * Allow: - - https:localhost:1234 - protocol + host + port - - localhost:1234 - host + port - - 1234 - port - - http::1234 - protocol + port - - https://localhost:443/ - full url + https - - http://[::1]:443/ - ipv6 - - unix:/tmp/http.sock - unix sockets - - https://unix:/tmp/http.sock - unix sockets (https) + - https:localhost:1234 - protocol + host + port + - localhost:1234 - host + port + - 1234 - port + - http::1234 - protocol + port + - https://localhost:443/ - full url + https + - http://[::1]:443/ - ipv6 + - unix:/tmp/http.sock - unix sockets + - https://unix:/tmp/http.sock - unix sockets (https) * @param {*} urlAddress the internet address definition * @return {Object|Null} literal object that represent the address parsed */ diff --git a/src/webui/components/PackageSidebar/index.jsx b/src/webui/components/PackageSidebar/index.jsx index 833cd3b4c..8abcfc9d8 100644 --- a/src/webui/components/PackageSidebar/index.jsx +++ b/src/webui/components/PackageSidebar/index.jsx @@ -4,6 +4,7 @@ import get from 'lodash/get'; import LastSync from './modules/LastSync'; import Maintainers from './modules/Maintainers'; import Dependencies from './modules/Dependencies'; +import PeerDependencies from './modules/PeerDependencies'; import Infos from './modules/Infos'; import { @@ -65,6 +66,7 @@ export default class PackageSidebar extends React.Component { // Dependencies component const dependencies = get(packageMeta, 'latest.dependencies', {}); + const peerDependencies = get(packageMeta, 'latest.peerDependencies', {}); // Maintainers component return ( @@ -83,6 +85,7 @@ export default class PackageSidebar extends React.Component { {/* TODO: Refacor later, when we decide to show only maintainers/authors */} + {/* Package management module? Help us implement it! */} ); diff --git a/src/webui/components/PackageSidebar/modules/Dependencies/index.jsx b/src/webui/components/PackageSidebar/modules/Dependencies/index.jsx index c107e424d..8bd95efb9 100644 --- a/src/webui/components/PackageSidebar/modules/Dependencies/index.jsx +++ b/src/webui/components/PackageSidebar/modules/Dependencies/index.jsx @@ -29,10 +29,10 @@ const renderDependenciesList = (dependencies, dependenciesList) => { ); }; -const Dependencies = ({dependencies = {}}) => { +const Dependencies = ({dependencies = {}, title = 'Dependencies'}) => { const dependenciesList = Object.keys(dependencies); return ( - + {dependenciesList.length > 0 ? ( renderDependenciesList(dependencies, dependenciesList) ) : ( @@ -43,7 +43,8 @@ const Dependencies = ({dependencies = {}}) => { }; Dependencies.propTypes = { - dependencies: PropTypes.object + dependencies: PropTypes.object, + title: PropTypes.string }; export default Dependencies; diff --git a/src/webui/components/PackageSidebar/modules/PeerDependencies/index.jsx b/src/webui/components/PackageSidebar/modules/PeerDependencies/index.jsx new file mode 100644 index 000000000..d68a4671f --- /dev/null +++ b/src/webui/components/PackageSidebar/modules/PeerDependencies/index.jsx @@ -0,0 +1,18 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Dependencies from '../Dependencies'; + +export const TITLE = 'Peer Dependencies' + +const PeerDependencies = ({dependencies = {}, title = TITLE}) => { + return ( + + ); +}; + +PeerDependencies.propTypes = { + dependencies: PropTypes.object, + title: PropTypes.string +}; + +export default PeerDependencies; diff --git a/test/functional/sanity/security.js b/test/functional/sanity/security.js index 4afa1e891..c366a655d 100644 --- a/test/functional/sanity/security.js +++ b/test/functional/sanity/security.js @@ -9,7 +9,7 @@ export default function(server) { }); test('should fails on fetch bad pkg #1', () => { - return server.getPackage('package.json') + return server.getPackage('__proto__') .status(HTTP_STATUS.FORBIDDEN) .body_error(/invalid package/); }); @@ -31,8 +31,8 @@ export default function(server) { }); }); - test('should fails and do not return package.json as an attachment', () => { - return server.request({uri: '/testpkg-sec/-/package.json'}) + test('should fails and do not return __proto__ as an attachment', () => { + return server.request({uri: '/testpkg-sec/-/__proto__'}) .status(HTTP_STATUS.FORBIDDEN) .body_error(/invalid filename/); }); @@ -49,7 +49,7 @@ export default function(server) { }); test('should fails on fetch silly things - writing #1', () => { - return server.putTarball('testpkg-sec', 'package.json', '{}') + return server.putTarball('testpkg-sec', '__proto__', '{}') .status(HTTP_STATUS.FORBIDDEN) .body_error(/invalid filename/); }); diff --git a/test/unit/api/local-storage.spec.js b/test/unit/api/local-storage.spec.js index 6052ae416..ff2987b8b 100644 --- a/test/unit/api/local-storage.spec.js +++ b/test/unit/api/local-storage.spec.js @@ -343,7 +343,7 @@ describe('LocalStorage', () => { stream.on('error', (err) => { expect(err).not.toBeNull(); expect(err.statusCode).toEqual(HTTP_STATUS.CONFLICT); - expect(err.message).toMatch(/this package is already present/); + expect(err.message).toMatch(/this package is already present/); }); stream.on('success', function(){ expect(spy).toHaveBeenCalled(); @@ -384,7 +384,7 @@ describe('LocalStorage', () => { }); test('should fails on abort on add a new tarball', (done) => { - const stream = storage.addTarball('package.json', `${pkgName}-fails-add-tarball-1.0.4.tgz`); + const stream = storage.addTarball('__proto__', `${pkgName}-fails-add-tarball-1.0.4.tgz`); stream.abort(); stream.on('error', function(err) { expect(err).not.toBeNull(); diff --git a/test/unit/api/utils.spec.js b/test/unit/api/utils.spec.js index 6e7ccf3fe..74b7e7b44 100644 --- a/test/unit/api/utils.spec.js +++ b/test/unit/api/utils.spec.js @@ -210,10 +210,6 @@ describe('Utilities', () => { expect(validateName('JSONStream')).toBeTruthy(); }); - test('should fails using package.json', () => { - expect(validateName('package.json')).toBeFalsy(); - }); - test('should fails with path seps', () => { expect(validateName('some/thing')).toBeFalsy(); expect(validateName('some\\thing')).toBeFalsy(); diff --git a/test/unit/webui/components/PackageSidebar/__snapshots__/dependencies.spec.js.snap b/test/unit/webui/components/PackageSidebar/__snapshots__/dependencies.spec.js.snap index e749b614b..6964cfc53 100644 --- a/test/unit/webui/components/PackageSidebar/__snapshots__/dependencies.spec.js.snap +++ b/test/unit/webui/components/PackageSidebar/__snapshots__/dependencies.spec.js.snap @@ -3,3 +3,5 @@ exports[` : should load dependencies 1`] = `""`; exports[` : should load the package without dependencies 1`] = `"

Dependencies

Zero Dependencies!

"`; + +exports[` : should permit overriding title 1`] = `"

Package dependencies

Zero Dependencies!

"`; diff --git a/test/unit/webui/components/PackageSidebar/__snapshots__/peerDependencies.spec.js.snap b/test/unit/webui/components/PackageSidebar/__snapshots__/peerDependencies.spec.js.snap new file mode 100644 index 000000000..461fdf349 --- /dev/null +++ b/test/unit/webui/components/PackageSidebar/__snapshots__/peerDependencies.spec.js.snap @@ -0,0 +1,5 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` : should load dependencies 1`] = `""`; + +exports[` : should load the package without dependencies 1`] = `"

Peer Dependencies

Zero Dependencies!

"`; diff --git a/test/unit/webui/components/PackageSidebar/dependencies.spec.js b/test/unit/webui/components/PackageSidebar/dependencies.spec.js index 498cf0564..43a645c3c 100644 --- a/test/unit/webui/components/PackageSidebar/dependencies.spec.js +++ b/test/unit/webui/components/PackageSidebar/dependencies.spec.js @@ -3,7 +3,7 @@ */ import React from 'react'; -import { shallow } from 'enzyme'; +import { mount, shallow } from 'enzyme'; import Dependencies, { NO_DEPENDENCIES, DEP_ITEM_CLASS @@ -57,4 +57,11 @@ describe(' : ', () => { expect(wrapper.find(ModuleContentPlaceholder).props().text).toBe(NO_DEPENDENCIES); expect(wrapper.html()).toMatchSnapshot(); }); + + test('should permit overriding title', () => { + const wrapper = mount(); + + expect(wrapper.find('h2').text()).toEqual('Package dependencies'); + expect(wrapper.html()).toMatchSnapshot(); + }); }); diff --git a/test/unit/webui/components/PackageSidebar/peerDependencies.spec.js b/test/unit/webui/components/PackageSidebar/peerDependencies.spec.js new file mode 100644 index 000000000..0ba1a3717 --- /dev/null +++ b/test/unit/webui/components/PackageSidebar/peerDependencies.spec.js @@ -0,0 +1,64 @@ +/** + * Dependencies component + */ + +import React from 'react'; +import { mount } from 'enzyme'; +import { + NO_DEPENDENCIES, + DEP_ITEM_CLASS +} from '../../../../../src/webui/components/PackageSidebar/modules/Dependencies/index'; +import PeerDependencies, { + TITLE +} from '../../../../../src/webui/components/PackageSidebar/modules/PeerDependencies/index'; +import ModuleContentPlaceholder from '../../../../../src/webui/components/PackageSidebar/ModuleContentPlaceholder'; + + +describe(' : ', () => { + test('should load dependencies', () => { + const peerDependencies = { + '@verdaccio/file-locking': '0.0.3', + '@verdaccio/streams': '0.0.2', + JSONStream: '^1.1.1', + 'apache-md5': '^1.1.2', + async: '^2.0.1', + 'body-parser': '^1.15.0', + bunyan: '^1.8.0', + chalk: '^2.0.1', + commander: '^2.11.0', + compression: '1.6.2', + cookies: '^0.7.0', + cors: '^2.8.3', + express: '4.15.3', + global: '^4.3.2', + handlebars: '4.0.5', + 'http-errors': '^1.4.0', + 'js-string-escape': '1.0.1', + 'js-yaml': '^3.6.0', + jsonwebtoken: '^7.4.1', + lockfile: '^1.0.1', + lodash: '4.17.4', + lunr: '^0.7.0', + marked: '0.3.6', + mime: '^1.3.6', + minimatch: '^3.0.2', + mkdirp: '^0.5.1', + pkginfo: '^0.4.0', + request: '^2.72.0', + semver: '^5.1.0', + 'unix-crypt-td-js': '^1.0.0' + }; + const wrapper = mount(); + + expect(wrapper.find('h2').text()).toEqual(TITLE); + expect(wrapper.find(`.${DEP_ITEM_CLASS}`)).toHaveLength(Object.keys(peerDependencies).length); + expect(wrapper.html()).toMatchSnapshot(); + }); + + test('should load the package without dependencies', () => { + const wrapper = mount(); + + expect(wrapper.find(ModuleContentPlaceholder).props().text).toBe(NO_DEPENDENCIES); + expect(wrapper.html()).toMatchSnapshot(); + }); +});