1
0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-12-24 21:15:51 +01:00

feat: keep_readmes option when publishing packages (#4961)

This commit is contained in:
Marc Bernard 2024-11-28 05:54:51 -05:00 committed by GitHub
parent 3967a5280a
commit 538bb8f3a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 101 additions and 14 deletions

@ -0,0 +1,6 @@
---
'@verdaccio/types': patch
'@verdaccio/store': patch
---
feat: keep_readmes option when publishing packages

@ -202,8 +202,11 @@ export interface Security {
api: APITokenOptions;
}
export type ReadmeOptions = 'latest' | 'tagged' | 'all' | undefined;
export interface PublishOptions {
allow_offline: boolean;
keep_readmes: ReadmeOptions;
check_owners: boolean;
}

@ -3,7 +3,14 @@ import semver from 'semver';
import { errorUtils, pkgUtils, searchUtils, validatioUtils } from '@verdaccio/core';
import { API_ERROR, DIST_TAGS, HTTP_STATUS, MAINTAINERS, USERS } from '@verdaccio/core';
import { AttachMents, Manifest, Version, Versions } from '@verdaccio/types';
import {
AttachMents,
GenericBody,
Manifest,
ReadmeOptions,
Version,
Versions,
} from '@verdaccio/types';
import { generateRandomHexString, isNil, isObject } from '@verdaccio/utils';
import { sortVersionsAndFilterInvalid } from './versions-utils';
@ -92,10 +99,28 @@ export function getLatestReadme(pkg: Manifest): string {
return readme;
}
// FIXME: type any due this
export function cleanUpReadme(version: any): Version {
/**
* Cleanup readme from package version
*
* By default, we don't keep readmes for package versions, only one readme per package.
* Using publish.keep_readmes you can override this behavior and keep all readmes
* or only readmes for tagged versions.
*/
export function cleanUpReadme(
version: Version,
distTags?: GenericBody,
keepReadmes?: ReadmeOptions
): Version {
if (keepReadmes === 'all') {
return version;
} else if (keepReadmes === 'tagged') {
if (distTags && Object.values(distTags).includes(version.version)) {
return version;
}
}
if (isNil(version) === false) {
delete version.readme;
version.readme = '';
}
return version;

@ -1404,11 +1404,11 @@ class Storage {
): Promise<void> {
debug(`add version %s package for %s`, version, name);
await this.updatePackage(name, async (data: Manifest): Promise<Manifest> => {
// keep only one readme per package
// keep latest readme in manifest (on root level)
data.readme = metadata.readme;
debug('%s readme mutated', name);
// TODO: lodash remove
metadata = cleanUpReadme(metadata);
// removing other readmes depends on config
metadata = cleanUpReadme(metadata, metadata[DIST_TAGS], this.config?.publish?.keep_readmes);
metadata.contributors = normalizeContributors(metadata.contributors as Author[]);
debug('%s contributors normalized', name);
@ -1966,10 +1966,12 @@ class Storage {
debug('new version from upstream %o', versionId);
let version = remoteManifest.versions[versionId];
// we don't keep readme for package versions,
// only one readme per package
// TODO: readme clean up could be saved in configured eventually
version = cleanUpReadme(version);
// removing readmes depends on config
version = cleanUpReadme(
version,
remoteManifest[DIST_TAGS],
this.config?.publish?.keep_readmes
);
debug('clean up readme for %o', versionId);
version.contributors = normalizeContributors(version.contributors as Author[]);

@ -1,11 +1,12 @@
import { describe, expect, test } from 'vitest';
import { DIST_TAGS } from '@verdaccio/core';
import { generatePackageMetadata } from '@verdaccio/test-helper';
import { Manifest } from '@verdaccio/types';
import { generatePackageMetadata } from '../../api/node_modules/@verdaccio/test-helper/build';
import {
STORAGE,
cleanUpReadme,
hasInvalidPublishBody,
isDeprecatedManifest,
isDifferentThanOne,
@ -356,4 +357,54 @@ describe('Storage Utils', () => {
).toBeTruthy();
});
});
describe('cleanUpReadme', () => {
describe('should keep only latest readme', () => {
test('should clean up readme (no dist-tags)', () => {
const manifest = generatePackageMetadata('foo');
const version = manifest.versions['1.0.0'];
const cleanup = cleanUpReadme(version);
expect(cleanup.readme).toEqual('');
});
test('should clean up readme (latest in dist-tag)', () => {
const manifest = generatePackageMetadata('foo');
const version = manifest.versions['1.0.0'];
const cleanup = cleanUpReadme(version, manifest[DIST_TAGS]);
expect(cleanup.readme).toEqual('');
});
});
describe('should keep only tagged readme', () => {
test('should clean up readme (no dist-tags)', () => {
const manifest = generatePackageMetadata('foo');
const version = manifest.versions['1.0.0'];
const cleanup = cleanUpReadme(version, undefined, 'tagged');
expect(cleanup.readme).toEqual('');
});
test('should keep readme (version in dist-tag)', () => {
const manifest = generatePackageMetadata('foo');
const version = manifest.versions['1.0.0'];
const cleanup = cleanUpReadme(version, manifest[DIST_TAGS], 'tagged');
expect(cleanup.readme).toEqual('# test');
});
});
describe('should keep all readmes', () => {
test('should keep readme (no dist-tags)', () => {
const manifest = generatePackageMetadata('foo');
const version = manifest.versions['1.0.0'];
const cleanup = cleanUpReadme(version, undefined, 'all');
expect(cleanup.readme).toEqual('# test');
});
test('should keep readme (version in dist-tag)', () => {
const manifest = generatePackageMetadata('foo');
const version = manifest.versions['1.0.0'];
const cleanup = cleanUpReadme(version, manifest[DIST_TAGS], 'all');
expect(cleanup.readme).toEqual('# test');
});
});
});
});

@ -176,7 +176,7 @@ describe('storage', () => {
});
expect(manifest[DIST_TAGS]).toEqual({ latest: '1.0.0' });
// verdaccio keeps latest version of readme on manifest level but not by version
expect(manifest.versions['1.0.0'].readme).not.toBeDefined();
expect(manifest.versions['1.0.0'].readme).toEqual('');
expect(manifest.readme).toEqual('# test');
expect(manifest._attachments).toEqual({});
expect(typeof manifest._rev).toBeTruthy();
@ -388,7 +388,7 @@ describe('storage', () => {
})) as Manifest;
// verdaccio keeps latest version of readme on manifest level but not by version
expect(manifest.versions['1.0.0'].readme).not.toBeDefined();
expect(manifest.versions['1.0.0'].readme).toEqual('');
expect(manifest.readme).toEqual('# test');
});
});