vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
192 lines (191 loc) • 6.46 kB
JavaScript
export { assert };
export { assertUsage };
export { assertWarning };
export { assertInfo };
export { getProjectError };
export { addOnBeforeLogHook };
export { getAssertErrMsg };
export { overwriteAssertProductionLogger };
export { isBug };
export { setAlwaysShowStackTrace };
import { assertSingleInstance_onAssertModuleLoad } from './assertSingleInstance.js';
import { createErrorWithCleanStackTrace } from './createErrorWithCleanStackTrace.js';
import { getGlobalObject } from './getGlobalObject.js';
import { isObject } from './isObject.js';
import { PROJECT_VERSION } from './PROJECT_VERSION.js';
import pc from '@brillout/picocolors';
const globalObject = getGlobalObject('utils/assert.ts', {
alreadyLogged: new Set(),
// Production logger. Overwritten by loggerNotProd.ts in non-production environments.
logger(msg, logType) {
if (logType === 'info') {
console.log(msg);
}
else {
console.warn(msg);
}
},
showStackTraceList: new WeakSet(),
});
assertSingleInstance_onAssertModuleLoad();
const projectTag = `[vike]`;
const projectTagWithVersion = `[vike@${PROJECT_VERSION}]`;
const bugTag = 'Bug';
const numberOfStackTraceLinesToRemove = 2;
function assert(condition, debugInfo) {
if (condition)
return;
const debugStr = (() => {
if (!debugInfo) {
return null;
}
const debugInfoSerialized = typeof debugInfo === 'string' ? debugInfo : JSON.stringify(debugInfo);
return pc.dim(`Debug info for Vike maintainers (you can ignore this): ${debugInfoSerialized}`);
})();
const link = pc.underline('https://github.com/vikejs/vike/issues/new?template=bug.yml');
let errMsg = [
`You stumbled upon a Vike bug. Go to ${link} and copy-paste this error. A maintainer will fix the bug (usually within 24 hours).`,
debugStr,
]
.filter(Boolean)
.join(' ');
errMsg = addWhitespace(errMsg);
errMsg = addPrefixAssertType(errMsg, bugTag);
errMsg = addPrefixProjectName(errMsg, true);
const internalError = createErrorWithCleanStackTrace(errMsg, numberOfStackTraceLinesToRemove);
globalObject.onBeforeLog?.();
throw internalError;
}
function assertUsage(condition, errMsg, { showStackTrace, exitOnError } = {}) {
if (condition)
return;
showStackTrace = showStackTrace || globalObject.alwaysShowStackTrace;
errMsg = addWhitespace(errMsg);
errMsg = addPrefixAssertType(errMsg, 'Wrong Usage');
errMsg = addPrefixProjectName(errMsg);
const usageError = createErrorWithCleanStackTrace(errMsg, numberOfStackTraceLinesToRemove);
if (showStackTrace) {
globalObject.showStackTraceList.add(usageError);
}
globalObject.onBeforeLog?.();
if (!exitOnError) {
throw usageError;
}
else {
console.error(showStackTrace ? usageError : errMsg);
process.exit(1);
}
}
function getProjectError(errMsg) {
errMsg = addWhitespace(errMsg);
errMsg = addPrefixAssertType(errMsg, 'Error');
errMsg = addPrefixProjectName(errMsg);
const projectError = createErrorWithCleanStackTrace(errMsg, numberOfStackTraceLinesToRemove);
return projectError;
}
function assertWarning(condition, msg, { onlyOnce, showStackTrace }) {
if (condition)
return;
showStackTrace = showStackTrace || globalObject.alwaysShowStackTrace;
msg = addWhitespace(msg);
msg = addPrefixAssertType(msg, 'Warning');
msg = addPrefixProjectName(msg);
if (onlyOnce) {
const { alreadyLogged } = globalObject;
const key = onlyOnce === true ? msg : onlyOnce;
if (alreadyLogged.has(key))
return;
alreadyLogged.add(key);
}
globalObject.onBeforeLog?.();
if (showStackTrace) {
const err = createErrorWithCleanStackTrace(msg, numberOfStackTraceLinesToRemove);
globalObject.showStackTraceList.add(err);
globalObject.logger(err, 'warn');
}
else {
globalObject.logger(msg, 'warn');
}
}
function assertInfo(condition, msg, { onlyOnce }) {
if (condition) {
return;
}
msg = addWhitespace(msg);
msg = addPrefixProjectName(msg);
if (onlyOnce) {
const { alreadyLogged } = globalObject;
const key = msg;
if (alreadyLogged.has(key)) {
return;
}
else {
alreadyLogged.add(key);
}
}
globalObject.onBeforeLog?.();
globalObject.logger(msg, 'info');
}
function addOnBeforeLogHook(onBeforeLog) {
globalObject.onBeforeLog = onBeforeLog;
}
function addPrefixAssertType(msg, tag) {
let prefix = `[${tag}]`;
const color = tag === 'Warning' ? 'yellow' : 'red';
prefix = pc.bold(pc[color](prefix));
return `${prefix}${msg}`;
}
function addWhitespace(msg) {
if (msg.startsWith('[')) {
return msg;
}
else {
return ` ${msg}`;
}
}
function addPrefixProjectName(msg, showProjectVersion = false) {
const prefix = showProjectVersion ? projectTagWithVersion : projectTag;
return `${prefix}${msg}`;
}
function getAssertErrMsg(thing) {
let errMsg;
let errStack;
if (typeof thing === 'string') {
errMsg = thing;
}
else if (isObject(thing) && typeof thing.message === 'string' && typeof thing.stack === 'string') {
errMsg = thing.message;
errStack = thing.stack;
}
else {
return null;
}
for (const tag of [projectTagWithVersion, projectTag]) {
const showVikeVersion = tag === projectTagWithVersion;
const errStackPrefix = `Error: ${tag}`;
if (errStack?.startsWith(errStackPrefix)) {
if (globalObject.showStackTraceList.has(thing) || isBug(thing)) {
const assertMsg = errStack.slice(errStackPrefix.length);
return { assertMsg, showVikeVersion };
}
}
else if (errStack?.includes(tag)) {
throw new Error('Internal Vike error');
}
if (errMsg?.startsWith(tag)) {
const assertMsg = errMsg.slice(tag.length);
return { assertMsg, showVikeVersion };
}
}
return null;
}
function overwriteAssertProductionLogger(logger) {
globalObject.logger = logger;
}
function isBug(err) {
return String(err).includes(`[${bugTag}]`);
}
// Called upon `DEBUG=vike:error`
function setAlwaysShowStackTrace() {
globalObject.alwaysShowStackTrace = true;
}