mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-02-17 23:45:29 -05:00
* #2606 add prettier plugin sort imprts * #2606 update pnpm-lock.yaml * #2606 update eslint rules * #2606 fixes website directory formatting Co-authored-by: Ayush Sharma <ayush.sharma@trivago.com>
139 lines
4.1 KiB
TypeScript
139 lines
4.1 KiB
TypeScript
/* eslint-disable no-undef */
|
|
import buildDebug from 'debug';
|
|
import Handlebars from 'handlebars';
|
|
|
|
import { logger } from '@verdaccio/logger';
|
|
import { Config, Notification, Package, RemoteUser } from '@verdaccio/types';
|
|
|
|
import { FetchOptions, notifyRequest } from './notify-request';
|
|
|
|
const debug = buildDebug('verdaccio:hooks');
|
|
|
|
export function compileTemplate(content, metadata) {
|
|
// FUTURE: multiple handlers
|
|
return new Promise((resolve, reject) => {
|
|
let handler;
|
|
try {
|
|
if (!handler) {
|
|
debug('compile default template handler %o', content);
|
|
const template: HandlebarsTemplateDelegate = Handlebars.compile(content);
|
|
return resolve(template(metadata));
|
|
}
|
|
} catch (error: any) {
|
|
debug('error template handler %o', error);
|
|
reject(error);
|
|
}
|
|
});
|
|
}
|
|
|
|
export async function handleNotify(
|
|
metadata: Partial<Package>,
|
|
notifyEntry,
|
|
remoteUser: Partial<RemoteUser>,
|
|
publishedPackage: string
|
|
): Promise<boolean> {
|
|
let regex;
|
|
if (metadata.name && notifyEntry.packagePattern) {
|
|
regex = new RegExp(notifyEntry.packagePattern, notifyEntry.packagePatternFlags || '');
|
|
if (!regex.test(metadata.name)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
let content;
|
|
// FIXME: publisher is not part of the expected types metadata
|
|
// @ts-ignore
|
|
if (typeof metadata?.publisher === 'undefined' || metadata?.publisher === null) {
|
|
// @ts-ignore
|
|
metadata = { ...metadata, publishedPackage, publisher: { name: remoteUser.name as string } };
|
|
debug('template metadata %o', metadata);
|
|
content = await compileTemplate(notifyEntry.content, metadata);
|
|
}
|
|
|
|
const options: FetchOptions = {
|
|
body: JSON.stringify(content),
|
|
};
|
|
|
|
// provides fallback support, it's accept an Object {} and Array of {}
|
|
if (notifyEntry.headers && Array.isArray(notifyEntry.headers)) {
|
|
const header = {};
|
|
// FIXME: we can simplify this
|
|
notifyEntry.headers.map(function (item): void {
|
|
if (Object.is(item, item)) {
|
|
for (const key in item) {
|
|
/* eslint no-prototype-builtins: 0 */
|
|
if (item.hasOwnProperty(key)) {
|
|
header[key] = item[key];
|
|
}
|
|
}
|
|
}
|
|
});
|
|
options.headers = header;
|
|
} else if (Object.is(notifyEntry.headers, notifyEntry.headers)) {
|
|
options.headers = notifyEntry.headers;
|
|
}
|
|
|
|
if (!notifyEntry.endpoint) {
|
|
debug('error due endpoint is missing');
|
|
throw new Error('missing parameter');
|
|
}
|
|
|
|
return notifyRequest(notifyEntry.endpoint, {
|
|
method: notifyEntry.method,
|
|
...options,
|
|
});
|
|
}
|
|
|
|
export function sendNotification(
|
|
metadata: Partial<Package>,
|
|
notify: Notification,
|
|
remoteUser: Partial<RemoteUser>,
|
|
publishedPackage: string
|
|
): Promise<boolean> {
|
|
return handleNotify(metadata, notify, remoteUser, publishedPackage) as Promise<any>;
|
|
}
|
|
|
|
export async function notify(
|
|
metadata: Partial<Package>,
|
|
config: Partial<Config>,
|
|
remoteUser: Partial<RemoteUser>,
|
|
publishedPackage: string
|
|
): Promise<boolean[]> {
|
|
debug('init send notification');
|
|
if (config.notify) {
|
|
const isSingle = Object.keys(config.notify).includes('method');
|
|
if (isSingle) {
|
|
debug('send single notification');
|
|
try {
|
|
const response = await sendNotification(
|
|
metadata,
|
|
config.notify as Notification,
|
|
remoteUser,
|
|
publishedPackage
|
|
);
|
|
return [response];
|
|
} catch {
|
|
debug('error on sending single notification');
|
|
return [false];
|
|
}
|
|
} else {
|
|
debug('send multiples notification');
|
|
const results = await Promise.allSettled(
|
|
Object.keys(config.notify).map((keyId: string) => {
|
|
// @ts-ignore
|
|
const item = config.notify[keyId];
|
|
debug('send item %o', item);
|
|
return sendNotification(metadata, item, remoteUser, publishedPackage);
|
|
})
|
|
).catch((error) => {
|
|
logger.error({ error }, 'notify request has failed: @error');
|
|
});
|
|
|
|
// @ts-ignore
|
|
return Object.keys(results).map((promiseValue) => results[promiseValue].value);
|
|
}
|
|
} else {
|
|
debug('no notifications configuration detected');
|
|
return [false];
|
|
}
|
|
}
|