Next.js website for Rocky Mountain Vending company featuring: - Product catalog with Stripe integration - Service areas and parts pages - Admin dashboard with Clerk authentication - SEO optimized pages with JSON-LD structured data Co-authored-by: Cursor <cursoragent@cursor.com>
287 lines
6.3 KiB
Text
287 lines
6.3 KiB
Text
/**
|
|
* @license
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import process from 'process';
|
|
import {EventEmitter} from 'events';
|
|
|
|
import debug from 'debug';
|
|
import * as marky from 'marky';
|
|
|
|
const isWindows = process.platform === 'win32';
|
|
|
|
// @ts-expect-error: process.browser is set via Rollup.
|
|
const isBrowser = process.browser;
|
|
|
|
const colors = {
|
|
red: isBrowser ? 'crimson' : 1,
|
|
yellow: isBrowser ? 'gold' : 3,
|
|
cyan: isBrowser ? 'darkturquoise' : 6,
|
|
green: isBrowser ? 'forestgreen' : 2,
|
|
blue: isBrowser ? 'steelblue' : 4,
|
|
magenta: isBrowser ? 'palevioletred' : 5,
|
|
};
|
|
|
|
// allow non-red/yellow colors for debug()
|
|
debug.colors = [colors.cyan, colors.green, colors.blue, colors.magenta];
|
|
|
|
class Emitter extends EventEmitter {
|
|
// yarn build-types fails without this!
|
|
// https://github.com/microsoft/TypeScript/issues/41672#issuecomment-2303803072
|
|
constructor(options) {
|
|
super(options);
|
|
}
|
|
|
|
/**
|
|
* Fires off all status updates. Listen with
|
|
* `require('lib/log').events.addListener('status', callback)`
|
|
* @param {string} title
|
|
* @param {!Array<*>} argsArray
|
|
*/
|
|
issueStatus(title, argsArray) {
|
|
if (title === 'status' || title === 'statusEnd') {
|
|
this.emit(title, [title, ...argsArray]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fires off all warnings. Listen with
|
|
* `require('lib/log').events.addListener('warning', callback)`
|
|
* @param {string} title
|
|
* @param {!Array<*>} argsArray
|
|
*/
|
|
issueWarning(title, argsArray) {
|
|
this.emit('warning', [title, ...argsArray]);
|
|
}
|
|
}
|
|
|
|
const loggersByTitle = {};
|
|
const loggingBufferColumns = 25;
|
|
let level_;
|
|
|
|
class Log {
|
|
static _logToStdErr(title, argsArray) {
|
|
const log = Log.loggerfn(title);
|
|
log(...argsArray);
|
|
}
|
|
|
|
/**
|
|
* @param {string} title
|
|
*/
|
|
static loggerfn(title) {
|
|
title = `LH:${title}`;
|
|
let log = loggersByTitle[title];
|
|
if (!log) {
|
|
log = debug(title);
|
|
loggersByTitle[title] = log;
|
|
// errors with red, warnings with yellow.
|
|
if (title.endsWith('error')) {
|
|
log.color = colors.red;
|
|
} else if (title.endsWith('warn')) {
|
|
log.color = colors.yellow;
|
|
}
|
|
}
|
|
return log;
|
|
}
|
|
|
|
/**
|
|
* @param {string} level
|
|
*/
|
|
static setLevel(level) {
|
|
level_ = level;
|
|
switch (level) {
|
|
case 'silent':
|
|
debug.enable('-LH:*');
|
|
break;
|
|
case 'verbose':
|
|
debug.enable('LH:*');
|
|
break;
|
|
case 'warn':
|
|
debug.enable('-LH:*, LH:*:warn, LH:*:error');
|
|
break;
|
|
case 'error':
|
|
debug.enable('-LH:*, LH:*:error');
|
|
break;
|
|
default:
|
|
debug.enable('LH:*, -LH:*:verbose');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A simple formatting utility for event logging.
|
|
* @param {string} prefix
|
|
* @param {!Object} data A JSON-serializable object of event data to log.
|
|
* @param {string=} level Optional logging level. Defaults to 'log'.
|
|
*/
|
|
static formatProtocol(prefix, data, level) {
|
|
const columns = (!process || process.browser) ? Infinity : process.stdout.columns;
|
|
const method = data.method || '?????';
|
|
const maxLength = columns - method.length - prefix.length - loggingBufferColumns;
|
|
// IO.read ignored here to avoid logging megabytes of trace data
|
|
const snippet = (data.params && method !== 'IO.read') ?
|
|
JSON.stringify(data.params).substr(0, maxLength) : '';
|
|
Log._logToStdErr(`${prefix}:${level || ''}`, [method, snippet]);
|
|
}
|
|
|
|
/**
|
|
* @return {boolean}
|
|
*/
|
|
static isVerbose() {
|
|
return level_ === 'verbose';
|
|
}
|
|
|
|
/**
|
|
* @param {{msg: string, id: string, args?: any[]}} status
|
|
* @param {string} level
|
|
*/
|
|
static time({msg, id, args = []}, level = 'log') {
|
|
marky.mark(id);
|
|
Log[level]('status', msg, ...args);
|
|
}
|
|
|
|
/**
|
|
* @param {{msg: string, id: string, args?: any[]}} status
|
|
* @param {string} level
|
|
*/
|
|
static timeEnd({msg, id, args = []}, level = 'verbose') {
|
|
Log[level]('statusEnd', msg, ...args);
|
|
marky.stop(id);
|
|
}
|
|
|
|
/**
|
|
* @param {string} title
|
|
* @param {...any} args
|
|
*/
|
|
static log(title, ...args) {
|
|
Log.events.issueStatus(title, args);
|
|
return Log._logToStdErr(title, args);
|
|
}
|
|
|
|
/**
|
|
* @param {string} title
|
|
* @param {...any} args
|
|
*/
|
|
static warn(title, ...args) {
|
|
Log.events.issueWarning(title, args);
|
|
return Log._logToStdErr(`${title}:warn`, args);
|
|
}
|
|
|
|
/**
|
|
* @param {string} title
|
|
* @param {...any} args
|
|
*/
|
|
static error(title, ...args) {
|
|
return Log._logToStdErr(`${title}:error`, args);
|
|
}
|
|
|
|
/**
|
|
* @param {string} title
|
|
* @param {...any} args
|
|
*/
|
|
static verbose(title, ...args) {
|
|
Log.events.issueStatus(title, args);
|
|
return Log._logToStdErr(`${title}:verbose`, args);
|
|
}
|
|
|
|
/**
|
|
* Add surrounding escape sequences to turn a string green when logged.
|
|
* @param {string} str
|
|
* @return {string}
|
|
*/
|
|
static greenify(str) {
|
|
return `${Log.green}${str}${Log.reset}`;
|
|
}
|
|
|
|
/**
|
|
* Add surrounding escape sequences to turn a string red when logged.
|
|
* @param {string} str
|
|
* @return {string}
|
|
*/
|
|
static redify(str) {
|
|
return `${Log.red}${str}${Log.reset}`;
|
|
}
|
|
|
|
static get green() {
|
|
return '\x1B[32m';
|
|
}
|
|
|
|
static get red() {
|
|
return '\x1B[31m';
|
|
}
|
|
|
|
static get yellow() {
|
|
return '\x1b[33m';
|
|
}
|
|
|
|
static get purple() {
|
|
return '\x1b[95m';
|
|
}
|
|
|
|
static get reset() {
|
|
return '\x1B[0m';
|
|
}
|
|
|
|
static get bold() {
|
|
return '\x1b[1m';
|
|
}
|
|
|
|
static get dim() {
|
|
return '\x1b[2m';
|
|
}
|
|
|
|
static get tick() {
|
|
return isWindows ? '\u221A' : '✓';
|
|
}
|
|
|
|
static get cross() {
|
|
return isWindows ? '\u00D7' : '✘';
|
|
}
|
|
|
|
static get whiteSmallSquare() {
|
|
return isWindows ? '\u0387' : '▫';
|
|
}
|
|
|
|
static get heavyHorizontal() {
|
|
return isWindows ? '\u2500' : '━';
|
|
}
|
|
|
|
static get heavyVertical() {
|
|
return isWindows ? '\u2502 ' : '┃ ';
|
|
}
|
|
|
|
static get heavyUpAndRight() {
|
|
return isWindows ? '\u2514' : '┗';
|
|
}
|
|
|
|
static get heavyVerticalAndRight() {
|
|
return isWindows ? '\u251C' : '┣';
|
|
}
|
|
|
|
static get heavyDownAndHorizontal() {
|
|
return isWindows ? '\u252C' : '┳';
|
|
}
|
|
|
|
static get doubleLightHorizontal() {
|
|
return '──';
|
|
}
|
|
}
|
|
|
|
Log.events = new Emitter();
|
|
|
|
/**
|
|
* @return {PerformanceEntry[]}
|
|
*/
|
|
Log.takeTimeEntries = () => {
|
|
const entries = marky.getEntries();
|
|
marky.clear();
|
|
return entries;
|
|
};
|
|
|
|
/**
|
|
* @return {PerformanceEntry[]}
|
|
*/
|
|
Log.getTimeEntries = () => marky.getEntries();
|
|
|
|
export default Log;
|