0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-02-17 23:45:29 -05:00

test: add some unit test for local-storage

This commit is contained in:
Juan Picado @jotadeveloper 2017-12-17 18:33:09 +01:00 committed by juanpicado
parent 724e372246
commit d0e97cf076
9 changed files with 530 additions and 189 deletions

View file

@ -16,7 +16,7 @@
},
"dependencies": {
"@verdaccio/file-locking": "^0.0.5",
"@verdaccio/local-storage": "^0.0.11",
"@verdaccio/local-storage": "^0.0.14",
"@verdaccio/streams": "^0.0.2",
"@verdaccio/types": "^0.0.8",
"JSONStream": "^1.1.1",

View file

@ -2,8 +2,8 @@
/* eslint prefer-rest-params: 0 */
import assert from 'assert';
import Crypto from 'crypto';
import assert from 'assert';
import fs from 'fs';
import Path from 'path';
import Stream from 'stream';
@ -12,6 +12,10 @@ import _ from 'lodash';
// $FlowFixMe
import async from 'async';
import * as Utils from './utils';
import {
generatePackageTemplate, normalizePackage, generateRevision, cleanUpReadme,
fileExist, noSuchFile, resourceNotAvailable, DEFAULT_REVISION, pkgFileName,
} from './storage-utils';
import LocalDatabase from '@verdaccio/local-storage';
import {UploadTarball, ReadTarball} from '@verdaccio/streams';
@ -30,33 +34,12 @@ import type {
ILocalData,
} from '@verdaccio/local-storage';
const pkgFileName = 'package.json';
const fileExist = 'EEXISTS';
const noSuchFile = 'ENOENT';
const resourceNotAvailable = 'EAGAIN';
const generatePackageTemplate = function(name: string): Package {
return {
// standard things
'name': name,
'versions': {},
'dist-tags': {},
'time': {},
'_distfiles': {},
'_attachments': {},
'_uplinks': {},
};
};
const DEFAULT_REVISION: string = `0-0000000000000000`;
/**
* Implements Storage interface (same for storage.js, local-storage.js, up-storage.js).
*/
class Storage implements IStorage {
class LocalStorage implements IStorage {
config: Config;
utils: Utils;
localData: ILocalData;
logger: Logger;
@ -66,7 +49,7 @@ class Storage implements IStorage {
this.config = config;
}
addPackage(name: string, info: Package, callback: Callback) {
addPackage(name: string, pkg: Package, callback: Callback) {
const storage: ILocalFS = this._getLocalStorage(name);
if (_.isNil(storage)) {
@ -74,15 +57,15 @@ class Storage implements IStorage {
}
storage.createJSON(pkgFileName, generatePackageTemplate(name), (err) => {
if (err && err.code === fileExist) {
if (_.isNull(err) === false && err.code === fileExist) {
return callback( Utils.ErrorCode.get409());
}
const latest = Utils.getLatestVersion(info);
if (_.isNil(latest) === false && info.versions[latest]) {
return callback(null, info.versions[latest]);
const latest = Utils.getLatestVersion(pkg);
if (_.isNil(latest) === false && pkg.versions[latest]) {
return callback(null, pkg.versions[latest]);
}
return callback();
});
}
@ -95,6 +78,7 @@ class Storage implements IStorage {
*/
removePackage(name: string, callback: Callback) {
let storage: ILocalFS = this._getLocalStorage(name);
if (_.isNil(storage)) {
return callback( Utils.ErrorCode.get404());
}
@ -107,9 +91,10 @@ class Storage implements IStorage {
return callback(err);
}
}
this._normalizePackage(data);
let removeFailed = this.localData.remove(name);
data = normalizePackage(data);
const removeFailed = this.localData.remove(name);
if (removeFailed) {
// This will happen when database is locked
@ -127,26 +112,6 @@ class Storage implements IStorage {
});
}
_deleteAttachments(storage: ILocalFS, attachments: string[], callback: Callback): void {
const unlinkNext = function(cb) {
if (_.isEmpty(attachments)) {
return cb();
}
const attachment = attachments.shift();
storage.deleteJSON(attachment, function() {
unlinkNext(cb);
});
};
unlinkNext(function() {
// try to unlink the directory, but ignore errors because it can fail
storage.removePackage(function(err) {
callback(err);
});
});
}
/**
* Synchronize remote package info with the local one
* @param {*} name
@ -162,11 +127,11 @@ class Storage implements IStorage {
let change = false;
for (let versionId in packageInfo.versions) {
if (_.isNil(packageLocalJson.versions[versionId])) {
const version = packageInfo.versions[versionId];
let version = packageInfo.versions[versionId];
// we don't keep readmes for package versions,
// only one readme per package
delete version.readme;
version = cleanUpReadme(version);
change = true;
packageLocalJson.versions[versionId] = version;
@ -192,12 +157,14 @@ class Storage implements IStorage {
}
}
}
for (let tag in packageInfo['dist-tags']) {
if (!packageLocalJson['dist-tags'][tag] || packageLocalJson['dist-tags'][tag] !== packageInfo['dist-tags'][tag]) {
change = true;
packageLocalJson['dist-tags'][tag] = packageInfo['dist-tags'][tag];
}
}
for (let up in packageInfo._uplinks) {
if (Object.prototype.hasOwnProperty.call(packageInfo._uplinks, up)) {
const need_change = !Utils.is_object(packageLocalJson._uplinks[up])
@ -232,27 +199,6 @@ class Storage implements IStorage {
});
}
/**
* Ensure the dist file remains as the same protocol
* @param {Object} hash metadata
* @param {String} upLinkKey registry key
* @private
*/
_updateUplinkToRemoteProtocol(hash: DistFile, upLinkKey: string): void {
// if we got this information from a known registry,
// use the same protocol for the tarball
//
// see https://github.com/rlidwka/sinopia/issues/166
const tarballUrl: any = UrlNode.parse(hash.url);
const uplinkUrl: any = UrlNode.parse(this.config.uplinks[upLinkKey].url);
if (uplinkUrl.host === tarballUrl.host) {
tarballUrl.protocol = uplinkUrl.protocol;
hash.registry = upLinkKey;
hash.url = UrlNode.format(tarballUrl);
}
}
/**
* Add a new version to a previous local package.
* @param {*} name
@ -269,7 +215,7 @@ class Storage implements IStorage {
data.readme = metadata.readme;
// TODO: lodash remove
delete metadata.readme;
metadata = cleanUpReadme(metadata);
if (data.versions[version] != null) {
return cb( Utils.ErrorCode.get409() );
@ -344,6 +290,7 @@ class Storage implements IStorage {
_getVersionNotFound() {
return Utils.ErrorCode.get404('this version doesn\'t exist');
}
/**
* Return file no available
* @return {String}
@ -357,32 +304,36 @@ class Storage implements IStorage {
* Update the package metadata, tags and attachments (tarballs).
* Note: Currently supports unpublishing only.
* @param {*} name
* @param {*} metadata
* @param {*} pkg
* @param {*} revision
* @param {*} callback
* @return {Function}
*/
changePackage(name: string,
metadata: Package,
pkg: Package,
revision?: string, callback: Callback) {
if (!Utils.is_object(metadata.versions) || !Utils.is_object(metadata['dist-tags'])) {
if (!Utils.is_object(pkg.versions) || !Utils.is_object(pkg['dist-tags'])) {
return callback( Utils.ErrorCode.get422());
}
this._updatePackage(name, (data, cb) => {
for (let ver in data.versions) {
if (_.isNil(metadata.versions[ver])) {
this.logger.info( {name: name, version: ver},
'unpublishing @{name}@@{version}');
delete data.versions[ver];
for (let file in data._attachments) {
if (data._attachments[file].version === ver) {
delete data._attachments[file].version;
this._updatePackage(name, (jsonData, cb) => {
for (let ver in jsonData.versions) {
if (_.isNil(pkg.versions[ver])) {
this.logger.info( {name: name, version: ver}, 'unpublishing @{name}@@{version}');
delete jsonData.versions[ver];
for (let file in jsonData._attachments) {
if (jsonData._attachments[file].version === ver) {
delete jsonData._attachments[file].version;
}
}
}
}
data['dist-tags'] = metadata['dist-tags'];
jsonData['dist-tags'] = pkg['dist-tags'];
cb();
}, function(err) {
if (err) {
@ -391,7 +342,6 @@ class Storage implements IStorage {
callback();
});
}
/**
* Remove a tarball.
* @param {*} name
@ -697,8 +647,8 @@ class Storage implements IStorage {
return callback(this._internalError(err, pkgFileName, 'error reading'));
}
}
this._normalizePackage(result);
callback(err, result);
callback(err, normalizePackage(result));
});
}
@ -772,28 +722,6 @@ class Storage implements IStorage {
}, on_end);
}
/**
* Normalise package properties, tags, revision id.
* @param {Object} pkg package reference.
*/
_normalizePackage(pkg: Package) {
const pkgProperties = ['versions', 'dist-tags', '_distfiles', '_attachments', '_uplinks', 'time'];
pkgProperties.forEach((key) => {
if (_.isNil(Utils.is_object(pkg[key]))) {
pkg[key] = {};
}
});
if (_.isString(pkg._rev) === false) {
pkg._rev = DEFAULT_REVISION;
}
// normalize dist-tags
Utils.normalize_dist_tags(pkg);
}
/**
* Retrieve either a previous created local package or a boilerplate.
* @param {*} name
@ -810,23 +738,18 @@ class Storage implements IStorage {
// TODO: race condition
if (_.isNil(err) === false) {
if (err.code === noSuchFile) {
// if package doesn't exist, we create it here
data = generatePackageTemplate(name);
} else {
return callback(this._internalError(err, pkgFileName, 'error reading'));
}
}
this._normalizePackage(data);
callback(null, data);
callback(null, normalizePackage(data));
});
}
_createNewPackage(name: string, callback: Callback): Callback {
const data = generatePackageTemplate(name);
this._normalizePackage(data);
return callback(null, data);
return callback(null, normalizePackage(generatePackageTemplate(name)));
}
/**
@ -837,8 +760,7 @@ class Storage implements IStorage {
* @return {Object} Error instance
*/
_internalError(err: string, file: string, message: string) {
this.logger.error( {err: err, file: file},
message + ' @{file}: @{!err.message}' );
this.logger.error( {err: err, file: file}, `${message} @{file}: @{!err.message}` );
return Utils.ErrorCode.get500();
}
@ -854,29 +776,29 @@ class Storage implements IStorage {
6. callback(err?)
* @param {*} name package name
* @param {*} updateFn function(package, cb) - update function
* @param {*} _callback callback that gets invoked after it's all updated
* @param {*} callback callback that gets invoked after it's all updated
* @return {Function}
*/
_updatePackage(name: string, updateFn: Callback, _callback: Callback) {
_updatePackage(name: string, updateFn: Callback, callback: Callback) {
const storage: ILocalFS = this._getLocalStorage(name);
if (!storage) {
return _callback( Utils.ErrorCode.get404() );
return callback( Utils.ErrorCode.get404() );
}
storage.lockAndReadJSON(pkgFileName, (err, json) => {
let locked = false;
// callback that cleans up lock first
const callback = function(err: Error) {
const lockCallback = function(err: Error) {
let _args = arguments;
if (locked) {
storage.unlockJSON(pkgFileName, function() {
// ignore any error from the unlock
_callback.apply(err, _args);
callback.apply(err, _args);
});
} else {
_callback(..._args);
callback(..._args);
}
};
@ -886,20 +808,21 @@ class Storage implements IStorage {
if (err) {
if (err.code === resourceNotAvailable) {
return callback( Utils.ErrorCode.get503() );
return lockCallback( Utils.ErrorCode.get503() );
} else if (err.code === noSuchFile) {
return callback( Utils.ErrorCode.get404() );
return lockCallback( Utils.ErrorCode.get404() );
} else {
return callback(err);
return lockCallback(err);
}
}
this._normalizePackage(json);
json = normalizePackage(json);
updateFn(json, (err) => {
if (err) {
return callback(err);
return lockCallback(err);
}
this._writePackage(name, json, callback);
this._writePackage(name, json, lockCallback);
});
});
}
@ -913,11 +836,11 @@ class Storage implements IStorage {
*/
_writePackage(name: string, json: Package, callback: Callback) {
// calculate revision a la couchdb
if (typeof(json._rev) !== 'string') {
if (_.isString(json._rev) === false) {
json._rev = DEFAULT_REVISION;
}
json._rev = this._generateRevision(json._rev);
json._rev = generateRevision(json._rev);
let storage: ILocalFS = this._getLocalStorage(name);
if (_.isNil(storage)) {
@ -926,11 +849,46 @@ class Storage implements IStorage {
storage.writeJSON(pkgFileName, json, callback);
}
_generateRevision(rev: string): string {
const _rev = rev.split('-');
_deleteAttachments(storage: ILocalFS, attachments: string[], callback: Callback): void {
const unlinkNext = function(cb) {
if (_.isEmpty(attachments)) {
return cb();
}
return ((+_rev[0] || 0) + 1) + '-' + Crypto.pseudoRandomBytes(8).toString('hex');
const attachment = attachments.shift();
storage.deleteJSON(attachment, function() {
unlinkNext(cb);
});
};
unlinkNext(function() {
// try to unlink the directory, but ignore errors because it can fail
storage.removePackage(function(err) {
callback(err);
});
});
}
/**
* Ensure the dist file remains as the same protocol
* @param {Object} hash metadata
* @param {String} upLinkKey registry key
* @private
*/
_updateUplinkToRemoteProtocol(hash: DistFile, upLinkKey: string): void {
// if we got this information from a known registry,
// use the same protocol for the tarball
//
// see https://github.com/rlidwka/sinopia/issues/166
const tarballUrl: any = UrlNode.parse(hash.url);
const uplinkUrl: any = UrlNode.parse(this.config.uplinks[upLinkKey].url);
if (uplinkUrl.host === tarballUrl.host) {
tarballUrl.protocol = uplinkUrl.protocol;
hash.registry = upLinkKey;
hash.url = UrlNode.format(tarballUrl);
}
}
}
module.exports = Storage;
module.exports = LocalStorage;

84
src/lib/storage-utils.js Normal file
View file

@ -0,0 +1,84 @@
// @flow
import _ from 'lodash';
import crypto from 'crypto';
import * as Utils from './utils';
import type {
Package, Version
} from '@verdaccio/types';
const pkgFileName = 'package.json';
const fileExist: string = 'EEXISTS';
const noSuchFile: string = 'ENOENT';
const resourceNotAvailable: string = 'EAGAIN';
const DEFAULT_REVISION: string = `0-0000000000000000`;
const generatePackageTemplate = function(name: string): Package {
return {
// standard things
'name': name,
'versions': {},
'dist-tags': {},
'time': {},
'_distfiles': {},
'_attachments': {},
'_uplinks': {},
};
};
/**
* Normalise package properties, tags, revision id.
* @param {Object} pkg package reference.
*/
function normalizePackage(pkg: Package) {
const pkgProperties = [
'versions',
'dist-tags',
'_distfiles',
'_attachments',
'_uplinks',
'time'];
pkgProperties.forEach((key) => {
if (_.isNil(Utils.is_object(pkg[key]))) {
pkg[key] = {};
}
});
if (_.isString(pkg._rev) === false) {
pkg._rev = DEFAULT_REVISION;
}
// normalize dist-tags
Utils.normalize_dist_tags(pkg);
return pkg;
}
function generateRevision(rev: string): string {
const _rev = rev.split('-');
return ((+_rev[0] || 0) + 1) + '-' + crypto.pseudoRandomBytes(8).toString('hex');
}
function cleanUpReadme(version: Version): Version {
if(_.isNil(version) === false) {
delete version.readme;
}
return version;
}
export {
generatePackageTemplate,
normalizePackage,
generateRevision,
cleanUpReadme,
DEFAULT_REVISION,
fileExist,
noSuchFile,
pkgFileName,
resourceNotAvailable,
};

View file

@ -0,0 +1,179 @@
// @flow
import rimRaf from 'rimraf';
import LocalStorage from '../../src/lib/local-storage';
import AppConfig from '../../src/lib/config';
import configExample from './partials/config';
import Logger, {setup} from '../../src/lib/logger';
import {readFile} from '../functional/lib/test.utils';
const readMetadata = (fileName: string = 'metadata') => readFile(`../../unit/partials/${fileName}`);
import type {IStorage} from '@verdaccio/types';
setup([]);
describe('LocalStorage', () => {
let storage: IStorage;
const pkgName: string = 'npm_test';
beforeAll(function () {
storage = new LocalStorage(new AppConfig(configExample), Logger.logger);
});
test('should be defined', () => {
expect(storage).toBeDefined();
});
describe('LocalStorage::addPackage', () => {
test('should add a package', (done) => {
const metadata = JSON.parse(readMetadata());
const pkgStoragePath: string = storage._getLocalStorage(pkgName);
rimRaf(pkgStoragePath.path, (err) => {
expect(err).toBeNull();
storage.addPackage(pkgName, metadata, (err, data) => {
expect(data.version).toMatch(/1.0.0/);
expect(data.dist.tarball).toMatch(/npm_test-1.0.0.tgz/);
expect(data.name).toMatch(pkgName);
done();
});
});
});
test('should fails on add a package', (done) => {
const metadata = JSON.parse(readMetadata());
storage.addPackage(pkgName, metadata, (err, data) => {
expect(err).not.toBeNull();
expect(err.statusCode).toEqual(409);
// expect(err.status).toMatch(/this package is already present/);
done();
});
});
});
describe('LocalStorage::addVersion', () => {
test('should add new version without tag', (done) => {
const metadata = JSON.parse(readMetadata('metadata-add-version'));
storage.addVersion(pkgName, '1.0.1', metadata, null, (err, data) => {
expect(err).toBeNull();
expect(data).toBeUndefined();
done();
});
});
test('should fails on add a duplicated version without tag', (done) => {
const metadata = JSON.parse(readMetadata('metadata-add-version'));
storage.addVersion(pkgName, '1.0.1', metadata, null, (err, data) => {
expect(err).not.toBeNull();
expect(err.statusCode).toEqual(409);
expect(err.message).toMatch(/this package is already present/);
done();
});
});
test('should add new second version without tag', (done) => {
const metadata = JSON.parse(readMetadata('metadata-add-version'));
storage.addVersion(pkgName, '1.0.2', metadata, 'beta', (err, data) => {
expect(err).toBeNull();
expect(data).toBeUndefined();
done();
});
});
});
describe('LocalStorage::changePackage', () => {
test('should unpublish a version', (done) => {
const metadata = JSON.parse(readMetadata('metadata-unpublish'));
const rev: string = metadata['_rev'];
storage.changePackage(pkgName, metadata, rev, (err) => {
expect(err).toBeUndefined();
done();
});
});
});
describe('LocalStorage::addTarball', () => {
test('should add a new tarball', (done) => {
const tarballData = JSON.parse(readMetadata('addTarball'));
const stream = storage.addTarball(pkgName, `${pkgName}-add-tarball-1.0.4.tgz`);
stream.on('error', function(err) {
expect(err).toBeNull();
done();
});
stream.on('success', function() {
done();
});
stream.end(new Buffer(tarballData.data, 'base64'));
stream.done();
});
test('should fails on add a new tarball on missing package', (done) => {
const tarballData = JSON.parse(readMetadata('addTarball'));
const stream = storage.addTarball('unexsiting-package', `${pkgName}-add-tarball-1.0.4.tgz`);
stream.on('error', function(err) {
expect(err).not.toBeNull();
expect(err.statusCode).toEqual(404);
expect(err.message).toMatch(/no such package available/);
done();
});
stream.on('success', function() {
done();
});
stream.end(new Buffer(tarballData.data, 'base64'));
stream.done();
});
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) {
expect(err).not.toBeNull();
expect(err.statusCode).toEqual(422);
expect(err.message).toMatch(/refusing to accept zero-length file/);
done();
});
stream.done();
});
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`);
stream.abort();
stream.on('error', function(err) {
expect(err).not.toBeNull();
expect(err.statusCode).toEqual(403);
expect(err.message).toMatch(/can't use this filename/);
done();
});
stream.done();
});
});
// describe('LocalStorage::removePackage', () => {
// test('should remove completely package', (done) => {
// storage.removePackage(pkgName, (err, data) => {
// expect(err).toBeNull();
// expect(data).toBeUndefined();
// done();
// });
// });
//
// test('should fails with package not found', (done) => {
// const pkgName: string = 'npm_test_fake';
// storage.removePackage(pkgName, (err, data) => {
// expect(err).not.toBeNull();
// expect(err.message).toMatch(/no such package available/);
// done();
// });
// });
// });
});

View file

@ -0,0 +1,5 @@
{
"content_type": "application\/octet-stream",
"data": "H4sIAAAAAAAAE+2SPU\/DMBCGM+dXnDx0QsHOR5G6AgMzI4XKcg7qltiW7ZYi1P+OHRcqoWxEQkh5lpPf93x3\/jBcbPkLXpoUi43TKhsZSum8rmFIj9RNCRmrStY0ZVXNq4wy1lwxyOjYgwyxc57bMMpv66SzwHf8J3zkAETxDskiRNOtPDq\/2mjPyUW09mid1Cq6rKBFndQWnbDS+JOTxI7LfiVVi4fwkb5SDQZBCYkuuLFfUGOXmPvEirqgJIjHU\/b+5seGZKR+AxVQrDUsya212i5AaYgGOINCPktslwRmM8CD9MDObbb4\/qZtG8s9PPYK3\/m1tufDvEqByvW3cnd\/TfJj\/tcvNTExMTEun6rWVXoACAAA",
"length": 279
}

View file

@ -0,0 +1,50 @@
{
"_id": "npm_test",
"name": "npm_test",
"description": "",
"dist-tags": {
"latest": "1.0.0"
},
"versions": {
"1.0.0": {
"name": "npm_test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"test": "^1.4.0"
},
"devDependencies": {
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
],
"author": "",
"license": "ISC",
"readme": "ERROR: No README data found!",
"_id": "npm_test@1.0.0",
"_npmVersion": "5.5.1",
"_nodeVersion": "9.3.0",
"_npmUser": {
},
"dist": {
"integrity": "sha512-tfzM1OFjWwg2d2Wke\/DV6icjeTZUVOZYLkbf8wmONRSAgMovL\/F+zyI24OhTtWyOXd1Kbj2YUMBvLpmpAjv8zg==",
"shasum": "3e4e6bd5097b295e520b947c9be3259a9509a673",
"tarball": "http:\/\/localhost:4873\/npm_test\/-\/npm_test-1.0.0.tgz"
}
}
},
"readme": "ERROR: No README data found!",
"_attachments": {
"npm_test-1.0.0.tgz": {
"content_type": "application\/octet-stream",
"data": "H4sIAAAAAAAAE+2ST08CMRDFOe+nmPTAyawt7ELCVT149ihqmu4gI9I2bUGM4bvbbhGM4eYmxmR\/l6bvtW+mf6xUK\/mMlzaP5Ys3etAxnPNJVcE5PVHV0RPjkairsZiK0YALUU+mMOBdN3KOjQ\/SxVZ+m5PPAsfxn\/BRADAt18hmwDxpY0k+BfSBXSRni86T0ckUJS95Vhv0ypENByeLa0ntjHSDu\/iPvpZajIJWhD66qRwcC6Xlj6KsYm7U94cN2+sfe7KRS34LabuMCaiWBubsxjnjZqANJAO8RUULwmbOYDgE3FEAcSqzwvc345oUd\/\/QKnITlsadzvNKCrVv7+X27ooV++Kv36qnp6enSz4B8bhKUwAIAAA=",
"length": 281
}
}
}

View file

@ -0,0 +1,32 @@
{
"name": "npm_test",
"version": "1.0.1",
"description": "",
"main": "index.js",
"dependencies": {
"test": "^1.4.1"
},
"devDependencies": {
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
],
"author": "",
"license": "ISC",
"readme": "ERROR: No README data found!",
"_id": "npm_test@1.0.1",
"_npmVersion": "5.5.1",
"_nodeVersion": "9.3.0",
"_npmUser": {
},
"dist": {
"integrity": "sha512-zVEqt1JUCOPsash9q4wMkJEDPD+QCx95TRhQII+JnoS31uBUKoZxhzvvUJCcLVy2CQG4QdwXARU7dYWPnrwhGg==",
"shasum": "b7088c30970489637f8b4e6795e8cf2b699d7569",
"tarball": "http:\/\/localhost:4873\/npm_test\/-\/npm_test-1.0.1.tgz"
}
}

View file

@ -0,0 +1,46 @@
{
"name": "npm_test",
"versions": {
"1.0.1": {
"name": "npm_test",
"version": "1.0.1",
"description": "",
"main": "index.js",
"dependencies": {
"test": "^1.4.0"
},
"devDependencies": {
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
],
"author": "",
"license": "ISC",
"_id": "npm_test@1.0.0",
"_npmVersion": "5.5.1",
"_nodeVersion": "9.3.0",
"_npmUser": {
},
"dist": {
"integrity": "sha512-tfzM1OFjWwg2d2Wke\/DV6icjeTZUVOZYLkbf8wmONRSAgMovL\/F+zyI24OhTtWyOXd1Kbj2YUMBvLpmpAjv8zg==",
"shasum": "3e4e6bd5097b295e520b947c9be3259a9509a673",
"tarball": "http:\/\/localhost:4873\/npm_test\/-\/npm_test-1.0.1.tgz"
}
}
},
"dist-tags": {
"latest": "1.0.1"
},
"time": {
"modified": "2017-12-17T14:15:10.760Z",
"created": "2017-12-17T11:39:33.140Z",
"1.0.1": "2017-12-17T11:39:33.140Z"
},
"_rev": "9-1c8dae9336a8dc70",
"readme": "ERROR: No README data found!"
}

View file

@ -56,8 +56,8 @@
to-fast-properties "^2.0.0"
"@types/node@*":
version "8.0.57"
resolved "https://registry.npmjs.org/@types/node/-/node-8.0.57.tgz#e5d8b4dc112763e35cfc51988f4f38da3c486d99"
version "8.5.1"
resolved "https://registry.npmjs.org/@types/node/-/node-8.5.1.tgz#4ec3020bcdfe2abffeef9ba3fbf26fca097514b5"
"@verdaccio/file-locking@^0.0.5":
version "0.0.5"
@ -66,14 +66,14 @@
lockfile "1.0.3"
lodash "4.17.4"
"@verdaccio/local-storage@^0.0.11":
version "0.0.11"
resolved "https://registry.npmjs.org/@verdaccio/local-storage/-/local-storage-0.0.11.tgz#3a121f6f08a7cfed1d778c5db26d095542c74cad"
"@verdaccio/local-storage@^0.0.14":
version "0.0.14"
resolved "https://registry.npmjs.org/@verdaccio/local-storage/-/local-storage-0.0.14.tgz#bd9d7084a33336111448801fd266f2dbc8bbe6dc"
dependencies:
"@verdaccio/file-locking" "^0.0.5"
"@verdaccio/streams" "^0.0.2"
async "2.5.0"
http-errors "1.4.0"
http-errors "1.6.2"
lodash "4.17.4"
mkdirp "0.5.1"
@ -149,8 +149,8 @@ ajv@^4.9.1:
json-stable-stringify "^1.0.1"
ajv@^5.0.0, ajv@^5.1.0, ajv@^5.1.5, ajv@^5.2.0, ajv@^5.2.3:
version "5.5.1"
resolved "https://registry.npmjs.org/ajv/-/ajv-5.5.1.tgz#b38bb8876d9e86bee994956a04e721e88b248eb2"
version "5.5.2"
resolved "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
dependencies:
co "^4.6.0"
fast-deep-equal "^1.0.0"
@ -376,11 +376,11 @@ autoprefixer@^6.3.1:
postcss-value-parser "^3.2.3"
autoprefixer@^7.1.2:
version "7.2.2"
resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.2.tgz#082293b964be00602efacc59aa4aa7df5158bb6e"
version "7.2.3"
resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.3.tgz#c2841e38b7940c2d0a9bbffd72c75f33637854f8"
dependencies:
browserslist "^2.10.0"
caniuse-lite "^1.0.30000780"
caniuse-lite "^1.0.30000783"
normalize-range "^0.1.2"
num2fraction "^1.2.2"
postcss "^6.0.14"
@ -1456,12 +1456,12 @@ caniuse-api@^1.5.2:
lodash.uniq "^4.5.0"
caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
version "1.0.30000780"
resolved "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000780.tgz#8d1977561d00ff0f0ed2b6b66140328ab4504c0a"
version "1.0.30000783"
resolved "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000783.tgz#16b30d47266a4f515cc69ae0316b670c9603cdbe"
caniuse-lite@^1.0.30000780:
version "1.0.30000780"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000780.tgz#1f9095f2efd4940e0ba6c5992ab7a9b64cc35ba4"
caniuse-lite@^1.0.30000780, caniuse-lite@^1.0.30000783:
version "1.0.30000783"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000783.tgz#9b5499fb1b503d2345d12aa6b8612852f4276ffd"
caseless@~0.11.0:
version "0.11.0"
@ -1937,8 +1937,8 @@ core-js@^1.0.0:
resolved "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
core-js@^2.4.0, core-js@^2.5.0:
version "2.5.1"
resolved "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b"
version "2.5.3"
resolved "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e"
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
@ -2524,10 +2524,10 @@ enzyme@^3.2.0:
rst-selector-parser "^2.2.3"
errno@^0.1.3, errno@^0.1.4:
version "0.1.4"
resolved "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d"
version "0.1.6"
resolved "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz#c386ce8a6283f14fc09563b71560908c9bf53026"
dependencies:
prr "~0.0.0"
prr "~1.0.1"
error-ex@^1.2.0, error-ex@^1.3.1:
version "1.3.1"
@ -2699,8 +2699,8 @@ eslint-plugin-import@2.8.0:
read-pkg-up "^2.0.0"
eslint-plugin-jest@^21.2.0:
version "21.4.2"
resolved "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-21.4.2.tgz#0e8ec03687259169cef46656827a0a0715e8a8d4"
version "21.5.0"
resolved "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-21.5.0.tgz#c7a3bd2ee9d1c832b4e31dec89f6ad93e08d4853"
eslint-plugin-react@7.5.1:
version "7.5.1"
@ -3660,13 +3660,6 @@ http-deceiver@^1.2.7:
version "1.2.7"
resolved "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
http-errors@1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.4.0.tgz#6c0242dea6b3df7afda153c71089b31c6e82aabf"
dependencies:
inherits "2.0.1"
statuses ">= 1.2.1 < 2"
http-errors@1.6.2, http-errors@^1.4.0, http-errors@~1.6.2:
version "1.6.2"
resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
@ -4032,10 +4025,8 @@ is-regexp@^1.0.0:
resolved "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
is-resolvable@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62"
dependencies:
tryit "^1.0.1"
version "1.0.1"
resolved "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.1.tgz#acca1cd36dbe44b974b924321555a70ba03b1cf4"
is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
@ -5030,8 +5021,8 @@ modify-values@^1.0.0:
resolved "https://registry.npmjs.org/modify-values/-/modify-values-1.0.0.tgz#e2b6cdeb9ce19f99317a53722f3dbf5df5eaaab2"
moment@^2.10.6:
version "2.19.3"
resolved "https://registry.npmjs.org/moment/-/moment-2.19.3.tgz#bdb99d270d6d7fda78cc0fbace855e27fe7da69f"
version "2.20.0"
resolved "https://registry.npmjs.org/moment/-/moment-2.20.0.tgz#53396358994dd3a551e966a66af715ecb6c30ad0"
ms@2.0.0:
version "2.0.0"
@ -6042,9 +6033,9 @@ proxy-addr@~2.0.2:
forwarded "~0.1.2"
ipaddr.js "1.5.2"
prr@~0.0.0:
version "0.0.0"
resolved "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"
prr@~1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
pseudomap@^1.0.2:
version "1.0.2"
@ -7024,7 +7015,7 @@ state-toggle@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz#d20f9a616bb4f0c3b98b91922d25b640aa2bc425"
"statuses@>= 1.2.1 < 2", "statuses@>= 1.3.1 < 2":
"statuses@>= 1.3.1 < 2":
version "1.4.0"
resolved "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
@ -7424,10 +7415,6 @@ trough@^1.0.0:
dependencies:
glob "^6.0.4"
tryit@^1.0.1:
version "1.0.3"
resolved "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb"
tty-browserify@0.0.0:
version "0.0.0"
resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
@ -7468,8 +7455,8 @@ ua-parser-js@^0.7.9:
resolved "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac"
uglify-js@3.2.x:
version "3.2.1"
resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.2.1.tgz#d6427fd45a25fefc5d196689c0c772a6915e10fe"
version "3.2.2"
resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.2.2.tgz#870e4b34ed733d179284f9998efd3293f7fd73f6"
dependencies:
commander "~2.12.1"
source-map "~0.6.1"
@ -7563,8 +7550,8 @@ unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1:
resolved "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz#3ccbdc53679eed6ecf3777dd7f5e3229c1b6aa3c"
unist-util-visit@^1.1.0:
version "1.2.0"
resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.2.0.tgz#9dc78d1f95cd242e865f7f93f327d3296bb9a718"
version "1.3.0"
resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz#41ca7c82981fd1ce6c762aac397fc24e35711444"
dependencies:
unist-util-is "^2.1.1"