vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
200 lines (199 loc) • 7.82 kB
JavaScript
// Non-production logger used for:
// - Development
// - Preview
// - Build
// - Pre-rendering
// In other words: everywhere except in production
export { logViteAny };
export { logViteError };
export { logConfigInfo };
export { logConfigError };
export { logConfigErrorRecover };
export { logErrorDebugNote };
import { isAbortError } from '../../../shared/route/abort.js';
import { getViteConfig, vikeConfigErrorRecoverMsg } from '../../runtime/globalContext.js';
import { overwriteRuntimeProductionLogger } from '../../runtime/loggerRuntime.js';
import { assert, assertIsNotProductionRuntime, formatHintLog, getAssertErrMsg, overwriteAssertProductionLogger, stripAnsi, warnIfErrorIsNotObject, } from '../utils.js';
import { getHttpRequestAsyncStore } from './getHttpRequestAsyncStore.js';
import { isErrorDebug } from '../../shared/isErrorDebug.js';
import { isErrorWithCodeSnippet, getPrettyErrorWithCodeSnippet } from './loggerNotProd/errorWithCodeSnippet.js';
import { getConfigExecutionErrorIntroMsg, getConfigBuildErrorFormatted, } from './resolveVikeConfigInternal/transpileAndExecuteFile.js';
import { logWithVikeTag, logWithViteTag, logDirectly, applyViteSourceMapToStackTrace } from './loggerNotProd/log.js';
import pc from '@brillout/picocolors';
import { setAlreadyLogged } from '../../runtime/renderPage/isNewError.js';
import { onRuntimeError } from '../../runtime/renderPage/loggerProd.js';
import { isUserHookError } from '../../../shared/hooks/execHook.js';
assertIsNotProductionRuntime();
overwriteRuntimeProductionLogger(logRuntimeError, logRuntimeInfo);
overwriteAssertProductionLogger(assertLogger);
function logRuntimeInfo(msg, httpRequestId, logType) {
const category = getCategory(httpRequestId);
logWithVikeTag(msg, logType, category);
}
function logViteAny(msg, logType, httpRequestId, prependViteTag) {
if (prependViteTag) {
const category = getCategory(httpRequestId);
logWithViteTag(msg, logType, category);
}
else {
logDirectly(msg, logType);
}
}
function logConfigInfo(msg, logType) {
const category = getConfigCategory();
logWithVikeTag(msg, logType, category);
}
function logConfigErrorRecover() {
const category = getConfigCategory();
logWithVikeTag(vikeConfigErrorRecoverMsg, 'error-recover', category);
}
function logRuntimeError(err,
// httpRequestId is `null` when pre-rendering
httpRequestId) {
logErr(err, httpRequestId, false);
}
function logViteError(err,
// httpRequestId is `undefined` if development environment doesn't support async stores
httpRequestId) {
logErr(err, httpRequestId, true);
}
function logErr(err, httpRequestId = null, errorComesFromVite) {
warnIfErrorIsNotObject(err);
if (isAbortError(err) && !isErrorDebug()) {
return;
}
const store = getHttpRequestAsyncStore();
setAlreadyLogged(err);
if (getHttpRequestAsyncStore()?.shouldErrorBeSwallowed(err)) {
if (!isErrorDebug())
return;
}
else {
store?.markErrorAsLogged(err);
}
const category = getCategory(httpRequestId);
if (!isErrorDebug()) {
if (isErrorWithCodeSnippet(err)) {
// We handle transpile errors globally because wrapping viteDevServer.ssrLoadModule() wouldn't be enough: transpile errors can be thrown not only when calling viteDevServer.ssrLoadModule() but also later when loading user code with import() (since Vite lazy-transpiles import() calls)
const viteConfig = getViteConfig();
assert(viteConfig);
const prettyErr = getPrettyErrorWithCodeSnippet(err, viteConfig.root);
assert(stripAnsi(prettyErr).startsWith('Failed to transpile'));
logWithViteTag(prettyErr, 'error', category);
logErrorDebugNote();
return;
}
{
const logged = handleAssertMsg(err, category);
if (logged)
return;
}
}
// Needs to be after assertion messages handling, because user hooks may throw an assertion error
const hook = isUserHookError(err);
if (hook) {
const { hookName, hookFilePath } = hook;
logWithVikeTag(pc.red(`Following error was thrown by the ${hookName}() hook defined at ${hookFilePath}`), 'error', category);
}
else if (category) {
logFallbackErrIntro(category, errorComesFromVite);
}
logDirectly(err, 'error');
// Needs to be called after logging the error.
onRuntimeError(err);
}
function logConfigError(err) {
warnIfErrorIsNotObject(err);
const category = getConfigCategory();
{
const errIntroMsg = getConfigExecutionErrorIntroMsg(err);
if (errIntroMsg) {
assert(stripAnsi(errIntroMsg).startsWith('Failed to execute'));
logWithVikeTag(errIntroMsg, 'error', category);
logDirectly(err, 'error');
return;
}
}
{
const errMsgFormatted = getConfigBuildErrorFormatted(err);
if (errMsgFormatted) {
assert(stripAnsi(errMsgFormatted).startsWith('Failed to transpile'));
if (!isErrorDebug()) {
logWithVikeTag(errMsgFormatted, 'error', category);
}
else {
logDirectly(err, 'error');
}
return;
}
}
{
const logged = handleAssertMsg(err, category);
if (logged)
return;
}
if (category)
logFallbackErrIntro(category, false);
logDirectly(err, 'error');
}
function logFallbackErrIntro(category, errorComesFromVite) {
const msg = errorComesFromVite ? 'Transpilation error' : 'An error was thrown';
logWithVikeTag(pc.bold(pc.red(`[Error] ${msg}:`)), 'error', category);
}
function getConfigCategory() {
const category = getCategory() ?? 'config';
return category;
}
function handleAssertMsg(err, category) {
const res = getAssertErrMsg(err);
if (!res)
return false;
const { assertMsg, showVikeVersion } = res;
logWithVikeTag(assertMsg, 'error', category, showVikeVersion);
return true;
}
function assertLogger(thing, logType) {
// vite.ssrFixStacktrace() is needed for `assertWarning(..., { showStackTrace: true })`
applyViteSourceMapToStackTrace(thing);
const category = getCategory();
const res = getAssertErrMsg(thing);
/* Risk of infinite loop
assert(res)
*/
if (!res)
throw new Error('Internal Vike error, reach out to a maintainer');
const { assertMsg, showVikeVersion } = res;
logWithVikeTag(assertMsg, logType, category, showVikeVersion);
}
/** Note shown to user when vike does something risky:
* - When vike dedupes (i.e. swallows) an error with getHttpRequestAsyncStore().shouldErrorBeSwallowed(err)
* - When vike modifies the error with getPrettyErrorWithCodeSnippet(err)
*/
function logErrorDebugNote() {
if (isErrorDebug())
return;
const store = getHttpRequestAsyncStore();
if (store) {
if (store.errorDebugNoteAlreadyShown)
return;
store.errorDebugNoteAlreadyShown = true;
}
const msg = pc.dim(formatHintLog("Error isn't helpful? See https://vike.dev/debug#verbose-errors"));
logDirectly(msg, 'error');
}
function getCategory(httpRequestId = null) {
const store = getHttpRequestAsyncStore();
if (store?.httpRequestId !== undefined) {
if (httpRequestId === null) {
httpRequestId = store.httpRequestId;
}
else {
assert(httpRequestId === store.httpRequestId);
}
}
if (httpRequestId === null)
return null;
// const category = httpRequestId % 2 === 1 ? (`request-${httpRequestId}` as const) : (`request(${httpRequestId})` as const)
const category = `request(${httpRequestId})`;
return category;
}