diff --git a/src/lib/config-utils.js b/src/lib/config-utils.js index 2b712402d..d4c1eac98 100644 --- a/src/lib/config-utils.js +++ b/src/lib/config-utils.js @@ -93,10 +93,10 @@ export function hasProxyTo(pkg: string, upLink: string, packages: PackageList): return false; } -export function getMatchedPackagesSpec(pkg: string, packages: PackageList): MatchedPackage { +export function getMatchedPackagesSpec(pkgName: string, packages: PackageList): MatchedPackage { for (let i in packages) { // $FlowFixMe - if (minimatch.makeRe(i).exec(pkg)) { + if (minimatch.makeRe(i).exec(pkgName)) { return packages[i]; } } diff --git a/src/lib/config.js b/src/lib/config.js index a2966ccfc..a01ea96f1 100644 --- a/src/lib/config.js +++ b/src/lib/config.js @@ -95,8 +95,8 @@ class Config implements AppConfig { /** * Check for package spec */ - getMatchedPackagesSpec(pkg: string): MatchedPackage { - return getMatchedPackagesSpec(pkg, this.packages); + getMatchedPackagesSpec(pkgName: string): MatchedPackage { + return getMatchedPackagesSpec(pkgName, this.packages); } /** diff --git a/src/lib/local-storage.js b/src/lib/local-storage.js index 216e2e63d..4c46686a9 100644 --- a/src/lib/local-storage.js +++ b/src/lib/local-storage.js @@ -269,12 +269,12 @@ class LocalStorage implements IStorage { /** * Merge a new list of tags for a local packages with the existing one. - * @param {*} name + * @param {*} pkgName * @param {*} tags * @param {*} callback */ - mergeTags(name: string, tags: MergeTags, callback: Callback) { - this._updatePackage(name, (data, cb) => { + mergeTags(pkgName: string, tags: MergeTags, callback: Callback) { + this._updatePackage(pkgName, (data, cb) => { /* eslint guard-for-in: 0 */ for (let tag: string in tags) { // this handle dist-tag rm command @@ -315,35 +315,35 @@ class LocalStorage implements IStorage { * Update the package metadata, tags and attachments (tarballs). * Note: Currently supports unpublishing only. * @param {*} name - * @param {*} pkg + * @param {*} incomingPkg * @param {*} revision * @param {*} callback * @return {Function} */ changePackage(name: string, - pkg: Package, + incomingPkg: Package, revision?: string, callback: Callback) { - if (!isObject(pkg.versions) || !isObject(pkg[DIST_TAGS])) { + if (!isObject(incomingPkg.versions) || !isObject(incomingPkg[DIST_TAGS])) { return callback( ErrorCode.getBadData()); } - 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}'); + this._updatePackage(name, (localData, cb) => { + for (let version in localData.versions) { + if (_.isNil(incomingPkg.versions[version])) { + this.logger.info( {name: name, version: version}, 'unpublishing @{name}@@{version}'); - delete jsonData.versions[ver]; - delete jsonData.time[ver]; + delete localData.versions[version]; + delete localData.time[version]; - for (let file in jsonData._attachments) { - if (jsonData._attachments[file].version === ver) { - delete jsonData._attachments[file].version; + for (let file in localData._attachments) { + if (localData._attachments[file].version === version) { + delete localData._attachments[file].version; } } } } - jsonData[DIST_TAGS] = pkg[DIST_TAGS]; + localData[DIST_TAGS] = incomingPkg[DIST_TAGS]; cb(); }, function(err) { if (err) { @@ -601,11 +601,11 @@ class LocalStorage implements IStorage { /** * Retrieve a wrapper that provide access to the package location. - * @param {Object} packageInfo package name. + * @param {Object} pkgName package name. * @return {Object} */ - _getLocalStorage(packageInfo: string): IPackageStorage { - return this.localData.getPackageStorage(packageInfo); + _getLocalStorage(pkgName: string): IPackageStorage { + return this.localData.getPackageStorage(pkgName); } /** @@ -667,21 +667,21 @@ class LocalStorage implements IStorage { /** * Retrieve either a previous created local package or a boilerplate. - * @param {*} name + * @param {*} pkgName * @param {*} callback * @return {Function} */ - _readCreatePackage(name: string, callback: Callback) { - const storage: any = this._getLocalStorage(name); + _readCreatePackage(pkgName: string, callback: Callback) { + const storage: any = this._getLocalStorage(pkgName); if (_.isNil(storage)) { - return this._createNewPackage(name, callback); + return this._createNewPackage(pkgName, callback); } - storage.readPackage(name, (err, data) => { + storage.readPackage(pkgName, (err, data) => { // TODO: race condition if (_.isNil(err) === false) { if (err.code === noSuchFile) { - data = generatePackageTemplate(name); + data = generatePackageTemplate(pkgName); } else { return callback(this._internalError(err, pkgFileName, 'error reading')); } diff --git a/test/lib/utils-test.js b/test/lib/utils-test.js new file mode 100644 index 000000000..63a32fe14 --- /dev/null +++ b/test/lib/utils-test.js @@ -0,0 +1,33 @@ +// @flow + +import type { Version } from "@verdaccio/types"; + +export function generateNewVersion( + pkgName: string, + version: string, + shashum: string = '238e7641e59508dc9c20eb4ad37a8aa57ab777b4'): Version { + // $FlowFixMe + return { + "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", + "_nodeVersion": "9.3.0", + "_npmUser": { + + }, + "dist": { + "integrity": "sha512-zVEqt1JUCOPsash9q4wMkJEDPD+QCx95TRhQII+JnoS31uBUKoZxhzvvUJCcLVy2CQG4QdwXARU7dYWPnrwhGg==", + "shasum": shashum, + "tarball": `http:\/\/localhost:4873\/${pkgName}\/-\/${pkgName}-${version}.tgz` + } + } +} diff --git a/test/unit/api/local-storage.spec.js b/test/unit/api/local-storage.spec.js index 71275a990..e95132bc3 100644 --- a/test/unit/api/local-storage.spec.js +++ b/test/unit/api/local-storage.spec.js @@ -8,11 +8,16 @@ import AppConfig from '../../../src/lib/config'; import configExample from '../partials/config/index'; import Logger, {setup} from '../../../src/lib/logger'; import {readFile} from '../../functional/lib/test.utils'; +import {generatePackageTemplate} from '../../../src/lib/storage-utils'; +import {generateNewVersion} from '../../lib/utils-test'; + const readMetadata = (fileName: string = 'metadata') => readFile(`../../unit/partials/${fileName}`); -import type {Config} from '@verdaccio/types'; +import type {Config, MergeTags} from '@verdaccio/types'; import type {IStorage} from '../../../types/index'; +import {API_ERROR, HTTP_STATUS} from '../../../src/lib/constants'; +import {DIST_TAGS} from '../../../src/lib/utils'; setup([]); @@ -22,8 +27,57 @@ describe('LocalStorage', () => { const pkgNameScoped = `@scope/${pkgName}-scope`; const tarballName: string = `${pkgName}-add-tarball-1.0.4.tgz`; const tarballName2: string = `${pkgName}-add-tarball-1.0.5.tgz`; + const getPackageMetadataFromStore = (pkgName: string) => { + return new Promise((resolve) => { + storage.getPackageMetadata(pkgName, (err, data ) => { + resolve(data); + }); + }); + }; - beforeAll(function () { + const addNewVersion = (pkgName: string, version: string) => { + return new Promise((resolve) => { + storage.addVersion(pkgName, version, generateNewVersion(pkgName, version), '', (err, data) => { + resolve(data); + }); + }); + }; + const addTarballToStore = (pkgName: string, tarballName) => { + return new Promise((resolve, reject) => { + const tarballData = JSON.parse(readMetadata('addTarball')); + const stream = storage.addTarball(pkgName, tarballName); + + stream.on('error', (err) => { + expect(err).toBeNull(); + reject(); + }); + stream.on('success', () => { + resolve(); + }); + + stream.end(new Buffer(tarballData.data, 'base64')); + stream.done(); + }); + }; + + const addPackageToStore = (pkgName, metadata) => { + return new Promise((resolve, reject) => { + // $FlowFixMe + const pkgStoragePath = storage._getLocalStorage(pkgName); + rimRaf(pkgStoragePath.path, (err) => { + expect(err).toBeNull(); + storage.addPackage(pkgName, metadata, async (err, data) => { + if (err) { + reject(err); + } + + resolve(data); + }); + }); + }); + }; + + beforeAll(() => { const config: Config = new AppConfig(configExample); config.self_path = path.join('../partials/store'); @@ -71,38 +125,124 @@ describe('LocalStorage', () => { storage.addPackage(pkgName, metadata, (err) => { expect(err).not.toBeNull(); - expect(err.statusCode).toEqual(409); - expect(err.message).toMatch(/this package is already present/); + expect(err.statusCode).toEqual(HTTP_STATUS.CONFLICT); + expect(err.message).toMatch(API_ERROR.PACKAGE_EXIST); done(); }); }); - describe('LocalStorage::addVersion', () => { - test('should add new version without tag', (done) => { - const metadata = JSON.parse(readMetadata('metadata-add-version')); + describe('LocalStorage::mergeTags', () => { + test('should mergeTags', async (done) => { + const pkgName = 'merge-tags-test-1'; + await addPackageToStore(pkgName, generatePackageTemplate(pkgName)); + await addNewVersion(pkgName, '1.0.0'); + await addNewVersion(pkgName, '2.0.0'); + await addNewVersion(pkgName, '3.0.0'); + const tags: MergeTags = { + beta: '3.0.0', + latest: '2.0.0' + }; - storage.addVersion(pkgName, '1.0.1', metadata, '', (err, data) => { + storage.mergeTags(pkgName, tags, async (err, data) => { + expect(err).toBeNull(); + expect(data).toBeUndefined(); + const metadata = await getPackageMetadataFromStore(pkgName); + expect(metadata[DIST_TAGS]).toBeDefined(); + expect(metadata[DIST_TAGS]['beta']).toBeDefined(); + expect(metadata[DIST_TAGS]['beta']).toBe('3.0.0'); + expect(metadata[DIST_TAGS]['latest']).toBe('2.0.0'); + done(); + }); + }); + + test('should fails mergeTags version not found', async (done) => { + const pkgName = 'merge-tags-test-1'; + await addPackageToStore(pkgName, generatePackageTemplate(pkgName)); + // const tarballName: string = `${pkgName}-${version}.tgz`; + await addNewVersion(pkgName, '1.0.0'); + await addNewVersion(pkgName, '2.0.0'); + await addNewVersion(pkgName, '3.0.0'); + const tags: MergeTags = { + beta: '9999.0.0' + }; + + storage.mergeTags(pkgName, tags, async (err, data) => { + expect(err).not.toBeNull(); + expect(err.statusCode).toEqual(HTTP_STATUS.NOT_FOUND); + expect(err.message).toMatch(API_ERROR.VERSION_NOT_EXIST); + done(); + }); + }); + + test('should fails on mergeTags', async (done) => { + const tags: MergeTags = { + beta: '3.0.0', + latest: '2.0.0' + }; + + storage.mergeTags('not-found', tags, async (err) => { + expect(err).not.toBeNull(); + expect(err.statusCode).toEqual(HTTP_STATUS.NOT_FOUND); + expect(err.message).toMatch(API_ERROR.NO_PACKAGE); + done(); + }); + }); + }); + + describe('LocalStorage::addVersion', () => { + test('should add new version without tag', async (done) => { + const pkgName = 'add-version-test-1'; + const version = '1.0.1'; + await addPackageToStore(pkgName, generatePackageTemplate(pkgName)); + const tarballName: string = `${pkgName}-${version}.tgz`; + await addNewVersion(pkgName, '9.0.0'); + await addTarballToStore(pkgName, `${pkgName}-9.0.0.tgz`); + await addTarballToStore(pkgName, tarballName); + + storage.addVersion(pkgName, version, generateNewVersion(pkgName, version), '', (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')); + test('should fails on add a duplicated version without tag', async (done) => { + const pkgName = 'add-version-test-2'; + const version = '1.0.1'; + await addPackageToStore(pkgName, generatePackageTemplate(pkgName)); + await addNewVersion(pkgName, version); - storage.addVersion(pkgName, '1.0.1', metadata, '', (err, data) => { + storage.addVersion(pkgName, version, generateNewVersion(pkgName, version), '', (err, data) => { expect(err).not.toBeNull(); - expect(err.statusCode).toEqual(409); - expect(err.message).toMatch(/this package is already present/); + expect(err.statusCode).toEqual(HTTP_STATUS.CONFLICT); + expect(err.message).toMatch(API_ERROR.PACKAGE_EXIST); done(); }); }); - test('should add new second version without tag', (done) => { - const metadata = JSON.parse(readMetadata('metadata-add-version')); + test('should fails add new version wrong shasum', async (done) => { + const pkgName = 'add-version-test-4'; + const version = '4.0.0'; + await addPackageToStore(pkgName, generatePackageTemplate(pkgName)); + const tarballName: string = `${pkgName}-${version}.tgz`; + await addTarballToStore(pkgName, tarballName); - storage.addVersion(pkgName, '1.0.2', metadata, 'beta', (err, data) => { + storage.addVersion(pkgName, version, generateNewVersion(pkgName, version, 'fake'), '', (err, data) => { + expect(err).not.toBeNull(); + expect(err.statusCode).toEqual(HTTP_STATUS.BAD_REQUEST); + expect(err.message).toMatch(/shasum error/); + done(); + }); + }); + + test('should add new second version without tag', async (done) => { + const pkgName = 'add-version-test-3'; + const version = '1.0.2'; + await addPackageToStore(pkgName, generatePackageTemplate(pkgName)); + await addNewVersion(pkgName, '1.0.1'); + await addNewVersion(pkgName, '1.0.3'); + + storage.addVersion(pkgName, version, generateNewVersion(pkgName, version), 'beta', (err, data) => { expect(err).toBeNull(); expect(data).toBeUndefined(); done(); @@ -111,25 +251,52 @@ describe('LocalStorage', () => { }); describe('LocalStorage::updateVersions', () => { - test('should update versions from origin', (done) => { + test('should update versions from external source', async (done) => { const metadata = JSON.parse(readMetadata('metadata-update-versions-tags')); + const pkgName = 'add-update-versions-test-1'; + const version = '1.0.2'; + await addPackageToStore(pkgName, generatePackageTemplate(pkgName)); + await addNewVersion(pkgName, '1.0.1'); + await addNewVersion(pkgName, version); storage.updateVersions(pkgName, metadata, (err, data) => { expect(err).toBeNull(); - expect(data.versions['1.0.3']).toBeDefined(); + expect(data.versions['1.0.1']).toBeDefined(); + expect(data.versions[version]).toBeDefined(); + expect(data.versions['1.0.4']).toBeDefined(); + expect(data[DIST_TAGS]['latest']).toBeDefined(); + expect(data[DIST_TAGS]['latest']).toBe('1.0.1'); + expect(data[DIST_TAGS]['beta']).toBeDefined(); + expect(data[DIST_TAGS]['beta']).toBe('1.0.2'); + expect(data[DIST_TAGS]['next']).toBeDefined(); + expect(data[DIST_TAGS]['next']).toBe('1.0.4'); + expect(data['_rev'] === metadata['_rev']).toBeFalsy(); + expect(data.readme).toBe('readme 1.0.4'); done(); }); }); }); describe('LocalStorage::changePackage', () => { - test('should unpublish a version', (done) => { - const metadata = JSON.parse(readMetadata('metadata-unpublish')); + const pkgName: string = 'change-package'; + + test('should unpublish a version', async done => { + await addPackageToStore(pkgName, generatePackageTemplate(pkgName)); + await addNewVersion(pkgName, '1.0.1'); + await addNewVersion(pkgName, '1.0.2'); + await addNewVersion(pkgName, '1.0.3'); + const metadata = JSON.parse(readMetadata('changePackage/metadata-change')); const rev: string = metadata['_rev']; storage.changePackage(pkgName, metadata, rev, (err) => { expect(err).toBeUndefined(); - done(); + storage.getPackageMetadata(pkgName, (err, data ) => { + expect(err).toBeNull(); + expect(data.versions['1.0.1']).toBeDefined(); + expect(data.versions['1.0.2']).toBeUndefined(); + expect(data.versions['1.0.3']).toBeUndefined(); + done(); + }); }); }); }); @@ -142,7 +309,7 @@ describe('LocalStorage', () => { const tarballData = JSON.parse(readMetadata('addTarball')); const stream = storage.addTarball(pkgName, tarballName); - stream.on('error', function(err) { + stream.on('error', (err) => { expect(err).toBeNull(); done(); }); @@ -157,7 +324,7 @@ describe('LocalStorage', () => { test('should add a new second tarball', (done) => { const tarballData = JSON.parse(readMetadata('addTarball')); const stream = storage.addTarball(pkgName, tarballName2); - stream.on('error', function(err) { + stream.on('error', (err) => { expect(err).toBeNull(); done(); }); @@ -172,9 +339,9 @@ describe('LocalStorage', () => { test('should fails on add a duplicated new tarball ', (done) => { const tarballData = JSON.parse(readMetadata('addTarball')); const stream = storage.addTarball(pkgName, tarballName); - stream.on('error', function(err) { + stream.on('error', (err) => { expect(err).not.toBeNull(); - expect(err.statusCode).toEqual(409); + expect(err.statusCode).toEqual(HTTP_STATUS.CONFLICT); expect(err.message).toMatch(/this package is already present/); done(); }); @@ -190,14 +357,14 @@ describe('LocalStorage', () => { test('should fails on add a new tarball on missing package', (done) => { const tarballData = JSON.parse(readMetadata('addTarball')); const stream = storage.addTarball('unexsiting-package', tarballName); - stream.on('error', function(err) { + stream.on('error', (err) => { expect(err).not.toBeNull(); expect(err.statusCode).toEqual(404); expect(err.message).toMatch(/no such package available/); done(); }); - stream.on('success', function() { + stream.on('success', () => { done(); }); @@ -209,7 +376,7 @@ describe('LocalStorage', () => { 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.statusCode).toEqual(HTTP_STATUS.BAD_DATA); expect(err.message).toMatch(/refusing to accept zero-length file/); done(); }); @@ -222,7 +389,7 @@ describe('LocalStorage', () => { stream.abort(); stream.on('error', function(err) { expect(err).not.toBeNull(); - expect(err.statusCode).toEqual(403); + expect(err.statusCode).toEqual(HTTP_STATUS.FORBIDDEN); expect(err.message).toMatch(/can't use this filename/); done(); }); @@ -243,7 +410,7 @@ describe('LocalStorage', () => { test('should remove a tarball that does not exist', (done) => { storage.removeTarball(pkgName, tarballName2, 'rev', (err) => { expect(err).not.toBeNull(); - expect(err.statusCode).toEqual(404); + expect(err.statusCode).toEqual(HTTP_STATUS.NOT_FOUND); expect(err.message).toMatch(/no such file available/); done(); }); @@ -268,7 +435,7 @@ describe('LocalStorage', () => { const stream = storage.getTarball('fake', tarballName); stream.on('error', function(err) { expect(err).not.toBeNull(); - expect(err.statusCode).toEqual(404); + expect(err.statusCode).toEqual(HTTP_STATUS.NOT_FOUND); expect(err.message).toMatch(/no such file available/); done(); }); @@ -325,7 +492,7 @@ describe('LocalStorage', () => { test('should fails with @scoped package not found', (done) => { storage.removePackage(pkgNameScoped, (err, data) => { expect(err).not.toBeNull(); - expect(err.message).toMatch(/no such package available/); + expect(err.message).toMatch(API_ERROR.NO_PACKAGE); done(); }); }); diff --git a/test/unit/partials/metadata-unpublish b/test/unit/partials/changePackage/metadata-change similarity index 83% rename from test/unit/partials/metadata-unpublish rename to test/unit/partials/changePackage/metadata-change index f4fbc36fe..e932f9142 100644 --- a/test/unit/partials/metadata-unpublish +++ b/test/unit/partials/changePackage/metadata-change @@ -1,8 +1,8 @@ { - "name": "npm_test", + "name": "change-package", "versions": { "1.0.1": { - "name": "npm_test", + "name": "change-package", "version": "1.0.1", "description": "", "main": "index.js", @@ -20,7 +20,7 @@ ], "author": "", "license": "ISC", - "_id": "npm_test@1.0.0", + "_id": "change-package@1.0.0", "_npmVersion": "5.5.1", "_nodeVersion": "9.3.0", "_npmUser": { @@ -29,7 +29,7 @@ "dist": { "integrity": "sha512-tfzM1OFjWwg2d2Wke\/DV6icjeTZUVOZYLkbf8wmONRSAgMovL\/F+zyI24OhTtWyOXd1Kbj2YUMBvLpmpAjv8zg==", "shasum": "3e4e6bd5097b295e520b947c9be3259a9509a673", - "tarball": "http:\/\/localhost:4873\/npm_test\/-\/npm_test-1.0.1.tgz" + "tarball": "http:\/\/localhost:4873\/change-package\/-\/change-package-1.0.1.tgz" } } }, diff --git a/test/unit/partials/metadata-add-version b/test/unit/partials/metadata-add-version deleted file mode 100644 index 92fd10aaa..000000000 --- a/test/unit/partials/metadata-add-version +++ /dev/null @@ -1,32 +0,0 @@ -{ - "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" - } -} diff --git a/test/unit/partials/metadata-update-versions-tags b/test/unit/partials/metadata-update-versions-tags index e8791b893..4679888fc 100644 --- a/test/unit/partials/metadata-update-versions-tags +++ b/test/unit/partials/metadata-update-versions-tags @@ -1,8 +1,8 @@ { - "name": "npm_test", + "name": "add-update-versions-test-1", "versions": { "1.0.1": { - "name": "npm_test", + "name": "add-update-versions-test-1", "version": "1.0.1", "description": "", "main": "index.js", @@ -16,18 +16,18 @@ "keywords": [], "author": "", "license": "ISC", - "_id": "npm_test@1.0.1", + "_id": "add-update-versions-test-1@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" + "shasum": "238e7641e59508dc9c20eb4ad37a8aa57ab777b4", + "tarball": "http://localhost:4873/add-update-versions-test-1/-/add-update-versions-test-1-1.0.1.tgz" } }, "1.0.2": { - "name": "npm_test", + "name": "add-update-versions-test-1", "version": "1.0.1", "description": "", "main": "index.js", @@ -41,19 +41,19 @@ "keywords": [], "author": "", "license": "ISC", - "_id": "npm_test@1.0.1", + "_id": "add-update-versions-test-1@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" + "shasum": "238e7641e59508dc9c20eb4ad37a8aa57ab777b4", + "tarball": "http://localhost:4873/add-update-versions-test-1/-/add-update-versions-test-1-1.0.1.tgz" } }, - "1.0.3": { - "name": "npm_test", - "version": "1.0.3", + "1.0.4": { + "name": "add-update-versions-test-1", + "version": "1.0.4", "description": "", "main": "index.js", "dependencies": { @@ -66,26 +66,26 @@ "keywords": [], "author": "", "license": "ISC", - "_id": "npm_test@1.0.1", + "_id": "add-update-versions-test-1@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" + "shasum": "238e7641e59508dc9c20eb4ad37a8aa57ab777b4", + "tarball": "http://localhost:4873/add-update-versions-test-1/-/add-update-versions-test-1-1.0.1.tgz" } } }, "dist-tags": { "latest": "1.0.1", "beta": "1.0.2", - "next": "1.0.3" + "next": "1.0.4" }, "time": {}, "_distfiles": {}, "_attachments": {}, "_uplinks": {}, "_rev": "2-b8a00ec71cdc7323", - "readme": "ERROR: No README data found!" + "readme": "readme 1.0.4" }