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

feat: migrate sidebar to fastify (#2618)

This commit is contained in:
Diana Morales 2021-11-03 20:56:36 +01:00 committed by GitHub
parent 076f0f85e8
commit f86c31ed0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 416 additions and 327 deletions

@ -0,0 +1,11 @@
---
'@verdaccio/fastify-migration': minor
'@verdaccio/store': minor
'@verdaccio/utils': minor
'@verdaccio/web': minor
'@verdaccio/website': minor
---
feat: migrate web sidebar endpoint to fastify
reuse utils methods between packages

@ -0,0 +1,68 @@
import buildDebug from 'debug';
import { FastifyInstance } from 'fastify';
import _ from 'lodash';
import { DIST_TAGS } from '@verdaccio/core';
import { convertDistRemoteToLocalTarballUrls } from '@verdaccio/tarball';
import { Package, Version } from '@verdaccio/types';
import {
addGravatarSupport,
deleteProperties,
formatAuthor,
isVersionValid,
} from '@verdaccio/utils';
const debug = buildDebug('verdaccio:web:api:sidebar');
export type $SidebarPackage = Package & { latest: Version };
async function sidebarRoute(fastify: FastifyInstance) {
fastify.get('/sidebar/(@:scope/)?:packageName', async (request, reply) => {
// @ts-ignore
const { packageName, scope } = request.params;
debug('pkg name %s, scope %s ', packageName, scope);
getSidebar(fastify, request, packageName, (err, sidebar) => {
if (err) {
reply.send(err);
} else {
reply.code(fastify.statusCode.OK).send(sidebar);
}
});
});
}
function getSidebar(fastify: FastifyInstance, request: any, packageName, callback) {
fastify.storage.getPackage({
name: packageName,
uplinksLook: true,
keepUpLinkData: true,
req: request.raw,
callback: function (err: Error, info: $SidebarPackage): void {
debug('sidebar pkg info %o', info);
if (_.isNil(err)) {
const { v } = request.query;
let sideBarInfo = _.clone(info);
sideBarInfo.versions = convertDistRemoteToLocalTarballUrls(
info,
{ protocol: request.protocol, headers: request.headers as any, host: request.hostname },
fastify.configInstance.url_prefix
).versions;
if (typeof v === 'string' && isVersionValid(info, v)) {
sideBarInfo.latest = sideBarInfo.versions[v];
sideBarInfo.latest.author = formatAuthor(sideBarInfo.latest.author);
} else {
sideBarInfo.latest = sideBarInfo.versions[info[DIST_TAGS].latest];
sideBarInfo.latest.author = formatAuthor(sideBarInfo.latest.author);
}
sideBarInfo = deleteProperties(['readme', '_attachments', '_rev', 'name'], sideBarInfo);
const authorAvatar = fastify.configInstance.web
? addGravatarSupport(sideBarInfo, fastify.configInstance.web.gravatar)
: addGravatarSupport(sideBarInfo);
callback(null, authorAvatar);
} else {
callback(fastify.statusCode.NOT_FOUND).send(err);
}
},
});
}
export default sidebarRoute;

@ -14,6 +14,7 @@ import configPlugin from './plugins/config';
import coreUtils from './plugins/coreUtils'; import coreUtils from './plugins/coreUtils';
import storagePlugin from './plugins/storage'; import storagePlugin from './plugins/storage';
import readme from './routes/web/api/readme'; import readme from './routes/web/api/readme';
import sidebar from './routes/web/api/sidebar';
const debug = buildDebug('verdaccio:fastify'); const debug = buildDebug('verdaccio:fastify');
@ -36,6 +37,7 @@ async function startServer({ logger, config }) {
instance.register(whoami); instance.register(whoami);
instance.register(tarball); instance.register(tarball);
instance.register(readme, { prefix: '/-/verdaccio' }); instance.register(readme, { prefix: '/-/verdaccio' });
instance.register(sidebar, { prefix: '/-/verdaccio' });
done(); done();
}); });

