UNPKG

vike

Version:

The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.

173 lines (172 loc) 5.62 kB
export { createDebugger }; export { isDebugActivated }; import { isBrowser } from './isBrowser.js'; import { isCallable } from './isCallable.js'; import { objectAssign } from './objectAssign.js'; import { assert, assertUsage } from './assert.js'; import { checkType } from './checkType.js'; import { getTerminalWidth } from './getTerminWidth.js'; import pc from '@brillout/picocolors'; import { isArray } from './isArray.js'; import { isObject } from './isObject.js'; import { setCreateDebugger } from '../shared/route/debug.js'; assert(!isBrowser()); setCreateDebugger(createDebugger); // for isomorphic code const flags = [ 'vike:crawl', 'vike:error', 'vike:esbuild-resolve', 'vike:pluginExtractAssets', 'vike:pluginExtractExportNames', 'vike:glob', 'vike:globalContext', 'vike:log', 'vike:optimizeDeps', 'vike:outDir', 'vike:pageFiles', 'vike:pointer-imports', 'vike:resolve', 'vike:routing', 'vike:setup', 'vike:stream', 'vike:virtualFiles', ]; const flagsSkipWildcard = ['vike:log']; const flagRegex = /\bvike:[a-zA-Z-]+/g; // We purposely read process.env.DEBUG early, in order to avoid users from the temptation to set process.env.DEBUG with JavaScript, since reading & writing process.env.DEBUG dynamically leads to inconsistencies such as https://github.com/vikejs/vike/issues/2239 const DEBUG = getDEBUG() ?? ''; if (isDebug()) Error.stackTraceLimit = Infinity; assertFlagsActivated(); function createDebugger(flag, optionsGlobal) { checkType(flag); assert(flags.includes(flag)); const debugWithOptions = (optionsLocal) => { return (...msgs) => { const options = { ...optionsGlobal, ...optionsLocal }; debug_(flag, options, ...msgs); }; }; const debug = (...msgs) => debugWithOptions({})(...msgs); objectAssign(debug, { options: debugWithOptions, isActivated: isDebugActivated(flag) }); return debug; } function debug_(flag, options, ...msgs) { if (!isDebugActivated(flag)) return; let [msgFirst, ...msgsRest] = msgs; const padding = ' '.repeat(flag.length + 1); msgFirst = formatMsg(msgFirst, options, padding, 'FIRST'); msgsRest = msgsRest.map((msg, i) => { const position = i === msgsRest.length - 1 ? 'LAST' : 'MIDDLE'; return formatMsg(msg, options, padding, position); }); let logFirst; let logsRest; const noNewLine = msgsRest.length <= 1 && [msgFirst, ...msgsRest].every((m) => (typeof m === 'string' ? !m.includes('\n') : !isObject(m))); if (noNewLine) { logFirst = [msgFirst, ...msgsRest].map((m) => (typeof m !== 'string' ? m : m.trim())); logsRest = []; } else { logFirst = [msgFirst]; logsRest = msgsRest; } console.log('\x1b[1m%s\x1b[0m', flag, ...logFirst); logsRest.forEach((msg) => { console.log(msg); }); } function isDebugActivated(flag) { checkType(flag); assert(flags.includes(flag)); const { flagsActivated, all } = getFlagsActivated(); const isActivated = flagsActivated.includes(flag) || (all && !flagsSkipWildcard.includes(flag)); return isActivated; } function formatMsg(info, options, padding, position) { if (info === undefined) { return undefined; } let str = position === 'FIRST' ? '' : padding; if (typeof info === 'string') { str += info; } else if (isArray(info)) { if (info.length === 0) { str += options.serialization?.emptyArray ?? '[]'; } else { str += info.map(strUnknown).join('\n'); } } else { str += strUnknown(info); } str = pad(str, padding); if (position !== 'LAST' && position !== 'FIRST') { str += '\n'; } return str; } function pad(str, padding) { const terminalWidth = getTerminalWidth(); const lines = []; str.split('\n').forEach((line) => { if (!terminalWidth) { lines.push(line); } else { chunk(line, terminalWidth - padding.length).forEach((chunk) => { lines.push(chunk); }); } }); return lines.join('\n' + padding); } function chunk(str, size) { if (str.length <= size) { return [str]; } const chunks = str.match(new RegExp('.{1,' + size + '}', 'g')); assert(chunks); return chunks; } function strUnknown(thing) { return typeof thing === 'string' ? thing : strObj(thing); } function strObj(obj, newLines = true) { return JSON.stringify(obj, replaceFunctionSerializer, newLines ? 2 : undefined); } function replaceFunctionSerializer(_key, value) { if (isCallable(value)) { return value.toString().split(/\s+/).join(' '); } return value; } function assertFlagsActivated() { const { flagsActivated } = getFlagsActivated(); flagsActivated.forEach((flag) => { assertUsage(flags.includes(flag), `Unknown DEBUG flag ${pc.cyan(flag)}. Valid flags:\n${flags.map((f) => ` ${pc.cyan(f)}`).join('\n')}`); }); } function getFlagsActivated() { const flagsActivated = DEBUG.match(flagRegex) ?? []; const all = DEBUG.includes('vike:*'); return { flagsActivated, all }; } function isDebug() { const { flagsActivated, all } = getFlagsActivated(); return all || flagsActivated.length > 0; } function getDEBUG() { let DEBUG; // - `process` can be undefined in edge workers // - We want bundlers to be able to statically replace `process.env.*` try { DEBUG = process.env.DEBUG; } catch { } return DEBUG; }