@modern-js/utils
Version:
A Progressive React Framework for modern web development.
69 lines (68 loc) • 3.29 kB
JavaScript
import { isIPv6 } from "net";
import os from "os";
import { chalk } from "../compiled.mjs";
import { DEFAULT_DEV_HOST } from "./constants.mjs";
import { isDev, isSingleEntry } from "./is/index.mjs";
const normalizeUrl = (url)=>url.replace(/([^:]\/)\/+/g, '$1');
const getIpv4Interfaces = ()=>{
const interfaces = os.networkInterfaces();
const ipv4Interfaces = [];
Object.keys(interfaces).forEach((key)=>{
interfaces[key].forEach((detail)=>{
const familyV4Value = 'string' == typeof detail.family ? 'IPv4' : 4;
if (detail.family === familyV4Value) ipv4Interfaces.push(detail);
});
});
return ipv4Interfaces;
};
const getHostInUrl = (host)=>{
if (isIPv6(host)) return '::' === host ? '[::1]' : `[${host}]`;
return host;
};
const getAddressUrls = (protocol = 'http', port, host)=>{
const LOCAL_LABEL = 'Local: ';
const NETWORK_LABEL = 'Network: ';
const isLocalhost = (url)=>url?.includes('localhost');
if (host && host !== DEFAULT_DEV_HOST) return [
{
label: isLocalhost(host) ? LOCAL_LABEL : NETWORK_LABEL,
url: `${protocol}://${getHostInUrl(host)}:${port}`
}
];
const ipv4Interfaces = getIpv4Interfaces();
return ipv4Interfaces.reduce((memo, detail)=>{
if (isLocalhost(detail.address) || detail.internal) memo.push({
label: LOCAL_LABEL,
url: `${protocol}://localhost:${port}`
});
else memo.push({
label: NETWORK_LABEL,
url: `${protocol}://${detail.address}:${port}`
});
return memo;
}, []);
};
const prettyInstructions = (appContext, config)=>{
const { entrypoints, serverRoutes, port, apiOnly, checkedEntries } = appContext;
const isHttps = isDev() && (config?.dev?.https || config?.tools?.devServer?.https);
const urls = getAddressUrls(isHttps ? 'https' : 'http', port, config.dev?.host);
const routes = apiOnly ? serverRoutes : serverRoutes.filter((route)=>route.entryName);
let message = '\n';
if (isSingleEntry(entrypoints, config.source?.mainEntryName) || apiOnly) message += urls.map(({ label, url })=>` ${chalk.bold(`> ${label.padEnd(10)}`)}${chalk.cyanBright(normalizeUrl(`${url}/${routes[0].urlPath}`))}\n`).join('');
else {
const maxNameLength = Math.max(...routes.map((r)=>r.entryName.length));
urls.forEach(({ label, url })=>{
message += ` ${chalk.bold(`> ${label}`)}${0 === routes.length ? chalk.cyanBright(url) : ''}\n`;
routes.forEach(({ entryName, urlPath, isSSR })=>{
if (!checkedEntries.includes(entryName)) return;
message += ` ${chalk.yellowBright(isSSR ? 'λ' : '○')} ${chalk.yellowBright(entryName.padEnd(maxNameLength + 8))}${chalk.cyanBright(normalizeUrl(`${url}/${urlPath}`))}\n`;
});
});
message += '\n';
message += chalk.cyanBright(' λ (Server) server-side renders at runtime\n');
message += chalk.cyanBright(' ○ (Static) client-side renders as static HTML\n');
}
if (config.dev?.cliShortcuts) message += ` ${chalk.dim('> press')} ${chalk.bold('h + enter')} ${chalk.dim('to show shortcuts')}\n`;
return message;
};
export { getAddressUrls, prettyInstructions };