@neodx/log
Version:
A lightweight universal logging framework
1,218 lines (1,191 loc) • 54.3 kB
JavaScript
'use strict';
var node_os = require('node:os');
var createLoggerFactory = require('./create-logger-factory-LGNVkcG-.cjs');
var readArguments = require('./read-arguments-BBlq0hOP.cjs');
var node_fs = require('node:fs');
var colors = require('@neodx/colors');
var pathe = require('pathe');
var utils_index = require('../utils/index.cjs');
function fromLength(length, fn = readArguments.identity) {
return Array.from(
{
length
},
(_, index) => fn(index)
);
}
function filterObject(record, fn) {
return Object.fromEntries(readArguments.entries(record).filter(([key, value]) => fn(value, key)));
}
const omit = (obj, keys) => filterObject(obj, (_, key) => !keys.includes(key));
const pick = (target, keys) =>
Object.fromEntries(Object.entries(target).filter(([key]) => keys.includes(key)));
const sum = values => values.reduce((acc, item) => acc + item, 0);
function memoizeWeak(fn) {
return memoize(fn, {
cache: new WeakMap()
});
}
function memoize(fn, { cache = new Map(), key = readArguments.identity } = {}) {
function cachedFn(input) {
return readArguments.getOrCreateMapValue(cache, key(input), () => fn(input));
}
cachedFn.cache = cache;
return cachedFn;
}
const truncateString = (str, maxLength, suffix = '...') =>
str.length <= maxLength ? str : str.slice(0, maxLength - suffix.length) + suffix;
const formatOutgoingMessageStatus = res => {
if (!res.headersSent) return 'unknown status';
const { statusCode, statusMessage } = res;
return `${statusCode} ${statusMessage}`;
};
const formatIncomingMessage = (req, colors, delimiter = ' ') =>
`${colors.bold(req.method?.toUpperCase() ?? 'GET')}${delimiter}${colors.underline(colors.gray(truncateString(getIncomingMessageUrl(req).split('?')?.shift() ?? '', 50)))}`;
const formatResponseTime = time => {
const showSeconds = time >= 100;
const timeValue = showSeconds ? time / 1000 : time;
return timeValue
.toLocaleString('en', {
style: 'unit',
unit: showSeconds ? 'second' : 'millisecond',
unitDisplay: 'narrow',
maximumFractionDigits: 1
})
.padEnd(4);
};
function serializeHttpRequest(req) {
const { id, info, query, method, params, headers, [HTTP_LOG_RAW_SYMBOL]: raw } = req;
const connection = info || req.socket;
return {
id: typeof id === 'function' ? id() : id ?? info?.id,
url: getIncomingMessageUrl(req),
query,
params,
method,
headers,
remotePort: connection?.remotePort,
remoteAddress: connection?.remoteAddress,
[HTTP_LOG_RAW_SYMBOL]: raw || req
};
}
function serializeHttpResponse(res) {
return {
statusCode: res.headersSent ? res.statusCode : null,
headers: res.getHeaders(),
[HTTP_LOG_RAW_SYMBOL]: res
};
}
const getIncomingMessageUrl = ({ originalUrl, path, url }) =>
originalUrl || (typeof path === 'string' ? path : url?.path ?? url);
const createRequestIdGenerator = () => {
let currentRequestId = 0;
return function generateRequestId() {
currentRequestId = currentRequestId >= maxInt ? 0 : currentRequestId + 1;
return currentRequestId;
};
};
const HTTP_LOG_START_TIME_SYMBOL = Symbol('HTTP_LOG_START_TIME');
const HTTP_LOG_RAW_SYMBOL = Symbol('raw');
const maxInt = 2147483647;
/* eslint-disable yoda */ function isFullwidthCodePoint(codePoint) {
if (!Number.isInteger(codePoint)) {
return false;
}
// Code points are derived from:
// https://unicode.org/Public/UNIDATA/EastAsianWidth.txt
return (
codePoint >= 0x1100 &&
(codePoint <= 0x115f || // Hangul Jamo
codePoint === 0x2329 || // LEFT-POINTING ANGLE BRACKET
codePoint === 0x232a || // RIGHT-POINTING ANGLE BRACKET
// CJK Radicals Supplement .. Enclosed CJK Letters and Months
(0x2e80 <= codePoint && codePoint <= 0x3247 && codePoint !== 0x303f) || // Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A
(0x3250 <= codePoint && codePoint <= 0x4dbf) || // CJK Unified Ideographs .. Yi Radicals
(0x4e00 <= codePoint && codePoint <= 0xa4c6) || // Hangul Jamo Extended-A
(0xa960 <= codePoint && codePoint <= 0xa97c) || // Hangul Syllables
(0xac00 <= codePoint && codePoint <= 0xd7a3) || // CJK Compatibility Ideographs
(0xf900 <= codePoint && codePoint <= 0xfaff) || // Vertical Forms
(0xfe10 <= codePoint && codePoint <= 0xfe19) || // CJK Compatibility Forms .. Small Form Variants
(0xfe30 <= codePoint && codePoint <= 0xfe6b) || // Halfwidth and Fullwidth Forms
(0xff01 <= codePoint && codePoint <= 0xff60) ||
(0xffe0 <= codePoint && codePoint <= 0xffe6) || // Kana Supplement
(0x1b000 <= codePoint && codePoint <= 0x1b001) || // Enclosed Ideographic Supplement
(0x1f200 <= codePoint && codePoint <= 0x1f251) || // CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane
(0x20000 <= codePoint && codePoint <= 0x3fffd))
);
}
const ANSI_BACKGROUND_OFFSET = 10;
const wrapAnsi16 =
(offset = 0) =>
code =>
`\u001B[${code + offset}m`;
const wrapAnsi256 =
(offset = 0) =>
code =>
`\u001B[${38 + offset};5;${code}m`;
const wrapAnsi16m =
(offset = 0) =>
(red, green, blue) =>
`\u001B[${38 + offset};2;${red};${green};${blue}m`;
const styles = {
modifier: {
reset: [0, 0],
// 21 isn't widely supported and 22 does the same thing
bold: [1, 22],
dim: [2, 22],
italic: [3, 23],
underline: [4, 24],
overline: [53, 55],
inverse: [7, 27],
hidden: [8, 28],
strikethrough: [9, 29]
},
color: {
black: [30, 39],
red: [31, 39],
green: [32, 39],
yellow: [33, 39],
blue: [34, 39],
magenta: [35, 39],
cyan: [36, 39],
white: [37, 39],
// Bright color
blackBright: [90, 39],
gray: [90, 39],
grey: [90, 39],
redBright: [91, 39],
greenBright: [92, 39],
yellowBright: [93, 39],
blueBright: [94, 39],
magentaBright: [95, 39],
cyanBright: [96, 39],
whiteBright: [97, 39]
},
bgColor: {
bgBlack: [40, 49],
bgRed: [41, 49],
bgGreen: [42, 49],
bgYellow: [43, 49],
bgBlue: [44, 49],
bgMagenta: [45, 49],
bgCyan: [46, 49],
bgWhite: [47, 49],
// Bright color
bgBlackBright: [100, 49],
bgGray: [100, 49],
bgGrey: [100, 49],
bgRedBright: [101, 49],
bgGreenBright: [102, 49],
bgYellowBright: [103, 49],
bgBlueBright: [104, 49],
bgMagentaBright: [105, 49],
bgCyanBright: [106, 49],
bgWhiteBright: [107, 49]
}
};
function assembleStyles() {
const codes = new Map();
for (const [groupName, group] of Object.entries(styles)) {
for (const [styleName, style] of Object.entries(group)) {
styles[styleName] = {
open: `\u001B[${style[0]}m`,
close: `\u001B[${style[1]}m`
};
group[styleName] = styles[styleName];
codes.set(style[0], style[1]);
}
Object.defineProperty(styles, groupName, {
value: group,
enumerable: false
});
}
Object.defineProperty(styles, 'codes', {
value: codes,
enumerable: false
});
styles.color.close = '\u001B[39m';
styles.bgColor.close = '\u001B[49m';
styles.color.ansi = wrapAnsi16();
styles.color.ansi256 = wrapAnsi256();
styles.color.ansi16m = wrapAnsi16m();
styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
// From https://github.com/Qix-/color-convert/blob/3f0e0d4e92e235796ccb17f6e85c72094a651f49/conversions.js
Object.defineProperties(styles, {
rgbToAnsi256: {
value: (red, green, blue) => {
// We use the extended greyscale palette here, with the exception of
// black and white. normal palette only has 4 greyscale shades.
if (red === green && green === blue) {
if (red < 8) {
return 16;
}
if (red > 248) {
return 231;
}
return Math.round(((red - 8) / 247) * 24) + 232;
}
return (
16 +
36 * Math.round((red / 255) * 5) +
6 * Math.round((green / 255) * 5) +
Math.round((blue / 255) * 5)
);
},
enumerable: false
},
hexToRgb: {
value: hex => {
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
if (!matches) {
return [0, 0, 0];
}
let [colorString] = matches;
if (colorString.length === 3) {
colorString = [...colorString].map(character => character + character).join('');
}
const integer = Number.parseInt(colorString, 16);
return [
/* eslint-disable no-bitwise */ (integer >> 16) & 0xff,
(integer >> 8) & 0xff,
integer & 0xff
];
},
enumerable: false
},
hexToAnsi256: {
value: hex => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
enumerable: false
},
ansi256ToAnsi: {
value: code => {
if (code < 8) {
return 30 + code;
}
if (code < 16) {
return 90 + (code - 8);
}
let red;
let green;
let blue;
if (code >= 232) {
red = ((code - 232) * 10 + 8) / 255;
green = red;
blue = red;
} else {
code -= 16;
const remainder = code % 36;
red = Math.floor(code / 36) / 5;
green = Math.floor(remainder / 6) / 5;
blue = (remainder % 6) / 5;
}
const value = Math.max(red, green, blue) * 2;
if (value === 0) {
return 30;
}
// eslint-disable-next-line no-bitwise
let result = 30 + ((Math.round(blue) << 2) | (Math.round(green) << 1) | Math.round(red));
if (value === 2) {
result += 60;
}
return result;
},
enumerable: false
},
rgbToAnsi: {
value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
enumerable: false
},
hexToAnsi: {
value: hex => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
enumerable: false
}
});
return styles;
}
const ansiStyles = assembleStyles();
const astralRegex = /^[\uD800-\uDBFF][\uDC00-\uDFFF]$/;
const ESCAPES = ['\u001B', '\u009B'];
const wrapAnsi = code => `${ESCAPES[0]}[${code}m`;
const checkAnsi = (ansiCodes, isEscapes, endAnsiCode) => {
let output = [];
ansiCodes = [...ansiCodes];
for (let ansiCode of ansiCodes) {
const ansiCodeOrigin = ansiCode;
if (ansiCode.includes(';')) {
ansiCode = ansiCode.split(';')[0][0] + '0';
}
const item = ansiStyles.codes.get(Number.parseInt(ansiCode, 10));
if (item) {
const indexEscape = ansiCodes.indexOf(item.toString());
if (indexEscape === -1) {
output.push(wrapAnsi(isEscapes ? item : ansiCodeOrigin));
} else {
ansiCodes.splice(indexEscape, 1);
}
} else if (isEscapes) {
output.push(wrapAnsi(0));
break;
} else {
output.push(wrapAnsi(ansiCodeOrigin));
}
}
if (isEscapes) {
output = output.filter((element, index) => output.indexOf(element) === index);
if (endAnsiCode !== undefined) {
const fistEscapeCode = wrapAnsi(ansiStyles.codes.get(Number.parseInt(endAnsiCode, 10)));
// TODO: Remove the use of `.reduce` here.
// eslint-disable-next-line unicorn/no-array-reduce
output = output.reduce(
(current, next) => (next === fistEscapeCode ? [next, ...current] : [...current, next]),
[]
);
}
}
return output.join('');
};
function sliceAnsi(string, begin, end) {
const characters = [...string];
const ansiCodes = [];
let stringEnd = typeof end === 'number' ? end : characters.length;
let isInsideEscape = false;
let ansiCode;
let visible = 0;
let output = '';
for (const [index, character] of characters.entries()) {
let leftEscape = false;
if (ESCAPES.includes(character)) {
const code = /\d[^m]*/.exec(string.slice(index, index + 18));
ansiCode = code && code.length > 0 ? code[0] : undefined;
if (visible < stringEnd) {
isInsideEscape = true;
if (ansiCode !== undefined) {
ansiCodes.push(ansiCode);
}
}
} else if (isInsideEscape && character === 'm') {
isInsideEscape = false;
leftEscape = true;
}
if (!isInsideEscape && !leftEscape) {
visible++;
}
if (!astralRegex.test(character) && isFullwidthCodePoint(character.codePointAt())) {
visible++;
if (typeof end !== 'number') {
stringEnd++;
}
}
if (visible > begin && visible <= stringEnd) {
output += character;
} else if (visible === begin && !isInsideEscape && ansiCode !== undefined) {
output = checkAnsi(ansiCodes);
} else if (visible >= stringEnd) {
output += checkAnsi(ansiCodes, true, ansiCode);
break;
}
}
return output;
}
function ansiRegex({ onlyFirst = false } = {}) {
const pattern = [
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
].join('|');
return new RegExp(pattern, onlyFirst ? undefined : 'g');
}
const regex = ansiRegex();
function stripAnsi(string) {
if (typeof string !== 'string') {
throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
}
// Even though the regex is global, we don't need to reset the `.lastIndex`
// because unlike `.exec()` and `.test()`, `.replace()` does it automatically
// and doing it manually has a performance penalty.
return string.replace(regex, '');
}
// Generated code.
function isAmbiguous(x) {
return (
x === 0xa1 ||
x === 0xa4 ||
x === 0xa7 ||
x === 0xa8 ||
x === 0xaa ||
x === 0xad ||
x === 0xae ||
(x >= 0xb0 && x <= 0xb4) ||
(x >= 0xb6 && x <= 0xba) ||
(x >= 0xbc && x <= 0xbf) ||
x === 0xc6 ||
x === 0xd0 ||
x === 0xd7 ||
x === 0xd8 ||
(x >= 0xde && x <= 0xe1) ||
x === 0xe6 ||
(x >= 0xe8 && x <= 0xea) ||
x === 0xec ||
x === 0xed ||
x === 0xf0 ||
x === 0xf2 ||
x === 0xf3 ||
(x >= 0xf7 && x <= 0xfa) ||
x === 0xfc ||
x === 0xfe ||
x === 0x101 ||
x === 0x111 ||
x === 0x113 ||
x === 0x11b ||
x === 0x126 ||
x === 0x127 ||
x === 0x12b ||
(x >= 0x131 && x <= 0x133) ||
x === 0x138 ||
(x >= 0x13f && x <= 0x142) ||
x === 0x144 ||
(x >= 0x148 && x <= 0x14b) ||
x === 0x14d ||
x === 0x152 ||
x === 0x153 ||
x === 0x166 ||
x === 0x167 ||
x === 0x16b ||
x === 0x1ce ||
x === 0x1d0 ||
x === 0x1d2 ||
x === 0x1d4 ||
x === 0x1d6 ||
x === 0x1d8 ||
x === 0x1da ||
x === 0x1dc ||
x === 0x251 ||
x === 0x261 ||
x === 0x2c4 ||
x === 0x2c7 ||
(x >= 0x2c9 && x <= 0x2cb) ||
x === 0x2cd ||
x === 0x2d0 ||
(x >= 0x2d8 && x <= 0x2db) ||
x === 0x2dd ||
x === 0x2df ||
(x >= 0x300 && x <= 0x36f) ||
(x >= 0x391 && x <= 0x3a1) ||
(x >= 0x3a3 && x <= 0x3a9) ||
(x >= 0x3b1 && x <= 0x3c1) ||
(x >= 0x3c3 && x <= 0x3c9) ||
x === 0x401 ||
(x >= 0x410 && x <= 0x44f) ||
x === 0x451 ||
x === 0x2010 ||
(x >= 0x2013 && x <= 0x2016) ||
x === 0x2018 ||
x === 0x2019 ||
x === 0x201c ||
x === 0x201d ||
(x >= 0x2020 && x <= 0x2022) ||
(x >= 0x2024 && x <= 0x2027) ||
x === 0x2030 ||
x === 0x2032 ||
x === 0x2033 ||
x === 0x2035 ||
x === 0x203b ||
x === 0x203e ||
x === 0x2074 ||
x === 0x207f ||
(x >= 0x2081 && x <= 0x2084) ||
x === 0x20ac ||
x === 0x2103 ||
x === 0x2105 ||
x === 0x2109 ||
x === 0x2113 ||
x === 0x2116 ||
x === 0x2121 ||
x === 0x2122 ||
x === 0x2126 ||
x === 0x212b ||
x === 0x2153 ||
x === 0x2154 ||
(x >= 0x215b && x <= 0x215e) ||
(x >= 0x2160 && x <= 0x216b) ||
(x >= 0x2170 && x <= 0x2179) ||
x === 0x2189 ||
(x >= 0x2190 && x <= 0x2199) ||
x === 0x21b8 ||
x === 0x21b9 ||
x === 0x21d2 ||
x === 0x21d4 ||
x === 0x21e7 ||
x === 0x2200 ||
x === 0x2202 ||
x === 0x2203 ||
x === 0x2207 ||
x === 0x2208 ||
x === 0x220b ||
x === 0x220f ||
x === 0x2211 ||
x === 0x2215 ||
x === 0x221a ||
(x >= 0x221d && x <= 0x2220) ||
x === 0x2223 ||
x === 0x2225 ||
(x >= 0x2227 && x <= 0x222c) ||
x === 0x222e ||
(x >= 0x2234 && x <= 0x2237) ||
x === 0x223c ||
x === 0x223d ||
x === 0x2248 ||
x === 0x224c ||
x === 0x2252 ||
x === 0x2260 ||
x === 0x2261 ||
(x >= 0x2264 && x <= 0x2267) ||
x === 0x226a ||
x === 0x226b ||
x === 0x226e ||
x === 0x226f ||
x === 0x2282 ||
x === 0x2283 ||
x === 0x2286 ||
x === 0x2287 ||
x === 0x2295 ||
x === 0x2299 ||
x === 0x22a5 ||
x === 0x22bf ||
x === 0x2312 ||
(x >= 0x2460 && x <= 0x24e9) ||
(x >= 0x24eb && x <= 0x254b) ||
(x >= 0x2550 && x <= 0x2573) ||
(x >= 0x2580 && x <= 0x258f) ||
(x >= 0x2592 && x <= 0x2595) ||
x === 0x25a0 ||
x === 0x25a1 ||
(x >= 0x25a3 && x <= 0x25a9) ||
x === 0x25b2 ||
x === 0x25b3 ||
x === 0x25b6 ||
x === 0x25b7 ||
x === 0x25bc ||
x === 0x25bd ||
x === 0x25c0 ||
x === 0x25c1 ||
(x >= 0x25c6 && x <= 0x25c8) ||
x === 0x25cb ||
(x >= 0x25ce && x <= 0x25d1) ||
(x >= 0x25e2 && x <= 0x25e5) ||
x === 0x25ef ||
x === 0x2605 ||
x === 0x2606 ||
x === 0x2609 ||
x === 0x260e ||
x === 0x260f ||
x === 0x261c ||
x === 0x261e ||
x === 0x2640 ||
x === 0x2642 ||
x === 0x2660 ||
x === 0x2661 ||
(x >= 0x2663 && x <= 0x2665) ||
(x >= 0x2667 && x <= 0x266a) ||
x === 0x266c ||
x === 0x266d ||
x === 0x266f ||
x === 0x269e ||
x === 0x269f ||
x === 0x26bf ||
(x >= 0x26c6 && x <= 0x26cd) ||
(x >= 0x26cf && x <= 0x26d3) ||
(x >= 0x26d5 && x <= 0x26e1) ||
x === 0x26e3 ||
x === 0x26e8 ||
x === 0x26e9 ||
(x >= 0x26eb && x <= 0x26f1) ||
x === 0x26f4 ||
(x >= 0x26f6 && x <= 0x26f9) ||
x === 0x26fb ||
x === 0x26fc ||
x === 0x26fe ||
x === 0x26ff ||
x === 0x273d ||
(x >= 0x2776 && x <= 0x277f) ||
(x >= 0x2b56 && x <= 0x2b59) ||
(x >= 0x3248 && x <= 0x324f) ||
(x >= 0xe000 && x <= 0xf8ff) ||
(x >= 0xfe00 && x <= 0xfe0f) ||
x === 0xfffd ||
(x >= 0x1f100 && x <= 0x1f10a) ||
(x >= 0x1f110 && x <= 0x1f12d) ||
(x >= 0x1f130 && x <= 0x1f169) ||
(x >= 0x1f170 && x <= 0x1f18d) ||
x === 0x1f18f ||
x === 0x1f190 ||
(x >= 0x1f19b && x <= 0x1f1ac) ||
(x >= 0xe0100 && x <= 0xe01ef) ||
(x >= 0xf0000 && x <= 0xffffd) ||
(x >= 0x100000 && x <= 0x10fffd)
);
}
function isFullWidth(x) {
return x === 0x3000 || (x >= 0xff01 && x <= 0xff60) || (x >= 0xffe0 && x <= 0xffe6);
}
function isWide(x) {
return (
(x >= 0x1100 && x <= 0x115f) ||
x === 0x231a ||
x === 0x231b ||
x === 0x2329 ||
x === 0x232a ||
(x >= 0x23e9 && x <= 0x23ec) ||
x === 0x23f0 ||
x === 0x23f3 ||
x === 0x25fd ||
x === 0x25fe ||
x === 0x2614 ||
x === 0x2615 ||
(x >= 0x2648 && x <= 0x2653) ||
x === 0x267f ||
x === 0x2693 ||
x === 0x26a1 ||
x === 0x26aa ||
x === 0x26ab ||
x === 0x26bd ||
x === 0x26be ||
x === 0x26c4 ||
x === 0x26c5 ||
x === 0x26ce ||
x === 0x26d4 ||
x === 0x26ea ||
x === 0x26f2 ||
x === 0x26f3 ||
x === 0x26f5 ||
x === 0x26fa ||
x === 0x26fd ||
x === 0x2705 ||
x === 0x270a ||
x === 0x270b ||
x === 0x2728 ||
x === 0x274c ||
x === 0x274e ||
(x >= 0x2753 && x <= 0x2755) ||
x === 0x2757 ||
(x >= 0x2795 && x <= 0x2797) ||
x === 0x27b0 ||
x === 0x27bf ||
x === 0x2b1b ||
x === 0x2b1c ||
x === 0x2b50 ||
x === 0x2b55 ||
(x >= 0x2e80 && x <= 0x2e99) ||
(x >= 0x2e9b && x <= 0x2ef3) ||
(x >= 0x2f00 && x <= 0x2fd5) ||
(x >= 0x2ff0 && x <= 0x2fff) ||
(x >= 0x3001 && x <= 0x303e) ||
(x >= 0x3041 && x <= 0x3096) ||
(x >= 0x3099 && x <= 0x30ff) ||
(x >= 0x3105 && x <= 0x312f) ||
(x >= 0x3131 && x <= 0x318e) ||
(x >= 0x3190 && x <= 0x31e3) ||
(x >= 0x31ef && x <= 0x321e) ||
(x >= 0x3220 && x <= 0x3247) ||
(x >= 0x3250 && x <= 0x4dbf) ||
(x >= 0x4e00 && x <= 0xa48c) ||
(x >= 0xa490 && x <= 0xa4c6) ||
(x >= 0xa960 && x <= 0xa97c) ||
(x >= 0xac00 && x <= 0xd7a3) ||
(x >= 0xf900 && x <= 0xfaff) ||
(x >= 0xfe10 && x <= 0xfe19) ||
(x >= 0xfe30 && x <= 0xfe52) ||
(x >= 0xfe54 && x <= 0xfe66) ||
(x >= 0xfe68 && x <= 0xfe6b) ||
(x >= 0x16fe0 && x <= 0x16fe4) ||
x === 0x16ff0 ||
x === 0x16ff1 ||
(x >= 0x17000 && x <= 0x187f7) ||
(x >= 0x18800 && x <= 0x18cd5) ||
(x >= 0x18d00 && x <= 0x18d08) ||
(x >= 0x1aff0 && x <= 0x1aff3) ||
(x >= 0x1aff5 && x <= 0x1affb) ||
x === 0x1affd ||
x === 0x1affe ||
(x >= 0x1b000 && x <= 0x1b122) ||
x === 0x1b132 ||
(x >= 0x1b150 && x <= 0x1b152) ||
x === 0x1b155 ||
(x >= 0x1b164 && x <= 0x1b167) ||
(x >= 0x1b170 && x <= 0x1b2fb) ||
x === 0x1f004 ||
x === 0x1f0cf ||
x === 0x1f18e ||
(x >= 0x1f191 && x <= 0x1f19a) ||
(x >= 0x1f200 && x <= 0x1f202) ||
(x >= 0x1f210 && x <= 0x1f23b) ||
(x >= 0x1f240 && x <= 0x1f248) ||
x === 0x1f250 ||
x === 0x1f251 ||
(x >= 0x1f260 && x <= 0x1f265) ||
(x >= 0x1f300 && x <= 0x1f320) ||
(x >= 0x1f32d && x <= 0x1f335) ||
(x >= 0x1f337 && x <= 0x1f37c) ||
(x >= 0x1f37e && x <= 0x1f393) ||
(x >= 0x1f3a0 && x <= 0x1f3ca) ||
(x >= 0x1f3cf && x <= 0x1f3d3) ||
(x >= 0x1f3e0 && x <= 0x1f3f0) ||
x === 0x1f3f4 ||
(x >= 0x1f3f8 && x <= 0x1f43e) ||
x === 0x1f440 ||
(x >= 0x1f442 && x <= 0x1f4fc) ||
(x >= 0x1f4ff && x <= 0x1f53d) ||
(x >= 0x1f54b && x <= 0x1f54e) ||
(x >= 0x1f550 && x <= 0x1f567) ||
x === 0x1f57a ||
x === 0x1f595 ||
x === 0x1f596 ||
x === 0x1f5a4 ||
(x >= 0x1f5fb && x <= 0x1f64f) ||
(x >= 0x1f680 && x <= 0x1f6c5) ||
x === 0x1f6cc ||
(x >= 0x1f6d0 && x <= 0x1f6d2) ||
(x >= 0x1f6d5 && x <= 0x1f6d7) ||
(x >= 0x1f6dc && x <= 0x1f6df) ||
x === 0x1f6eb ||
x === 0x1f6ec ||
(x >= 0x1f6f4 && x <= 0x1f6fc) ||
(x >= 0x1f7e0 && x <= 0x1f7eb) ||
x === 0x1f7f0 ||
(x >= 0x1f90c && x <= 0x1f93a) ||
(x >= 0x1f93c && x <= 0x1f945) ||
(x >= 0x1f947 && x <= 0x1f9ff) ||
(x >= 0x1fa70 && x <= 0x1fa7c) ||
(x >= 0x1fa80 && x <= 0x1fa88) ||
(x >= 0x1fa90 && x <= 0x1fabd) ||
(x >= 0x1fabf && x <= 0x1fac5) ||
(x >= 0x1face && x <= 0x1fadb) ||
(x >= 0x1fae0 && x <= 0x1fae8) ||
(x >= 0x1faf0 && x <= 0x1faf8) ||
(x >= 0x20000 && x <= 0x2fffd) ||
(x >= 0x30000 && x <= 0x3fffd)
);
}
function validate(codePoint) {
if (!Number.isSafeInteger(codePoint)) {
throw new TypeError(`Expected a code point, got \`${typeof codePoint}\`.`);
}
}
function eastAsianWidth(codePoint, { ambiguousAsWide = false } = {}) {
validate(codePoint);
if (isFullWidth(codePoint) || isWide(codePoint) || (ambiguousAsWide && isAmbiguous(codePoint))) {
return 2;
}
return 1;
}
var emojiRegex = () => {
// https://mths.be/emoji
return /[#*0-9]\uFE0F?\u20E3|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26AA\u26B0\u26B1\u26BD\u26BE\u26C4\u26C8\u26CF\u26D1\u26E9\u26F0-\u26F5\u26F7\u26F8\u26FA\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B55\u3030\u303D\u3297\u3299]\uFE0F?|[\u261D\u270C\u270D](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|[\u270A\u270B](?:\uD83C[\uDFFB-\uDFFF])?|[\u23E9-\u23EC\u23F0\u23F3\u25FD\u2693\u26A1\u26AB\u26C5\u26CE\u26D4\u26EA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2795-\u2797\u27B0\u27BF\u2B50]|\u26D3\uFE0F?(?:\u200D\uD83D\uDCA5)?|\u26F9(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|\u2764\uFE0F?(?:\u200D(?:\uD83D\uDD25|\uD83E\uDE79))?|\uD83C(?:[\uDC04\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]\uFE0F?|[\uDF85\uDFC2\uDFC7](?:\uD83C[\uDFFB-\uDFFF])?|[\uDFC4\uDFCA](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDFCB\uDFCC](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF43\uDF45-\uDF4A\uDF4C-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|\uDF44(?:\u200D\uD83D\uDFEB)?|\uDF4B(?:\u200D\uD83D\uDFE9)?|\uDFC3(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDFF3\uFE0F?(?:\u200D(?:\u26A7\uFE0F?|\uD83C\uDF08))?|\uDFF4(?:\u200D\u2620\uFE0F?|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDC73\uDB40\uDC63\uDB40\uDC74|\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F)?)|\uD83D(?:[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3]\uFE0F?|[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4\uDEB5](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD74\uDD90](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC25\uDC27-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE41\uDE43\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEDC-\uDEDF\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB\uDFF0]|\uDC08(?:\u200D\u2B1B)?|\uDC15(?:\u200D\uD83E\uDDBA)?|\uDC26(?:\u200D(?:\u2B1B|\uD83D\uDD25))?|\uDC3B(?:\u200D\u2744\uFE0F?)?|\uDC41\uFE0F?(?:\u200D\uD83D\uDDE8\uFE0F?)?|\uDC68(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDC68\uDC69]\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE])))?))?|\uDC69(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?[\uDC68\uDC69]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?))|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFE])))?))?|\uDC6F(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDD75(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDE2E(?:\u200D\uD83D\uDCA8)?|\uDE35(?:\u200D\uD83D\uDCAB)?|\uDE36(?:\u200D\uD83C\uDF2B\uFE0F?)?|\uDE42(?:\u200D[\u2194\u2195]\uFE0F?)?|\uDEB6(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?)|\uD83E(?:[\uDD0C\uDD0F\uDD18-\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5\uDEC3-\uDEC5\uDEF0\uDEF2-\uDEF8](?:\uD83C[\uDFFB-\uDFFF])?|[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD\uDDCF\uDDD4\uDDD6-\uDDDD](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDDDE\uDDDF](?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD0D\uDD0E\uDD10-\uDD17\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCC\uDDD0\uDDE0-\uDDFF\uDE70-\uDE7C\uDE80-\uDE88\uDE90-\uDEBD\uDEBF-\uDEC2\uDECE-\uDEDB\uDEE0-\uDEE8]|\uDD3C(?:\u200D[\u2640\u2642]\uFE0F?|\uD83C[\uDFFB-\uDFFF])?|\uDDCE(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDDD1(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1|\uDDD1\u200D\uD83E\uDDD2(?:\u200D\uD83E\uDDD2)?|\uDDD2(?:\u200D\uD83E\uDDD2)?))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?))?|\uDEF1(?:\uD83C(?:\uDFFB(?:\u200D\uD83E\uDEF2\uD83C[\uDFFC-\uDFFF])?|\uDFFC(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFD-\uDFFF])?|\uDFFD(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])?|\uDFFE(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFD\uDFFF])?|\uDFFF(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFE])?))?)/g;
};
const segmenter = new Intl.Segmenter();
function stringWidth(string, options = {}) {
if (typeof string !== 'string' || string.length === 0) {
return 0;
}
const { ambiguousIsNarrow = true, countAnsiEscapeCodes = false } = options;
if (!countAnsiEscapeCodes) {
string = stripAnsi(string);
}
if (string.length === 0) {
return 0;
}
let width = 0;
const eastAsianWidthOptions = {
ambiguousAsWide: !ambiguousIsNarrow
};
for (const { segment: character } of segmenter.segment(string)) {
const codePoint = character.codePointAt(0);
// Ignore control characters
if (codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f)) {
continue;
}
// Ignore combining characters
if (codePoint >= 0x3_00 && codePoint <= 0x3_6f) {
continue;
}
if (emojiRegex().test(character)) {
width += 2;
continue;
}
width += eastAsianWidth(codePoint, eastAsianWidthOptions);
}
return width;
}
function getIndexOfNearestSpace(string, wantedIndex, shouldSearchRight) {
if (string.charAt(wantedIndex) === ' ') {
return wantedIndex;
}
const direction = shouldSearchRight ? 1 : -1;
for (let index = 0; index <= 3; index++) {
const finalIndex = wantedIndex + index * direction;
if (string.charAt(finalIndex) === ' ') {
return finalIndex;
}
}
return wantedIndex;
}
function cliTruncate(text, columns, options = {}) {
const { position = 'end', space = false, preferTruncationOnSpace = false } = options;
let { truncationCharacter = '…' } = options;
if (typeof text !== 'string') {
throw new TypeError(`Expected \`input\` to be a string, got ${typeof text}`);
}
if (typeof columns !== 'number') {
throw new TypeError(`Expected \`columns\` to be a number, got ${typeof columns}`);
}
if (columns < 1) {
return '';
}
if (columns === 1) {
return truncationCharacter;
}
const length = stringWidth(text);
if (length <= columns) {
return text;
}
if (position === 'start') {
if (preferTruncationOnSpace) {
const nearestSpace = getIndexOfNearestSpace(text, length - columns + 1, true);
return truncationCharacter + sliceAnsi(text, nearestSpace, length).trim();
}
if (space === true) {
truncationCharacter += ' ';
}
return (
truncationCharacter +
sliceAnsi(text, length - columns + stringWidth(truncationCharacter), length)
);
}
if (position === 'middle') {
if (space === true) {
truncationCharacter = ` ${truncationCharacter} `;
}
const half = Math.floor(columns / 2);
if (preferTruncationOnSpace) {
const spaceNearFirstBreakPoint = getIndexOfNearestSpace(text, half);
const spaceNearSecondBreakPoint = getIndexOfNearestSpace(
text,
length - (columns - half) + 1,
true
);
return (
sliceAnsi(text, 0, spaceNearFirstBreakPoint) +
truncationCharacter +
sliceAnsi(text, spaceNearSecondBreakPoint, length).trim()
);
}
return (
sliceAnsi(text, 0, half) +
truncationCharacter +
sliceAnsi(text, length - (columns - half) + stringWidth(truncationCharacter), length)
);
}
if (position === 'end') {
if (preferTruncationOnSpace) {
const nearestSpace = getIndexOfNearestSpace(text, columns - 1);
return sliceAnsi(text, 0, nearestSpace) + truncationCharacter;
}
if (space === true) {
truncationCharacter = ` ${truncationCharacter}`;
}
return sliceAnsi(text, 0, columns - stringWidth(truncationCharacter)) + truncationCharacter;
}
throw new Error(
`Expected \`options.position\` to be either \`start\`, \`middle\` or \`end\`, got ${position}`
);
}
const cliSymbols = {
arrowUp: '↑',
arrowRight: '→',
arrowBottom: '↓',
enter: '↳',
cross: '×',
longDash: '─',
longArrowRight: '⇢',
more: '…',
pointer: '❯',
pointerSmall: '›',
pointerSmallDouble: '»'
};
const cliColumns = process.stdout.columns || 80;
// eslint-disable-next-line @typescript-eslint/prefer-includes
const getNewLineLength = source => (/\r\n/.test(source) ? 2 : 1);
function getPointerOffset(source, lineNumber, columnNumber) {
const lines = source.split(newlineRe);
if (lineNumber > lines.length) {
return source.length;
}
const newLineLength = getNewLineLength(source);
return sum(fromLength(lineNumber - 1, no => lines[no].length + newLineLength)) + columnNumber;
}
const newlineRe = /\r?\n/;
function printCodeFrame({
colors: colors$1 = colors.colors,
indent = 0,
columnNumber,
lineNumber,
source,
overscan = 2
}) {
const newLineLength = getNewLineLength(source);
const pointerOffset = getPointerOffset(source, lineNumber, columnNumber);
const lines = source.split(newlineRe);
const lineOffset = sum(lines.slice(0, lineNumber).map(line => line.length + newLineLength));
const startIndex = Math.max(0, lineNumber - 1 - overscan);
const printedLines = lines.slice(startIndex, lineNumber + overscan);
if (printedLines.length === 0 || printedLines.some(isMinifiedCodeLike)) return '';
const printUnderline = (line, offset) =>
fillSpace(offset) + colors$1.red('^'.repeat(Math.max(1, line.length - offset)));
const printLineNo = (no = '') => colors$1.gray(`${no.padStart(3, ' ')}| `);
return printedLines
.flatMap((line, index) => {
const lineNo = startIndex + index + 1;
const isCurrentLine = lineNo === lineNumber;
const color = isCurrentLine ? colors$1.yellowBright : colors$1.yellow;
return [
cliTruncate(
printLineNo(String(lineNo)) + color(line.replace(/\t/g, ' ')),
cliColumns - indent
),
isCurrentLine &&
printLineNo() + printUnderline(line, pointerOffset - (lineOffset - line.length))
];
})
.filter(Boolean)
.map(line => (indent ? fillSpace(indent) + line : line))
.join('\n');
}
// to long, maybe it's a minified file, skip for codeframe
const isMinifiedCodeLike = code => code.length > 240;
const fillSpace = length => ' '.repeat(Math.max(length, 0));
/**
* Serialize an error into a plain object that can be serialized into JSON then.
*/ function serializeError(error) {
if (!(error instanceof Error)) return error;
const result = {
name: error.name,
stack: error.stack,
message: error.message,
...(getErrorCustomProperties(error) ?? {})
};
if (error.cause instanceof Error) {
result.cause = serializeError(error.cause);
}
return result;
}
function getErrorCustomProperties(error) {
const errorProperties = omit(Object.fromEntries(Object.entries(error)), builtInErrorProps);
return readArguments.isEmptyObject(errorProperties) ? null : errorProperties;
}
const builtInErrorProps = ['stack', 'cause', 'name', 'message'];
const parseStackTraces = (originalTrace, filter = notInternals) =>
originalTrace
.split('\n')
.map(parseSingleStack)
.filter(stack => stack !== null && filter(stack));
// Based on https://github.com/stacktracejs/error-stack-parser
// Credit to stacktracejs
function parseSingleStack(raw) {
let line = raw.trim();
if (line.includes('(eval ')) {
line = line.replace(/eval code/g, 'eval').replace(/(\(eval at [^()]*)|(,.*$)/g, '');
}
let sanitizedLine = line
.replace(/^\s+/, '')
.replace(/\(eval code/g, '(')
.replace(/^.*?\s+/, '');
// capture and preserve the parenthesized location "(/foo/my bar.js:12:87)" in
// case it has spaces in it, as the string is split on \s+ later on
const location = sanitizedLine.match(/ (\(.+\)$)/);
if (location) {
// remove the parenthesized location from the line, if it was matched
sanitizedLine = sanitizedLine.replace(location[0], '');
}
// if a location was matched, pass it to extractLocation() otherwise pass all sanitizedLine
// because this line doesn't have function name
const [url, lineNumber, columnNumber] = parseTraceLocation(
location ? location[1] : sanitizedLine
);
let method = (location && sanitizedLine) || '';
let file = url && ['eval', '<anonymous>'].includes(url) ? undefined : url;
if (!file || !lineNumber || !columnNumber) return null;
if (method.startsWith('async ')) method = method.slice(6);
if (file.startsWith('file://')) file = file.slice(7);
return {
// normalize Windows path (\ -> /)
file: pathe.resolve(file),
line: readArguments.toInt(lineNumber),
column: readArguments.toInt(columnNumber),
method
};
}
function parseTraceLocation(urlLike) {
// Fail-fast but return locations like "(native)"
if (!urlLike.includes(':')) return [urlLike];
return LOCATIONS_RE.exec(urlLike.replace(/^\(|\)$/g, ''))?.slice(1, 4) ?? [urlLike];
}
const LOCATIONS_RE = /(.+?)(?::(\d+))?(?::(\d+))?$/;
const notInternals = stack => !stack.file.match('node:internal');
function printPrettyError(originalError, options = {}) {
const {
cwd = process.cwd(),
indent = 0,
codeFrame = true,
fullStack = false,
stringify = value => utils_index.serializeJSON(value, 2),
filterStack,
colors: colors$1 = colors.colors
} = options;
const getHighlightedStacks = codeFrame ? toCodeFrameCondition(codeFrame) : null;
const error = toError(originalError);
const stacks = parseStackTraces(error.stack || '', fullStack ? readArguments.True : filterStack);
const errorProperties = getErrorCustomProperties(error);
const highlightedStacks = readArguments.toArray(getHighlightedStacks?.(stacks) ?? []);
const prefix = (value = indent) => (value ? ' '.repeat(value) : '');
const messageParts = stacks.flatMap(stack => {
const { file, column, line, method } = stack;
const highlighted = highlightedStacks.includes(stack);
const color = highlighted ? colors$1.cyan : colors$1.gray;
const path = pathe.relative(cwd, file);
return [
color(
`${prefix()} ${colors$1.dim(highlighted ? cliSymbols.pointerSmallDouble : cliSymbols.pointerSmall)} ${[
method,
`${prefix()}${path}:${colors$1.dim(`${line}:${column}`)}`
]
.filter(Boolean)
.join(' ')}`
),
highlighted &&
colors$1.yellow(
printCodeFrame({
lineNumber: line,
columnNumber: column,
source: node_fs.readFileSync(file, 'utf-8'),
indent: indent + 3,
colors: colors$1
})
)
];
});
if (errorProperties) {
messageParts.push(
`${prefix()}${colors$1.red(`${cliSymbols.longArrowRight} serialized error properties:`)}`,
`${colors$1.gray(
stringify(errorProperties)
.split(newlineRe)
.map(line => `${prefix()}${line}`)
.slice(1, -1)
.join('\n')
)}`
);
}
if (error.cause && typeof error.cause === 'object' && 'name' in error.cause) {
error.cause.name = `${cliSymbols.enter} caused by ${error.cause.name}`;
messageParts.push(
' ',
printPrettyError(error.cause, {
...options,
indent: indent + 2,
codeFrame: false
})
);
}
return [
colors$1.red(`${prefix()}${colors$1.bold(error.name || 'Unknown Error')}: ${error.message}`),
...messageParts
]
.filter(Boolean)
.join('\n');
}
const toCodeFrameCondition = codeFrame =>
typeof codeFrame === 'function'
? codeFrame
: stacks => stacks.find(stack => node_fs.existsSync(stack.file));
const toError = error => {
if (!error) {
return pick(new Error('unknown error'), ['message', 'stack']);
}
if (readArguments.isPrimitive(error)) {
const stack = String(error);
return {
message: stack.split(/\n/g)[0],
stack
};
}
return error;
};
// TODO https://linear.app/secundant/issue/SEC-42/neodxlog-top-level-serializers-api
function serializeMeta(meta, serializers) {
if (!serializers) return meta;
const result = {};
for (const [key, value] of Object.entries(meta)) {
result[key] = readArguments.hasOwn(serializers, key) ? serializers[key](value) : value;
}
return result;
}
const DEFAULT_SERIALIZERS = {
req: serializeHttpRequest,
res: serializeHttpResponse,
err: serializeError
};
function file(filename, options) {
return json({
target: node_fs.createWriteStream(filename),
...options
});
}
function json({
target = process.stdout,
dateKey = 'time',
errorKey = 'err',
messageKey = 'msg',
serializers = DEFAULT_SERIALIZERS,
levelValueKey = 'level'
} = {}) {
const write = 'writable' in target ? target.write.bind(target) : target;
return function handleLog({ msg, error, meta, level, name, date, __: { levels } }) {
const info = Object.assign(
{
[levelValueKey]: levels[level],
[dateKey]: date.getTime(),
[errorKey]: error && serializeError(error),
[messageKey]: msg
},
name && {
name
},
serializeMeta(meta, serializers)
);
write(utils_index.serializeJSON(info) + '\n');
};
}
/**
* Creates a pretty log handler for development mode in node.
*/ function pretty({
// eslint-disable-next-line no-console
log = console.log,
logError = console.error,
colors: colors$1 = colors.colors,
displayMs = false,
serializers = DEFAULT_SERIALIZERS,
displayTime = true,
displayLevel = true,
prettyErrors = true,
levelColors = defaultLevelColors,
levelBadges = defaultLevelBadges
} = {}) {
const getLevelSetting = (settings, level) =>
settings && readArguments.hasOwn(settings, level) ? settings[level] : null;
const maxBadgesLength = levelBadges
? Math.max(...readArguments.values(levelBadges).map(b => String(b).length))
: 0;
const prettyErrorCustomOptions = {
colors: colors$1,
...(readArguments.isObject(prettyErrors) ?