From b5ac3c0f287b8d9ae9121a47d6ac9d27e2bd4ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B4=BE=E9=A1=BA=E5=90=8D=28Jarvis=29?= Date: Thu, 16 Dec 2021 23:17:52 +0800 Subject: [PATCH] fix: publish with deprecated field (#2771) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: publish with deprecated field by @Jiasm When publish with deprecated field in `package.json`, that will make all old versions miss. Examples: I have package@1.0.0 and package@1.0.1. When `npm deprecate package@1.0.0 "xxx"`, Verdaccio will recived: ```json { "name": "module_name", "version": { "1.0.0": { "deprecated": "xxx" }, "1.0.1": {} } } ``` ⬆️ This make sense But then publish new version with @1.0.2. Verdaccio will recived: ```json { "name": "module_name", "version": { "1.0.2": { "deprecated": "xxx" // if we set this field in package.json }, } } ``` and that metadata will override package.json, make old version miss. migrate from #2766 * remove spaces * fix: ignore empty package case * fix: cover normal unpublish case * refactor: Optimize check logic for lazy execution * test: upgrade Jest Snapshot * fix: set storage.getPackage `uplinksLook: false`. * feat: use `_attachments` to distinguish deprecate * test: rollback test snapshots * test: rollback jest snapshots * test: publish new version with deprecate field * test: remove space --- src/api/endpoint/api/publish.ts | 4 ++-- test/unit/modules/api/api.spec.ts | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/api/endpoint/api/publish.ts b/src/api/endpoint/api/publish.ts index b41bff5c5..f88071298 100644 --- a/src/api/endpoint/api/publish.ts +++ b/src/api/endpoint/api/publish.ts @@ -216,8 +216,8 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I try { const metadata = validateMetadata(req.body, packageName); - // treating deprecation as updating a package - if (req.params._rev || isRelatedToDeprecation(req.body)) { + // check _attachments to distinguish publish and deprecate + if (req.params._rev || (isRelatedToDeprecation(req.body) && _.isEmpty(req.body._attachments))) { debug('updating a new version for %o', packageName); // we check unpublish permissions, an update is basically remove versions const remote = req.remote_user; diff --git a/test/unit/modules/api/api.spec.ts b/test/unit/modules/api/api.spec.ts index bd47a7b74..6037689be 100644 --- a/test/unit/modules/api/api.spec.ts +++ b/test/unit/modules/api/api.spec.ts @@ -1073,6 +1073,28 @@ describe('endpoint unit test', () => { expect(res.body.versions['1.0.1'].deprecated).toEqual('get deprecated'); done(); }); + + test('should deprecate when publish new version with deprecate field', async (done) => { + await Promise.all([ + putPackage(request(app), `/${pkgName}`, generatePackageMetadata(pkgName, '2.0.0'), token), + putPackage(request(app), `/${pkgName}`, generatePackageMetadata(pkgName, '2.0.1'), token), + putPackage(request(app), `/${pkgName}`, generatePackageMetadata(pkgName, '2.0.2'), token) + ]); + + const pkg = generatePackageMetadata(pkgName, '2.0.3'); + pkg.versions['2.0.3'].deprecated = 'get deprecated'; + await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, pkg, token); + + const [, res] = await getPackage(request(app), '', pkgName); + const versions = Object.keys(res.body.versions); + + expect(res.body.versions['2.0.3'].deprecated).toEqual('get deprecated'); + expect(versions).toContain('2.0.0'); + expect(versions).toContain('2.0.1'); + expect(versions).toContain('2.0.2'); + expect(versions).toContain('2.0.3'); + done(); + }); }); }); });