@ -29,7 +29,7 @@ import {
Version, Version,
} from '@verdaccio/types'; } from '@verdaccio/types';
import { getLatestVersion, isObject } from '@verdaccio/utils'; import { getLatestVersion, isObject } from '@verdaccio/utils';
import { createTarballHash } from '@verdaccio/utils'; import { createTarballHash, normalizeContributors } from '@verdaccio/utils';
import { import {
STORAGE, STORAGE,
@ -37,7 +37,6 @@ import {
generatePackageTemplate, generatePackageTemplate,
generateRevision, generateRevision,
getLatestReadme, getLatestReadme,
normalizeContributors,
normalizePackage, normalizePackage,
tagVersion, tagVersion,
} from './storage-utils'; } from './storage-utils';

@ -3,7 +3,7 @@ import semver from 'semver';
import { errorUtils, pkgUtils, validatioUtils } from '@verdaccio/core'; import { errorUtils, pkgUtils, validatioUtils } from '@verdaccio/core';
import { API_ERROR, DIST_TAGS, HTTP_STATUS, USERS } from '@verdaccio/core'; import { API_ERROR, DIST_TAGS, HTTP_STATUS, USERS } from '@verdaccio/core';
import { Author, Package, StringValue, Version } from '@verdaccio/types'; import { Package, StringValue, Version } from '@verdaccio/types';
import { generateRandomHexString, isNil, normalizeDistTags } from '@verdaccio/utils'; import { generateRandomHexString, isNil, normalizeDistTags } from '@verdaccio/utils';
import { LocalStorage } from './local-storage'; import { LocalStorage } from './local-storage';
@ -98,24 +98,6 @@ export function cleanUpReadme(version: any): Version {
return version; return version;
} }
export function normalizeContributors(contributors: Author[]): Author[] {
if (isNil(contributors)) {
return [];
} else if (contributors && _.isArray(contributors) === false) {
// FIXME: this branch is clearly no an array, still tsc complains
// @ts-ignore
return [contributors];
} else if (_.isString(contributors)) {
return [
{
name: contributors,
},
];
}
return contributors;
}
export const WHITELIST = [ export const WHITELIST = [
'_rev', '_rev',
'name', 'name',

@ -5,6 +5,9 @@ import semver from 'semver';
import { DEFAULT_USER, DIST_TAGS } from '@verdaccio/core'; import { DEFAULT_USER, DIST_TAGS } from '@verdaccio/core';
import { Author, Package, Version } from '@verdaccio/types'; import { Author, Package, Version } from '@verdaccio/types';
import { stringToMD5 } from './crypto-utils';
export type AuthorAvatar = Author & { avatar?: string };
/** /**
* From normalize-package-data/lib/fixer.js * From normalize-package-data/lib/fixer.js
* @param {*} name the package name * @param {*} name the package name
@ -253,3 +256,111 @@ export function isVersionValid(packageMeta, packageVersion): boolean {
const hasMatchVersion = Object.keys(packageMeta.versions).includes(packageVersion); const hasMatchVersion = Object.keys(packageMeta.versions).includes(packageVersion);
return hasMatchVersion; return hasMatchVersion;
} }
export function addGravatarSupport(pkgInfo: Package, online = true): AuthorAvatar {
const pkgInfoCopy = { ...pkgInfo } as any;
const author: any = _.get(pkgInfo, 'latest.author', null) as any;
const contributors: AuthorAvatar[] = normalizeContributors(
_.get(pkgInfo, 'latest.contributors', [])
);
const maintainers = _.get(pkgInfo, 'latest.maintainers', []);
// for author.
if (author && _.isObject(author)) {
const { email } = author as Author;
pkgInfoCopy.latest.author.avatar = generateGravatarUrl(email, online);
}
if (author && _.isString(author)) {
pkgInfoCopy.latest.author = {
avatar: GENERIC_AVATAR,
email: '',
author,
};
}
// for contributors
if (_.isEmpty(contributors) === false) {
pkgInfoCopy.latest.contributors = contributors.map((contributor): AuthorAvatar => {
if (isObject(contributor)) {
contributor.avatar = generateGravatarUrl(contributor.email, online);
} else if (_.isString(contributor)) {
contributor = {
avatar: GENERIC_AVATAR,
email: contributor,
name: contributor,
};
}
return contributor;
});
}
// for maintainers
if (_.isEmpty(maintainers) === false) {
pkgInfoCopy.latest.maintainers = maintainers.map((maintainer): void => {
maintainer.avatar = generateGravatarUrl(maintainer.email, online);
return maintainer;
});
}
return pkgInfoCopy;
}
const AVATAR_PROVIDER = 'https://www.gravatar.com/avatar/';
export const GENERIC_AVATAR =
'data:image/svg+xml;utf8,' +
encodeURIComponent(
'<svg height="100" viewBox="-27 24 100 100" width="100" xmlns="http://www.w3.org/' +
'2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><circle cx="23" cy="7' +
'4" id="a" r="50"/></defs><use fill="#F5EEE5" overflow="visible" xlink:href="#a"/' +
'><clipPath id="b"><use overflow="visible" xlink:href="#a"/></clipPath><g clip-pa' +
'th="url(#b)"><defs><path d="M36 95.9c0 4 4.7 5.2 7.1 5.8 7.6 2 22.8 5.9 22.8 5.9' +
' 3.2 1.1 5.7 3.5 7.1 6.6v9.8H-27v-9.8c1.3-3.1 3.9-5.5 7.1-6.6 0 0 15.2-3.9 22.8-' +
'5.9 2.4-.6 7.1-1.8 7.1-5.8V85h26v10.9z" id="c"/></defs><use fill="#E6C19C" overf' +
'low="visible" xlink:href="#c"/><clipPath id="d"><use overflow="visible" xlink:hr' +
'ef="#c"/></clipPath><path clip-path="url(#d)" d="M23.2 35h.2c3.3 0 8.2.2 11.4 2 ' +
'3.3 1.9 7.3 5.6 8.5 12.1 2.4 13.7-2.1 35.4-6.3 42.4-4 6.7-9.8 9.2-13.5 9.4H23h-.' +
'1c-3.7-.2-9.5-2.7-13.5-9.4-4.2-7-8.7-28.7-6.3-42.4 1.2-6.5 5.2-10.2 8.5-12.1 3.2' +
'-1.8 8.1-2 11.4-2h.2z" fill="#D4B08C"/></g><path d="M22.6 40c19.1 0 20.7 13.8 20' +
'.8 15.1 1.1 11.9-3 28.1-6.8 33.7-4 5.9-9.8 8.1-13.5 8.3h-.5c-3.8-.3-9.6-2.5-13.6' +
'-8.4-3.8-5.6-7.9-21.8-6.8-33.8C2.3 53.7 3.5 40 22.6 40z" fill="#F2CEA5"/></svg>'
);
/**
* Generate gravatar url from email address
*/
export function generateGravatarUrl(email: string | void = '', online: boolean = true): string {
if (online && _.isString(email) && _.size(email) > 0) {
email = email.trim().toLocaleLowerCase();
const emailMD5 = stringToMD5(email);
return `${AVATAR_PROVIDER}${emailMD5}`;
}
return GENERIC_AVATAR;
}
export function normalizeContributors(contributors: Author[]): Author[] {
if (_.isNil(contributors)) {
return [];
} else if (contributors && _.isArray(contributors) === false) {
// FIXME: this branch is clearly no an array, still tsc complains
// @ts-ignore
return [contributors];
} else if (_.isString(contributors)) {
return [
{
name: contributors,
},
];
}
return contributors;
}
export function deleteProperties(propertiesToDelete: string[], objectItem: any): any {
_.forEach(propertiesToDelete, (property): any => {
delete objectItem[property];
});
return objectItem;
}

@ -1,6 +1,14 @@
import { DEFAULT_USER, DIST_TAGS } from '@verdaccio/core'; import { DEFAULT_USER, DIST_TAGS } from '@verdaccio/core';
import { formatAuthor, getVersion, normalizeDistTags, validateMetadata } from '../src/index'; import {
GENERIC_AVATAR,
addGravatarSupport,
formatAuthor,
generateGravatarUrl,
getVersion,
normalizeDistTags,
validateMetadata,
} from '../src/index';
describe('Utilities', () => { describe('Utilities', () => {
const metadata: any = { const metadata: any = {
@ -131,5 +139,212 @@ describe('Utilities', () => {
expect(formatAuthor([]).name).toEqual(DEFAULT_USER); expect(formatAuthor([]).name).toEqual(DEFAULT_USER);
}); });
}); });
describe('User utilities', () => {
test('should generate gravatar url with email', () => {
const gravatarUrl: string = generateGravatarUrl('user@verdaccio.org');
expect(gravatarUrl).toMatch('https://www.gravatar.com/avatar/');
expect(gravatarUrl).not.toMatch('000000000');
});
test('should generate generic gravatar url', () => {
const gravatarUrl: string = generateGravatarUrl();
expect(gravatarUrl).toMatch(GENERIC_AVATAR);
});
});
describe('addGravatarSupport', () => {
test('check for blank object', () => {
// @ts-ignore
expect(addGravatarSupport({})).toEqual({});
});
test('author, contributors and maintainers fields are not present', () => {
const packageInfo = {
latest: {},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(packageInfo);
});
test('author field is a blank object', () => {
const packageInfo = { latest: { author: {} } };
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(packageInfo);
});
test('author field is a string type', () => {
const packageInfo = {
latest: { author: 'user@verdccio.org' },
};
const result = {
latest: {
author: {
author: 'user@verdccio.org',
avatar: GENERIC_AVATAR,
email: '',
},
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(result);
});
test('author field is an object type with author information', () => {
const packageInfo = {
latest: { author: { name: 'verdaccio', email: 'user@verdccio.org' } },
};
const result = {
latest: {
author: {
avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7',
email: 'user@verdccio.org',
name: 'verdaccio',
},
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(result);
});
test('contributor field is a blank array', () => {
const packageInfo = {
latest: {
contributors: [],
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(packageInfo);
});
describe('contributors', () => {
test('contributors field has contributors', () => {
const packageInfo = {
latest: {
contributors: [
{ name: 'user', email: 'user@verdccio.org' },
{ name: 'user1', email: 'user1@verdccio.org' },
],
},
};
const result = {
latest: {
contributors: [
{
avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7',
email: 'user@verdccio.org',
name: 'user',
},
{
avatar: 'https://www.gravatar.com/avatar/51105a49ce4a9c2bfabf0f6a2cba3762',
email: 'user1@verdccio.org',
name: 'user1',
},
],
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(result);
});
test('contributors field is an object', () => {
const packageInfo = {
latest: {
contributors: { name: 'user', email: 'user@verdccio.org' },
},
};
const result = {
latest: {
contributors: [
{
avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7',
email: 'user@verdccio.org',
name: 'user',
},
],
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(result);
});
test('contributors field is a string', () => {
const contributor = 'Barney Rubble <b@rubble.com> (http://barnyrubble.tumblr.com/)';
const packageInfo = {
latest: {
contributors: contributor,
},
};
const result = {
latest: {
contributors: [
{
avatar: GENERIC_AVATAR,
email: contributor,
name: contributor,
},
],
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(result);
});
});
test('maintainers field is a blank array', () => {
const packageInfo = {
latest: {
maintainers: [],
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(packageInfo);
});
test('maintainers field has maintainers', () => {
const packageInfo = {
latest: {
maintainers: [
{ name: 'user', email: 'user@verdccio.org' },
{ name: 'user1', email: 'user1@verdccio.org' },
],
},
};
const result = {
latest: {
maintainers: [
{
avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7',
email: 'user@verdccio.org',
name: 'user',
},
{
avatar: 'https://www.gravatar.com/avatar/51105a49ce4a9c2bfabf0f6a2cba3762',
email: 'user1@verdccio.org',
name: 'user1',
},
],
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(result);
});
});
}); });
}); });

@ -8,9 +8,8 @@ import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '@verdaccio/mi
import { Storage } from '@verdaccio/store'; import { Storage } from '@verdaccio/store';
import { getLocalRegistryTarballUri } from '@verdaccio/tarball'; import { getLocalRegistryTarballUri } from '@verdaccio/tarball';
import { Config, Package, RemoteUser } from '@verdaccio/types'; import { Config, Package, RemoteUser } from '@verdaccio/types';
import { formatAuthor } from '@verdaccio/utils'; import { formatAuthor, generateGravatarUrl } from '@verdaccio/utils';
import { generateGravatarUrl } from '../utils/user';
import { AuthorAvatar, sortByName } from '../utils/web-utils'; import { AuthorAvatar, sortByName } from '../utils/web-utils';
export { $RequestExtend, $ResponseExtend, $NextFunctionVer }; // Was required by other packages export { $RequestExtend, $ResponseExtend, $NextFunctionVer }; // Was required by other packages

@ -8,9 +8,9 @@ import { $NextFunctionVer, $RequestExtend, $ResponseExtend, allow } from '@verda
import { Storage } from '@verdaccio/store'; import { Storage } from '@verdaccio/store';
import { convertDistRemoteToLocalTarballUrls } from '@verdaccio/tarball'; import { convertDistRemoteToLocalTarballUrls } from '@verdaccio/tarball';
import { Config, Package, Version } from '@verdaccio/types'; import { Config, Package, Version } from '@verdaccio/types';
import { formatAuthor, isVersionValid } from '@verdaccio/utils'; import { addGravatarSupport, formatAuthor, isVersionValid } from '@verdaccio/utils';
import { AuthorAvatar, addGravatarSupport, addScope, deleteProperties } from '../utils/web-utils'; import { AuthorAvatar, addScope, deleteProperties } from '../utils/web-utils';
export { $RequestExtend, $ResponseExtend, $NextFunctionVer }; // Was required by other packages export { $RequestExtend, $ResponseExtend, $NextFunctionVer }; // Was required by other packages

@ -1,37 +0,0 @@
import _ from 'lodash';
import { stringToMD5 } from '@verdaccio/utils';
// this is a generic avatar
// https://www.iconfinder.com/icons/403017/anonym_avatar_default_head_person_unknown_user_icon
// license: free commercial usage
export const GENERIC_AVATAR =
'data:image/svg+xml;utf8,' +
encodeURIComponent(
'<svg height="100" viewBox="-27 24 100 100" width="100" xmlns="http://www.w3.org/' +
'2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><circle cx="23" cy="7' +
'4" id="a" r="50"/></defs><use fill="#F5EEE5" overflow="visible" xlink:href="#a"/' +
'><clipPath id="b"><use overflow="visible" xlink:href="#a"/></clipPath><g clip-pa' +
'th="url(#b)"><defs><path d="M36 95.9c0 4 4.7 5.2 7.1 5.8 7.6 2 22.8 5.9 22.8 5.9' +
' 3.2 1.1 5.7 3.5 7.1 6.6v9.8H-27v-9.8c1.3-3.1 3.9-5.5 7.1-6.6 0 0 15.2-3.9 22.8-' +
'5.9 2.4-.6 7.1-1.8 7.1-5.8V85h26v10.9z" id="c"/></defs><use fill="#E6C19C" overf' +
'low="visible" xlink:href="#c"/><clipPath id="d"><use overflow="visible" xlink:hr' +
'ef="#c"/></clipPath><path clip-path="url(#d)" d="M23.2 35h.2c3.3 0 8.2.2 11.4 2 ' +
'3.3 1.9 7.3 5.6 8.5 12.1 2.4 13.7-2.1 35.4-6.3 42.4-4 6.7-9.8 9.2-13.5 9.4H23h-.' +
'1c-3.7-.2-9.5-2.7-13.5-9.4-4.2-7-8.7-28.7-6.3-42.4 1.2-6.5 5.2-10.2 8.5-12.1 3.2' +
'-1.8 8.1-2 11.4-2h.2z" fill="#D4B08C"/></g><path d="M22.6 40c19.1 0 20.7 13.8 20' +
'.8 15.1 1.1 11.9-3 28.1-6.8 33.7-4 5.9-9.8 8.1-13.5 8.3h-.5c-3.8-.3-9.6-2.5-13.6' +
'-8.4-3.8-5.6-7.9-21.8-6.8-33.8C2.3 53.7 3.5 40 22.6 40z" fill="#F2CEA5"/></svg>'
);
/**
* Generate gravatar url from email address
*/
export function generateGravatarUrl(email: string | void = '', online: boolean = true): string {
if (online && _.isString(email) && _.size(email) > 0) {
email = email.trim().toLocaleLowerCase();
const emailMD5 = stringToMD5(email);
return `https://www.gravatar.com/avatar/${emailMD5}`;
}
return GENERIC_AVATAR;
}

@ -2,11 +2,8 @@ import buildDebug from 'debug';
import _ from 'lodash'; import _ from 'lodash';
import sanitizyReadme from '@verdaccio/readme'; import sanitizyReadme from '@verdaccio/readme';
import { normalizeContributors } from '@verdaccio/store'; // import { normalizeContributors } from '@verdaccio/store';
import { Author, ConfigYaml, Package } from '@verdaccio/types'; import { Author, ConfigYaml } from '@verdaccio/types';
import { isObject } from '@verdaccio/utils';
import { GENERIC_AVATAR, generateGravatarUrl } from './user';
export type AuthorAvatar = Author & { avatar?: string }; export type AuthorAvatar = Author & { avatar?: string };
@ -22,56 +19,6 @@ export function validatePrimaryColor(primaryColor) {
return primaryColor; return primaryColor;
} }
export function addGravatarSupport(pkgInfo: Package, online = true): AuthorAvatar {
const pkgInfoCopy = { ...pkgInfo } as any;
const author: any = _.get(pkgInfo, 'latest.author', null) as any;
const contributors: AuthorAvatar[] = normalizeContributors(
_.get(pkgInfo, 'latest.contributors', [])
);
const maintainers = _.get(pkgInfo, 'latest.maintainers', []);
// for author.
if (author && _.isObject(author)) {
const { email } = author as Author;
pkgInfoCopy.latest.author.avatar = generateGravatarUrl(email, online);
}
if (author && _.isString(author)) {
pkgInfoCopy.latest.author = {
avatar: GENERIC_AVATAR,
email: '',
author,
};
}
// for contributors
if (_.isEmpty(contributors) === false) {
pkgInfoCopy.latest.contributors = contributors.map((contributor): AuthorAvatar => {
if (isObject(contributor)) {
contributor.avatar = generateGravatarUrl(contributor.email, online);
} else if (_.isString(contributor)) {
contributor = {
avatar: GENERIC_AVATAR,
email: contributor,
name: contributor,
};
}
return contributor;
});
}
// for maintainers
if (_.isEmpty(maintainers) === false) {
pkgInfoCopy.latest.maintainers = maintainers.map((maintainer): void => {
maintainer.avatar = generateGravatarUrl(maintainer.email, online);
return maintainer;
});
}
return pkgInfoCopy;
}
/** /**
* parse package readme - markdown/ascii * parse package readme - markdown/ascii
* @param {String} packageName name of package * @param {String} packageName name of package

@ -1,221 +1,13 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { GENERIC_AVATAR, generateGravatarUrl } from '../src/utils/user'; import { parseReadme } from '../src/utils/web-utils';
import { addGravatarSupport, parseReadme } from '../src/utils/web-utils';
const readmeFile = (fileName = 'markdown.md') => { const readmeFile = (fileName = 'markdown.md') => {
return fs.readFileSync(path.join(__dirname, `./partials/readme/${fileName}`)); return fs.readFileSync(path.join(__dirname, `./partials/readme/${fileName}`));
}; };
describe('Utilities', () => { describe('Utilities', () => {
describe('User utilities', () => {
test('should generate gravatar url with email', () => {
const gravatarUrl: string = generateGravatarUrl('user@verdaccio.org');
expect(gravatarUrl).toMatch('https://www.gravatar.com/avatar/');
expect(gravatarUrl).not.toMatch('000000000');
});
test('should generate generic gravatar url', () => {
const gravatarUrl: string = generateGravatarUrl();
expect(gravatarUrl).toMatch(GENERIC_AVATAR);
});
});
describe('addGravatarSupport', () => {
test('check for blank object', () => {
// @ts-ignore
expect(addGravatarSupport({})).toEqual({});
});
test('author, contributors and maintainers fields are not present', () => {
const packageInfo = {
latest: {},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(packageInfo);
});
test('author field is a blank object', () => {
const packageInfo = { latest: { author: {} } };
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(packageInfo);
});
test('author field is a string type', () => {
const packageInfo = {
latest: { author: 'user@verdccio.org' },
};
const result = {
latest: {
author: {
author: 'user@verdccio.org',
avatar: GENERIC_AVATAR,
email: '',
},
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(result);
});
test('author field is an object type with author information', () => {
const packageInfo = {
latest: { author: { name: 'verdaccio', email: 'user@verdccio.org' } },
};
const result = {
latest: {
author: {
avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7',
email: 'user@verdccio.org',
name: 'verdaccio',
},
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(result);
});
test('contributor field is a blank array', () => {
const packageInfo = {
latest: {
contributors: [],
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(packageInfo);
});
describe('contributors', () => {
test('contributors field has contributors', () => {
const packageInfo = {
latest: {
contributors: [
{ name: 'user', email: 'user@verdccio.org' },
{ name: 'user1', email: 'user1@verdccio.org' },
],
},
};
const result = {
latest: {
contributors: [
{
avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7',
email: 'user@verdccio.org',
name: 'user',
},
{
avatar: 'https://www.gravatar.com/avatar/51105a49ce4a9c2bfabf0f6a2cba3762',
email: 'user1@verdccio.org',
name: 'user1',
},
],
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(result);
});
test('contributors field is an object', () => {
const packageInfo = {
latest: {
contributors: { name: 'user', email: 'user@verdccio.org' },
},
};
const result = {
latest: {
contributors: [
{
avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7',
email: 'user@verdccio.org',
name: 'user',
},
],
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(result);
});
test('contributors field is a string', () => {
const contributor = 'Barney Rubble <b@rubble.com> (http://barnyrubble.tumblr.com/)';
const packageInfo = {
latest: {
contributors: contributor,
},
};
const result = {
latest: {
contributors: [
{
avatar: GENERIC_AVATAR,
email: contributor,
name: contributor,
},
],
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(result);
});
});
test('maintainers field is a blank array', () => {
const packageInfo = {
latest: {
maintainers: [],
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(packageInfo);
});
test('maintainers field has maintainers', () => {
const packageInfo = {
latest: {
maintainers: [
{ name: 'user', email: 'user@verdccio.org' },
{ name: 'user1', email: 'user1@verdccio.org' },
],
},
};
const result = {
latest: {
maintainers: [
{
avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7',
email: 'user@verdccio.org',
name: 'user',
},
{
avatar: 'https://www.gravatar.com/avatar/51105a49ce4a9c2bfabf0f6a2cba3762',
email: 'user1@verdccio.org',
name: 'user1',
},
],
},
};
// @ts-ignore
expect(addGravatarSupport(packageInfo)).toEqual(result);
});
});
describe('parseReadme', () => { describe('parseReadme', () => {
test('should parse makrdown text to html template', () => { test('should parse makrdown text to html template', () => {
const markdown = '# markdown'; const markdown = '# markdown';