0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-12-30 22:34:10 -05:00

chore(types): Improve TS types for renderHTML and related functions (#4605)

* chore(types): Improve TS types for renderHTML

* changeset

* Add author and PR to changeset

* Use RequestOptions instead of Request

* Update changeset text

* Separate type import

* Explain isArray check

* Add verdaccio/url to changeset

* Reverting: throw on wrong type
This commit is contained in:
Tobbe Lundberg 2024-05-02 20:55:52 +02:00 committed by GitHub
parent 3293c9a281
commit b0946b2a3b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 32 additions and 12 deletions

View file

@ -0,0 +1,6 @@
---
'@verdaccio/middleware': patch
'@verdaccio/url': patch
---
Improved TS types for renderHTML() and related functions (by @tobbe in #4605)

View file

@ -1,4 +1,5 @@
import buildDebug from 'debug'; import buildDebug from 'debug';
import type { IncomingHttpHeaders } from 'node:http';
import { URL } from 'url'; import { URL } from 'url';
import validator from 'validator'; import validator from 'validator';
@ -31,7 +32,7 @@ export function isHost(url: string = '', options = {}): boolean {
/** /**
* Detect running protocol (http or https) * Detect running protocol (http or https)
*/ */
export function getWebProtocol(headerProtocol: string | void, protocol: string): string { export function getWebProtocol(headerProtocol: string | undefined, protocol: string): string {
let returnProtocol; let returnProtocol;
const [, defaultProtocol] = validProtocols; const [, defaultProtocol] = validProtocols;
// HAProxy variant might return http,http with X-Forwarded-Proto // HAProxy variant might return http,http with X-Forwarded-Proto
@ -101,7 +102,7 @@ export type RequestOptions = {
/** /**
* Request headers. * Request headers.
*/ */
headers: { [key: string]: string }; headers: IncomingHttpHeaders;
remoteAddress?: string; remoteAddress?: string;
/** /**
* Logged username the request, usually after token verification. * Logged username the request, usually after token verification.
@ -119,10 +120,13 @@ export function getPublicUrl(url_prefix: string = '', requestOptions: RequestOpt
if (!isHost(host)) { if (!isHost(host)) {
throw new Error('invalid host'); throw new Error('invalid host');
} }
const protoHeader =
const protoHeader: string =
process.env.VERDACCIO_FORWARDED_PROTO?.toLocaleLowerCase() ?? process.env.VERDACCIO_FORWARDED_PROTO?.toLocaleLowerCase() ??
HEADERS.FORWARDED_PROTO.toLowerCase(); HEADERS.FORWARDED_PROTO.toLowerCase();
const protocol = getWebProtocol(requestOptions.headers[protoHeader], requestOptions.protocol); const forwardedProtocolHeaderValue = requestOptions.headers[protoHeader] as string | undefined;
const protocol = getWebProtocol(forwardedProtocolHeaderValue, requestOptions.protocol);
const combinedUrl = combineBaseUrl(protocol, host, url_prefix); const combinedUrl = combineBaseUrl(protocol, host, url_prefix);
debug('public url by request %o', combinedUrl); debug('public url by request %o', combinedUrl);
return combinedUrl; return combinedUrl;

View file

@ -1,4 +1,5 @@
import buildDebug from 'debug'; import buildDebug from 'debug';
import type { Response } from 'express';
import LRU from 'lru-cache'; import LRU from 'lru-cache';
import path from 'path'; import path from 'path';
import { URL } from 'url'; import { URL } from 'url';
@ -6,10 +7,12 @@ import { URL } from 'url';
import { WEB_TITLE } from '@verdaccio/config'; import { WEB_TITLE } from '@verdaccio/config';
import { HEADERS } from '@verdaccio/core'; import { HEADERS } from '@verdaccio/core';
import { ConfigYaml, TemplateUIOptions } from '@verdaccio/types'; import { ConfigYaml, TemplateUIOptions } from '@verdaccio/types';
import { isURLhasValidProtocol } from '@verdaccio/url'; import type { RequestOptions } from '@verdaccio/url';
import { getPublicUrl } from '@verdaccio/url'; import { getPublicUrl, isURLhasValidProtocol } from '@verdaccio/url';
import type { Manifest } from './manifest';
import renderTemplate from './template'; import renderTemplate from './template';
import type { WebpackManifest } from './template';
import { hasLogin, validatePrimaryColor } from './web-utils'; import { hasLogin, validatePrimaryColor } from './web-utils';
const DEFAULT_LANGUAGE = 'es-US'; const DEFAULT_LANGUAGE = 'es-US';
@ -17,19 +20,20 @@ const cache = new LRU({ max: 500, ttl: 1000 * 60 * 60 });
const debug = buildDebug('verdaccio:web:render'); const debug = buildDebug('verdaccio:web:render');
const defaultManifestFiles = { const defaultManifestFiles: Manifest = {
js: ['runtime.js', 'vendors.js', 'main.js'], js: ['runtime.js', 'vendors.js', 'main.js'],
ico: 'favicon.ico', ico: 'favicon.ico',
css: [],
}; };
export function resolveLogo(config: ConfigYaml, req) { export function resolveLogo(config: ConfigYaml, requestOptions: RequestOptions) {
if (typeof config?.web?.logo !== 'string') { if (typeof config?.web?.logo !== 'string') {
return ''; return '';
} }
const isLocalFile = config?.web?.logo && !isURLhasValidProtocol(config?.web?.logo); const isLocalFile = config?.web?.logo && !isURLhasValidProtocol(config?.web?.logo);
if (isLocalFile) { if (isLocalFile) {
return `${getPublicUrl(config?.url_prefix, req)}-/static/${path.basename(config?.web?.logo)}`; return `${getPublicUrl(config?.url_prefix, requestOptions)}-/static/${path.basename(config?.web?.logo)}`;
} else if (isURLhasValidProtocol(config?.web?.logo)) { } else if (isURLhasValidProtocol(config?.web?.logo)) {
return config?.web?.logo; return config?.web?.logo;
} else { } else {
@ -37,9 +41,15 @@ export function resolveLogo(config: ConfigYaml, req) {
} }
} }
export default function renderHTML(config: ConfigYaml, manifest, manifestFiles, req, res) { export default function renderHTML(
config: ConfigYaml,
manifest: WebpackManifest,
manifestFiles: Manifest | null | undefined,
requestOptions: RequestOptions,
res: Response
) {
const { url_prefix } = config; const { url_prefix } = config;
const base = getPublicUrl(config?.url_prefix, req); const base = getPublicUrl(config?.url_prefix, requestOptions);
const basename = new URL(base).pathname; const basename = new URL(base).pathname;
const language = config?.i18n?.web ?? DEFAULT_LANGUAGE; const language = config?.i18n?.web ?? DEFAULT_LANGUAGE;
const hideDeprecatedVersions = config?.web?.hideDeprecatedVersions ?? false; const hideDeprecatedVersions = config?.web?.hideDeprecatedVersions ?? false;
@ -51,7 +61,7 @@ export default function renderHTML(config: ConfigYaml, manifest, manifestFiles,
const title = config?.web?.title ?? WEB_TITLE; const title = config?.web?.title ?? WEB_TITLE;
const login = hasLogin(config); const login = hasLogin(config);
const scope = config?.web?.scope ?? ''; const scope = config?.web?.scope ?? '';
const logo = resolveLogo(config, req); const logo = resolveLogo(config, requestOptions);
const pkgManagers = config?.web?.pkgManagers ?? ['yarn', 'pnpm', 'npm']; const pkgManagers = config?.web?.pkgManagers ?? ['yarn', 'pnpm', 'npm'];
const version = res.locals.app_version ?? ''; const version = res.locals.app_version ?? '';
const flags = { const flags = {