@mmutils/logger 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1038 -2
- package/dist/cjs/index.cjs +72 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/levels.cjs +82 -0
- package/dist/cjs/levels.cjs.map +1 -0
- package/dist/cjs/logger.cjs +576 -0
- package/dist/cjs/logger.cjs.map +1 -0
- package/dist/cjs/outputs.cjs +24 -0
- package/dist/cjs/outputs.cjs.map +1 -0
- package/dist/cjs/plugins/columns.cjs +782 -0
- package/dist/cjs/plugins/columns.cjs.map +1 -0
- package/dist/cjs/plugins/graph.cjs +578 -0
- package/dist/cjs/plugins/graph.cjs.map +1 -0
- package/dist/cjs/plugins/json.cjs +644 -0
- package/dist/cjs/plugins/json.cjs.map +1 -0
- package/dist/cjs/plugins/message.cjs +108 -0
- package/dist/cjs/plugins/message.cjs.map +1 -0
- package/dist/cjs/plugins/shared.cjs +194 -0
- package/dist/cjs/plugins/shared.cjs.map +1 -0
- package/dist/cjs/time.cjs +234 -0
- package/dist/cjs/time.cjs.map +1 -0
- package/dist/cjs/utils/text.cjs +646 -0
- package/dist/cjs/utils/text.cjs.map +1 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/levels.js +72 -0
- package/dist/esm/levels.js.map +1 -0
- package/dist/esm/logger.js +572 -0
- package/dist/esm/logger.js.map +1 -0
- package/dist/esm/outputs.js +21 -0
- package/dist/esm/outputs.js.map +1 -0
- package/dist/esm/plugins/columns.js +778 -0
- package/dist/esm/plugins/columns.js.map +1 -0
- package/dist/esm/plugins/graph.js +572 -0
- package/dist/esm/plugins/graph.js.map +1 -0
- package/dist/esm/plugins/json.js +641 -0
- package/dist/esm/plugins/json.js.map +1 -0
- package/dist/esm/plugins/message.js +105 -0
- package/dist/esm/plugins/message.js.map +1 -0
- package/dist/esm/plugins/shared.js +187 -0
- package/dist/esm/plugins/shared.js.map +1 -0
- package/dist/esm/time.js +231 -0
- package/dist/esm/time.js.map +1 -0
- package/dist/esm/utils/text.js +621 -0
- package/dist/esm/utils/text.js.map +1 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/levels.d.ts +50 -0
- package/dist/types/logger.d.ts +245 -0
- package/dist/types/outputs.d.ts +12 -0
- package/dist/types/plugins/columns.d.ts +151 -0
- package/dist/types/plugins/graph.d.ts +243 -0
- package/dist/types/plugins/json.d.ts +169 -0
- package/dist/types/plugins/message.d.ts +181 -0
- package/dist/types/plugins/shared.d.ts +74 -0
- package/dist/types/time.d.ts +48 -0
- package/dist/types/types.d.ts +176 -0
- package/dist/types/utils/text.d.ts +231 -0
- package/package.json +85 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sources":["../../../src/plugins/json.ts"],"sourcesContent":["import { LOG_TYPE_VALUES } from '../levels.js';\nimport type { LogEntry, LoggerPlugin } from '../types.js';\nimport {\n DEFAULT_OUTPUT_LIMITS,\n describeBinary,\n describeFunction,\n describeLeftOut,\n describeObject,\n describeThrown,\n isForeignError,\n resolveOutputLimits,\n truncate,\n type OutputLimits,\n} from '../utils/text.js';\nimport { compileTimestamp } from '../time.js';\n\ntype Limits = Required<OutputLimits>;\n\n/**\n * Time of a JSON line, in its `time` property, from the logger's clock:\n * - `'iso'`: ISO 8601 in UTC, a string: `\"2026-03-16T15:35:00.000Z\"`, with\n * 9 fraction digits with the `'precise'` clock;\n * - `'epoch'`: epoch milliseconds, a number: `1773675300000`; with the\n * `'precise'` clock followed by `\"ns\"`, the nanoseconds within the\n * millisecond;\n * - `false`: no `time`.\n */\nexport type JsonTime = 'epoch' | 'iso' | false;\n\nexport interface JsonPluginOptions {\n /** Kind rendered by this plugin. Default: `'json'`. */\n readonly kind?: string;\n /**\n * Make `kind` the logger's default kind, so all logs without an explicit\n * kind are written as JSON lines. The last plugin used that sets the\n * default wins. Use `jsonPlugin` instead of `messagePlugin`, not next to\n * it: both render the whole log. Default: `true`.\n */\n readonly setAsDefault?: boolean;\n /**\n * Format of the `time` property, from the logger's `clock`. Lines have no\n * time when the logger's `timestamp` is `false`. Default: `'iso'`.\n */\n readonly time?: JsonTime;\n /**\n * Output size limits: elements and keys per object, characters per string\n * and per nested JSON value. `Infinity` turns a limit off. Default:\n * `DEFAULT_OUTPUT_LIMITS` (`{ items: 100, stringLength: 10_000 }`).\n */\n readonly limits?: OutputLimits;\n /**\n * Also escape DEL and C1 control characters (`U+007F`-`U+009F`) as\n * `\\u00XX`. `JSON.stringify` escapes C0 controls (including ESC and\n * newlines) but writes these raw; some terminals act on C1 controls when\n * the lines are shown raw (`cat`, `tail -f`). The parsed JSON is the same.\n * Costs about 1 ns per character. Default: `false`.\n */\n readonly escapeControls?: boolean;\n /**\n * Write the log's `kind` after `type`, e.g. `\"kind\":\"audit\"`. Turn it on\n * when several JSON kinds share a destination (all logs to stdout in a\n * container), so readers can tell them apart. Default: `false` (one\n * destination per kind makes it redundant).\n */\n readonly writeKind?: boolean;\n /** Line destination, called once per log. Default: `console.log`. */\n readonly write?: (line: string) => void;\n}\n\n/**\n * Most causes serialized per error; deeper causes are summarized as\n * `\"Name: message\"`. A cause already in the chain is `\"[Circular]\"`.\n */\nconst MAX_CAUSES = 5;\n\nconst NO_CAUSES: readonly object[] = [];\n\n/**\n * Depth of a value in the logged data. Values at `DATA` (the data itself)\n * and `PROPERTY` (its properties or elements) get special handling: errors,\n * binary data, bigints, functions, long strings and arrays. Objects at `DATA`\n * are also walked key by key when native JSON would lose something. `LEAF`\n * values (error properties) are handled like `PROPERTY` ones, except nested\n * errors, which are summarized, so error graphs can't multiply.\n */\nconst DATA = 0;\nconst PROPERTY = 1;\nconst LEAF = 2;\ntype Depth = typeof DATA | typeof PROPERTY | typeof LEAF;\n\nconst quote = (text: string): string => JSON.stringify(text);\n\nconst quoteLimited = (text: string, limits: Limits): string =>\n JSON.stringify(truncate(text, limits.stringLength));\n\nconst placeholder = (prefix: string, thrown: unknown, limits: Limits): string =>\n quoteLimited(`[${prefix}: ${describeThrown(thrown)}]`, limits);\n\n/**\n * Appends `\"key\":json` to the inside of an object. Values without JSON\n * (`undefined`) are left out, like `JSON.stringify` does.\n */\nconst appendProperty = (\n text: string,\n quotedKey: string,\n json: string | undefined\n): string =>\n json === undefined ? text : `${text}${text ? ',' : ''}${quotedKey}:${json}`;\n\n/**\n * Levels a too long value is cut into while keeping its type; deeper, the\n * value becomes a cut string.\n */\nconst MAX_CUT_LEVELS = 4;\n\nconst NO_ANCESTORS: readonly object[] = [];\n\n/**\n * Objects native JSON writes as objects from their own enumerable keys: not\n * arrays, and without `toJSON` (dates are written as strings).\n */\nconst isKeyedObject = (value: unknown): value is object =>\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n typeof (value as { toJSON?: unknown }).toJSON !== 'function';\n\n/**\n * Native JSON of a value, like `JSON.stringify` (`undefined` for functions,\n * symbols and `undefined`), or a placeholder if it can't be serialized.\n */\nconst elementJson = (value: unknown, limits: Limits): string | undefined => {\n try {\n return JSON.stringify(value);\n } catch (thrown) {\n return placeholder('Unserializable', thrown, limits);\n }\n};\n\n/**\n * JSON of an element or property inside a cut value: `\"[Circular]\"` if it\n * is one of the values being cut around it, native JSON when that works,\n * otherwise (a cycle further down, a nested bigint) cut the same way, so it\n * keeps its type too. A throwing getter gives a placeholder.\n *\n * @param ancestors The values being cut, the container included.\n */\nconst childJson = (\n read: () => unknown,\n room: number,\n limits: Limits,\n ancestors: readonly object[]\n): string | undefined => {\n let child: unknown;\n try {\n child = read();\n } catch (thrown) {\n return placeholder('Getter threw', thrown, limits);\n }\n if (typeof child === 'object' && child !== null && ancestors.includes(child))\n return '\"[Circular]\"';\n try {\n return JSON.stringify(child);\n } catch {\n return cutJson(child, room, limits, ancestors);\n }\n};\n\n/**\n * JSON of a value that is too long, cut to about `budget` characters while\n * keeping its type, so collectors that map fields by type (Elasticsearch)\n * accept the line: see `cutArray` and `cutObject`. Other values (strings,\n * dates, values deeper than `MAX_CUT_LEVELS`) become a cut string. A value\n * that contains itself is `\"[Circular]\"`.\n *\n * @param ancestors Arrays and objects being cut around this value.\n */\nconst cutJson = (\n value: unknown,\n budget: number,\n limits: Limits,\n ancestors: readonly object[]\n): string => {\n if (typeof value === 'object' && value !== null && ancestors.includes(value))\n return '\"[Circular]\"';\n if (ancestors.length < MAX_CUT_LEVELS) {\n if (Array.isArray(value)) return cutArray(value, budget, limits, ancestors);\n if (isKeyedObject(value))\n return cutObject(value, budget, limits, ancestors);\n }\n // a JSON number with every digit, like bigints elsewhere in the data\n if (typeof value === 'bigint') return String(value);\n const json = elementJson(value, limits) ?? 'null';\n if (json.length <= budget) return json;\n // cut the text of strings (also placeholders), the JSON of other values\n const text =\n typeof value === 'string' ? value\n : json.startsWith('\"') ? (JSON.parse(json) as string)\n : json;\n return quote(truncate(text, Math.max(1, budget - 2)));\n};\n\n/**\n * An array cut to about `budget` characters: elements while they fit, at\n * most `items`, then a `\"… N more items\"` element. A first element that\n * alone doesn't fit is cut the same way. The cost grows with `budget`, not\n * with the array: elements are serialized one by one until one doesn't fit.\n */\nconst cutArray = (\n array: readonly unknown[],\n budget: number,\n limits: Limits,\n ancestors: readonly object[]\n): string => {\n const max = Math.min(array.length, limits.items);\n const inner = [...ancestors, array];\n let text = '';\n let shown = 0;\n for (; shown < max; shown++) {\n const index = shown;\n // room inside the brackets, after the separator\n const room = budget - text.length - 2 - (shown ? 1 : 0);\n const json = childJson(() => array[index], room, limits, inner) ?? 'null';\n if (json.length <= room) {\n text += `${shown ? ',' : ''}${json}`;\n continue;\n }\n if (!shown) {\n text = cutJson(array[0], room, limits, inner);\n shown = 1;\n }\n break;\n }\n const more = array.length - shown;\n return `[${text}${more ? `${text ? ',' : ''}${quote(describeLeftOut(more, 'item'))}` : ''}]`;\n};\n\n/**\n * An object cut to about `budget` characters: properties while they fit, at\n * most `items`, then `\"…\": \"… N more items\"`. A first property whose value\n * alone doesn't fit is cut the same way.\n */\nconst cutObject = (\n object: object,\n budget: number,\n limits: Limits,\n ancestors: readonly object[]\n): string => {\n const keys = Object.keys(object);\n const max = Math.min(keys.length, limits.items);\n const inner = [...ancestors, object];\n const read = (key: string) => (object as Record<string, unknown>)[key];\n let text = '';\n let shown = 0;\n for (; shown < max; shown++) {\n const key = keys[shown] ?? '';\n const property = `${quoteLimited(key, limits)}:`;\n const room = budget - text.length - 2 - (text ? 1 : 0) - property.length;\n const json = childJson(() => read(key), room, limits, inner);\n // left out by JSON (functions, symbols, undefined): counted as shown\n if (json === undefined) continue;\n if (json.length <= room) {\n text += `${text ? ',' : ''}${property}${json}`;\n continue;\n }\n if (!text) {\n text = `${property}${cutJson(read(key), room, limits, inner)}`;\n shown++;\n }\n break;\n }\n const more = keys.length - shown;\n return `{${text}${more ? `${text ? ',' : ''}\"…\":${quote(describeLeftOut(more, 'item'))}` : ''}}`;\n};\n\n/**\n * Counts own enumerable keys, stopping after `max + 1`: enough to know if\n * an object has more than `max` without listing all keys.\n */\nconst countKeys = (object: object, max: number): number => {\n let count = 0;\n // no hasOwn check (it doubles the cost): enumerable keys added to\n // Object.prototype by other code can only overcount, which cuts with\n // Object.keys and still writes the object's real keys\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- counting\n for (const _ in object) if (++count > max) break;\n return count;\n};\n\n/**\n * Native JSON of an object. A text longer than `stringLength` is cut\n * keeping its type (`cutJson`); plain objects with more than `items` keys\n * are cut the same way. Objects JSON shows as `{}` (maps, sets, regular\n * expressions) are described instead.\n *\n * @throws Whatever `JSON.stringify` throws: callers catch it.\n */\nconst nativeJson = (value: object, limits: Limits): string | undefined => {\n if (isKeyedObject(value) && countKeys(value, limits.items) > limits.items)\n return cutObject(value, limits.stringLength, limits, NO_ANCESTORS);\n const text = JSON.stringify(value) as string | undefined;\n if (text === undefined) return undefined;\n if (text === '{}') {\n const described = describeObject(value, limits);\n if (described !== undefined) return quoteLimited(described, limits);\n }\n return text.length > limits.stringLength ?\n cutJson(value, limits.stringLength, limits, NO_ANCESTORS)\n : text;\n};\n\n/**\n * Prototypes whose instances native JSON serializes completely, as long as\n * their own values do: plain objects, null-prototype objects, arrays, dates.\n */\nconst isPlainPrototype = (proto: unknown): boolean =>\n proto === Object.prototype ||\n proto === null ||\n proto === Array.prototype ||\n proto === Date.prototype;\n\n/**\n * A property value native JSON serializes the same as the walk does, within\n * the limits. One cheap check per value of the logged data, so ordinary data\n * keeps the speed of a single native `JSON.stringify`.\n */\nconst isNativeSafe = (value: unknown, limits: Limits): boolean => {\n switch (typeof value) {\n case 'string':\n return value.length <= limits.stringLength;\n case 'number':\n case 'boolean':\n case 'undefined':\n return true;\n case 'object':\n return (\n value === null ||\n (isPlainPrototype(Object.getPrototypeOf(value)) &&\n !(Array.isArray(value) && value.length > limits.items))\n );\n default:\n // bigint (native JSON throws), function and symbol (left out)\n return false;\n }\n};\n\n/**\n * Data whose values are all native safe: one native `JSON.stringify`.\n * `undefined` when a value is not, or reading or serializing throws\n * (circular structures, throwing getters, revoked proxies, nested bigints),\n * or the text exceeds `stringLength`: the data is walked instead.\n */\nconst tryNative = (\n data: object,\n isArray: boolean,\n limits: Limits\n): string | undefined => {\n try {\n if (isArray) {\n const array = data as readonly unknown[];\n const { length } = array;\n if (length > limits.items) return undefined;\n for (let index = 0; index < length; index++)\n if (!isNativeSafe(array[index], limits)) return undefined;\n } else {\n let count = 0;\n for (const key in data)\n if (\n ++count > limits.items ||\n !isNativeSafe((data as Record<string, unknown>)[key], limits)\n )\n return undefined;\n }\n const text = JSON.stringify(data);\n if (text.length > limits.stringLength) return undefined;\n // a key takes at least 5 characters (`\"\":0,`): shorter text can't hold\n // an object with more than `items` keys, so ordinary data skips the scan\n if (\n text.length > MIN_KEY_LENGTH * limits.items &&\n hasLongObject(data, isArray, limits)\n )\n return undefined;\n return text;\n } catch {\n return undefined;\n }\n};\n\n/**\n * Shortest JSON of an object key with its value and separator: `\"\":0,`.\n */\nconst MIN_KEY_LENGTH = 5;\n\n/**\n * Whether a value of the data (one level deep, like errors) is an object\n * with more than `items` keys, which native JSON would write whole.\n */\nconst hasLongObject = (\n data: object,\n isArray: boolean,\n limits: Limits\n): boolean => {\n const isLong = (value: unknown): boolean =>\n isKeyedObject(value) && countKeys(value, limits.items) > limits.items;\n if (isArray) {\n for (const value of data as readonly unknown[])\n if (isLong(value)) return true;\n return false;\n }\n // no Object.values: it allocates an array per log\n for (const key in data)\n if (isLong((data as Record<string, unknown>)[key])) return true;\n return false;\n};\n\n/**\n * JSON of a property, element or error property. A throwing getter gives a\n * placeholder, so one bad property doesn't hide the others.\n */\nconst readProperty = (\n data: object,\n key: string | number,\n depth: Depth,\n limits: Limits\n): string | undefined => {\n let value: unknown;\n try {\n value = (data as Record<string | number, unknown>)[key];\n } catch (thrown) {\n return placeholder('Getter threw', thrown, limits);\n }\n return stringifyValue(value, depth, limits);\n};\n\n/**\n * Logged data that is an array: each element serialized on its own (errors,\n * binary data, ...), at most `items`, then a `\"… N more items\"` element.\n */\nconst walkArray = (array: readonly unknown[], limits: Limits): string => {\n const shown = Math.min(array.length, limits.items);\n let text = '';\n for (let index = 0; index < shown; index++)\n text += `${index ? ',' : ''}${readProperty(array, index, PROPERTY, limits) ?? 'null'}`;\n if (array.length > shown)\n text += `,${quote(describeLeftOut(array.length - shown, 'item'))}`;\n return `[${text}]`;\n};\n\n/**\n * Logged data that is an object: own enumerable keys (like JSON), each value\n * serialized on its own, at most `items` keys, then `\"…\": \"… N more items\"`.\n * A throwing getter gives a placeholder and the other keys still render.\n */\nconst walkObject = (data: object, limits: Limits): string | undefined => {\n if (typeof (data as { toJSON?: unknown }).toJSON === 'function')\n return nativeJson(data, limits);\n const keys = Object.keys(data);\n const shown = Math.min(keys.length, limits.items);\n let text = '';\n for (let index = 0; index < shown; index++) {\n const key = keys[index] ?? '';\n text = appendProperty(\n text,\n quoteLimited(key, limits),\n readProperty(data, key, PROPERTY, limits)\n );\n }\n if (keys.length > shown)\n text = appendProperty(\n text,\n '\"…\"',\n quote(describeLeftOut(keys.length - shown, 'item'))\n );\n return `{${text}}`;\n};\n\n/**\n * A property or element that is an array: longer than `items`, its first\n * `items` elements (native JSON) and a `\"… N more items\"` element, without\n * serializing the rest.\n */\nconst limitArray = (\n array: readonly unknown[],\n limits: Limits\n): string | undefined => {\n if (array.length <= limits.items) return nativeJson(array, limits);\n const head = JSON.stringify(array.slice(0, limits.items));\n const text = `${head.slice(0, -1)},${quote(describeLeftOut(array.length - limits.items, 'item'))}]`;\n return text.length > limits.stringLength ?\n cutArray(array, limits.stringLength, limits, NO_ANCESTORS)\n : text;\n};\n\n/**\n * Error properties written first (or last, `cause`), not repeated when an\n * error makes them enumerable.\n */\nconst ERROR_KEYS = new Set(['name', 'message', 'stack', 'cause']);\n\nconst isErrorLike = (value: unknown): value is object =>\n value instanceof Error ||\n (typeof value === 'object' && value !== null && isForeignError(value));\n\n/**\n * `{\"name\",\"message\",\"stack\",...own enumerable properties,\"cause\"}`. Name,\n * message and stack are not enumerable, so native JSON drops them. Each part\n * is read on its own: an unreadable one gives a placeholder, the others\n * still render.\n *\n * @param chain Errors this one is the cause of, outermost first.\n */\nconst stringifyError = (\n error: object,\n chain: readonly object[],\n limits: Limits\n): string => {\n let text = appendProperty(\n '',\n '\"name\"',\n readProperty(error, 'name', LEAF, limits)\n );\n text = appendProperty(\n text,\n '\"message\"',\n readProperty(error, 'message', LEAF, limits)\n );\n text = appendProperty(\n text,\n '\"stack\"',\n readProperty(error, 'stack', LEAF, limits)\n );\n let keys: string[] = [];\n try {\n keys = Object.keys(error).filter((key) => !ERROR_KEYS.has(key));\n } catch {\n // keys of a throwing proxy are left out; name, message and stack stay\n }\n const shown = Math.min(keys.length, limits.items);\n for (let index = 0; index < shown; index++) {\n const key = keys[index] ?? '';\n text = appendProperty(\n text,\n quoteLimited(key, limits),\n readProperty(error, key, LEAF, limits)\n );\n }\n if (keys.length > shown)\n text = appendProperty(\n text,\n '\"…\"',\n quote(describeLeftOut(keys.length - shown, 'item'))\n );\n let cause: unknown;\n try {\n if (!Object.hasOwn(error, 'cause')) return `{${text}}`;\n cause = (error as { cause?: unknown }).cause;\n } catch (thrown) {\n return `{${appendProperty(text, '\"cause\"', placeholder('Getter threw', thrown, limits))}}`;\n }\n const json =\n !isErrorLike(cause) ? stringifyValue(cause, LEAF, limits)\n : cause === error || chain.includes(cause) ? '\"[Circular]\"'\n : chain.length < MAX_CAUSES ?\n stringifyError(cause, [...chain, error], limits)\n : quoteLimited(describeThrown(cause), limits);\n return `{${appendProperty(text, '\"cause\"', json)}}`;\n};\n\n/**\n * Native JSON of a nested array or object, or, when native JSON throws (a\n * circular element, a throwing getter, a nested bigint), the same value cut\n * element by element: the bad element becomes a placeholder and the value\n * keeps its type.\n */\nconst keepingType = (\n native: () => string | undefined,\n value: object,\n limits: Limits\n): string | undefined => {\n try {\n return native();\n } catch {\n return cutJson(value, limits.stringLength, limits, NO_ANCESTORS);\n }\n};\n\nconst stringifyObject = (\n value: object,\n depth: Depth,\n limits: Limits\n): string | undefined => {\n const proto: unknown = Object.getPrototypeOf(value);\n if (proto === Object.prototype || proto === null)\n return depth === DATA ?\n (tryNative(value, false, limits) ?? walkObject(value, limits))\n : keepingType(() => nativeJson(value, limits), value, limits);\n if (Array.isArray(value))\n return depth === DATA ?\n (tryNative(value, true, limits) ?? walkArray(value, limits))\n : keepingType(() => limitArray(value, limits), value, limits);\n if (value instanceof Error || isForeignError(value))\n return depth === LEAF ?\n quoteLimited(describeThrown(value), limits)\n : stringifyError(value, NO_CAUSES, limits);\n if (ArrayBuffer.isView(value))\n return quoteLimited(describeBinary(value, limits.items), limits);\n // dates, class instances, maps, sets, ...\n return nativeJson(value, limits);\n};\n\n/**\n * JSON of a value, or `undefined` for values JSON leaves out.\n */\nconst stringifyValue = (\n value: unknown,\n depth: Depth,\n limits: Limits\n): string | undefined => {\n try {\n switch (typeof value) {\n case 'string':\n return value.length > limits.stringLength ?\n quoteLimited(value, limits)\n : quote(value);\n case 'number':\n return Number.isFinite(value) ? String(value) : 'null';\n case 'boolean':\n return value ? 'true' : 'false';\n case 'bigint':\n // a JSON number with every digit; `JSON.parse` rounds large ones\n return String(value);\n case 'undefined':\n return undefined;\n case 'function':\n return quote(describeFunction(value));\n case 'symbol':\n return quoteLimited(String(value), limits);\n default:\n // objects: the remaining type\n return value === null ? 'null' : (\n stringifyObject(value as object, depth, limits)\n );\n }\n } catch (thrown) {\n return placeholder('Unserializable', thrown, limits);\n }\n};\n\n/**\n * Serializes logged data to JSON text. Never throws, and always returns\n * valid JSON (or `undefined`, like `JSON.stringify`, for `undefined`):\n * - ordinary data is one native `JSON.stringify`;\n * - errors, also as property values and from other realms:\n * `{\"name\",\"message\",\"stack\",...own properties,\"cause\"}`, causes up to 5\n * deep;\n * - buffers and typed arrays: a one-line description (`describeBinary`);\n * - bigints: JSON numbers with every digit; functions and symbols:\n * `\"[Function: name]\"`, `\"Symbol(x)\"`, never source code;\n * - maps, sets and regular expressions: a description (`describeObject`);\n * - strings longer than `stringLength`: cut, with `… N more characters`;\n * - arrays and objects longer than `items` (the data and its direct\n * properties): the first `items` and `\"… N more items\"`;\n * - arrays and objects whose JSON is longer than `stringLength`: cut\n * structurally, keeping their type (`cutJson`);\n * - throwing getters and revoked proxies: placeholder strings; circular\n * references: `\"[Circular]\"`; the rest of the data still renders and\n * keeps its type.\n *\n * Errors, binary data, bigints, functions and long arrays are found one\n * level deep only: in the data and in its direct properties (`{ err }`).\n * This is for performance: ordinary data is one native `JSON.stringify`,\n * and a walker for every object would slow down all logs. Deeper ones get\n * native JSON, so a deeper error keeps only its own enumerable properties\n * (`{ request: { err } }` loses message and stack).\n *\n * @param limits Output limits. Default: `DEFAULT_OUTPUT_LIMITS`.\n */\nexport const renderJsonData = (\n data: unknown,\n limits: Limits = DEFAULT_OUTPUT_LIMITS\n): string | undefined => stringifyValue(data, DATA, limits);\n\n/**\n * JSON of the time of a log, written after `\"time\":`. With the `'precise'`\n * clock (`timeNs` defined) no data is lost: ISO gets 9 fraction digits,\n * epoch gets a separate `\"ns\"` property. The type of `time` depends only on\n * the option, never on the clock.\n */\ntype JsonTimeFormatter = (time: number, timeNs: number | undefined) => string;\n\nconst epochTime: JsonTimeFormatter = (time, timeNs) =>\n timeNs === undefined ?\n String(time)\n : `${String(time)},\"ns\":${String(timeNs)}`;\n\n/**\n * ISO 8601 in UTC, through the timestamp compiler: the text up to the\n * seconds is cached per second.\n */\nconst createIsoTime = (): JsonTimeFormatter => {\n const milliseconds = compileTimestamp('[\"]YYYY-MM-DD[T]HH:mm:ss.SSS[Z\"]', {\n utc: true,\n });\n const nanoseconds = compileTimestamp(\n '[\"]YYYY-MM-DD[T]HH:mm:ss.SSSSSSSSS[Z\"]',\n {\n utc: true,\n }\n );\n return (time, timeNs) =>\n timeNs === undefined ? milliseconds(time, 0) : nanoseconds(time, timeNs);\n};\n\nconst createTimeFormatter = (time: unknown): JsonTimeFormatter | undefined => {\n if (time === false) return undefined;\n if (time === undefined || time === 'iso') return createIsoTime();\n if (time === 'epoch') return epochTime;\n throw new RangeError(\n `jsonPlugin: time must be 'iso', 'epoch' or false, got ${typeof time === 'string' ? `'${time}'` : typeof time}.`\n );\n};\n\nconst DEL_C1 = /[\\x7F-\\x9F]/;\nconst DEL_C1_ALL = /[\\x7F-\\x9F]/g;\n\nconst escapeControl = (char: string): string =>\n `\\\\u00${char.charCodeAt(0).toString(16)}`;\n\n/**\n * Escapes DEL and C1 controls. They can only be inside JSON strings (the\n * rest of a line is printable ASCII), where `\\u00XX` is the same character.\n */\nconst escapeControls = (line: string): string =>\n DEL_C1.test(line) ? line.replace(DEL_C1_ALL, escapeControl) : line;\n\nconst keepLine = (line: string): string => line;\n\n/**\n * The kind of a plugin and its JSON, for `writeKind`.\n */\ninterface OwnKind {\n readonly name: string;\n readonly json: string;\n}\n\n/**\n * JSON line of an entry: `id`, `time` (from `timestamp`), `type`, `kind`\n * (only with `writeKind`), `data`, then properties added by transformers.\n * The known properties are collected and joined by one template, which is\n * faster than appending property by property.\n */\nconst renderJsonLine = (\n entry: LogEntry,\n time: string | undefined,\n ownKind: OwnKind | undefined,\n limits: Limits\n): string => {\n let id: string | undefined;\n let type: string | undefined;\n let kind: string | undefined;\n let data: string | undefined;\n let timed = false;\n let extra = '';\n for (const key in entry)\n switch (key) {\n case 'id':\n id = stringifyValue(entry[key], DATA, limits);\n break;\n case 'timestamp':\n timed = true;\n break;\n case 'type': {\n const value = entry[key];\n // log types need no escaping: skips a native call per log\n type =\n (\n typeof value === 'string' &&\n typeof LOG_TYPE_VALUES[value] === 'number'\n ) ?\n `\"${value}\"`\n : stringifyValue(value, DATA, limits);\n break;\n }\n case 'kind':\n if (ownKind !== undefined)\n kind =\n entry[key] === ownKind.name ?\n ownKind.json\n : stringifyValue(entry[key], DATA, limits);\n break;\n case 'data':\n data = stringifyValue(entry[key], DATA, limits);\n break;\n default:\n extra = appendProperty(\n extra,\n quote(key),\n stringifyValue(entry[key], DATA, limits)\n );\n }\n if (!timed) time = undefined;\n if (id !== undefined && type !== undefined && data !== undefined) {\n const typed = kind === undefined ? type : `${type},\"kind\":${kind}`;\n return time === undefined ?\n `{\"id\":${id},\"type\":${typed},\"data\":${data}${extra && `,${extra}`}}`\n : `{\"id\":${id},\"time\":${time},\"type\":${typed},\"data\":${data}${extra && `,${extra}`}}`;\n }\n // properties removed by transformers or `undefined` data\n let text = appendProperty('', '\"id\"', id);\n text = appendProperty(text, '\"time\"', time);\n text = appendProperty(text, '\"type\"', type);\n text = appendProperty(text, '\"kind\"', kind);\n text = appendProperty(text, '\"data\"', data);\n return `{${text}${text && extra ? ',' : ''}${extra}}`;\n};\n\n/**\n * Log methods re-declared by `jsonPlugin` when it becomes the default kind:\n * any data, written as one JSON line.\n */\nexport interface JsonMethods {\n /**\n * Logs a fatal error that leads to an immediate halt of all operations, as\n * a JSON line.\n *\n * @param data Any value, written as the line's `data`. Errors keep their\n * name, message, stack, properties and cause.\n * @param kind Log kind. Default: `'json'`.\n */\n fatal(data: unknown, kind?: string): void;\n /**\n * Logs an error that might lead to a halt of the current operation, as a\n * JSON line.\n *\n * @param data Any value, written as the line's `data`. Errors keep their\n * name, message, stack, properties and cause.\n * @param kind Log kind. Default: `'json'`.\n */\n error(data: unknown, kind?: string): void;\n /**\n * Logs a warning about something that might produce an unexpected result\n * later in the execution, as a JSON line.\n *\n * @param data Any value, written as the line's `data`.\n * @param kind Log kind. Default: `'json'`.\n */\n warning(data: unknown, kind?: string): void;\n /**\n * Logs an important milestone of the execution flow, relevant in\n * production, as a JSON line.\n *\n * @param data Any value, written as the line's `data`.\n * @param kind Log kind. Default: `'json'`.\n */\n info(data: unknown, kind?: string): void;\n /**\n * Logs information that helps to debug a problem, as a JSON line.\n *\n * @param data Any value, written as the line's `data`.\n * @param kind Log kind. Default: `'json'`.\n */\n debug(data: unknown, kind?: string): void;\n /**\n * Logs an execution checkpoint, to narrow down the execution path, as a\n * JSON line.\n *\n * @param data Any value, written as the line's `data`.\n * @param kind Log kind. Default: `'json'`.\n */\n trace(data: unknown, kind?: string): void;\n /**\n * Logs information of importance during a close examination of the\n * execution flow, as a JSON line.\n *\n * @param data Any value, written as the line's `data`.\n * @param kind Log kind. Default: `'json'`.\n */\n verbose(data: unknown, kind?: string): void;\n}\n\n/**\n * Methods typed by `jsonPlugin`: the re-declared log methods, unless the\n * plugin does not become the default kind.\n */\nexport type JsonPluginMethods<O extends JsonPluginOptions> =\n O extends { readonly setAsDefault: false } ? object : JsonMethods;\n\n/**\n * Writes logs of a given kind as JSON lines (NDJSON) and, by default, makes\n * that kind the logger's default, so `logger.info({ user: 'alice' })`\n * writes:\n *\n * ```\n * {\"id\":1,\"time\":\"2026-03-16T15:35:00.000Z\",\"type\":\"info\",\"data\":{\"user\":\"alice\"}}\n * ```\n *\n * Logging never throws because of the data; see `renderJsonData`. Errors of\n * `write` propagate.\n *\n * @throws RangeError if `time` or `limits` are invalid.\n * @throws TypeError if `write` is not a function.\n */\nexport const jsonPlugin = <\n const O extends JsonPluginOptions = JsonPluginOptions,\n>(\n options: O = {} as O\n): LoggerPlugin<JsonPluginMethods<O>> => {\n const kind = options.kind ?? 'json';\n const limits = resolveOutputLimits(options.limits, 'jsonPlugin');\n const formatTime = createTimeFormatter(options.time);\n const escape = options.escapeControls === true ? escapeControls : keepLine;\n // quoted once: the output only receives its own kind (unless a\n // transformer changes it)\n const ownKind: OwnKind | undefined =\n options.writeKind === true ? { name: kind, json: quote(kind) } : undefined;\n // checked for untyped callers: it would otherwise throw on the first log\n const write: unknown = options.write ?? console.log;\n if (typeof write !== 'function')\n throw new TypeError(\n `jsonPlugin: write is not a function, got ${write === null ? 'null' : typeof write}.`\n );\n const writeLine = write as (line: string) => void;\n return {\n name: `json:${kind}`,\n ...((options.setAsDefault ?? true) && { defaultKind: kind }),\n outputs: {\n [kind]: (entry, { time, timeNs }) => {\n writeLine(\n escape(\n renderJsonLine(\n entry,\n time === undefined || formatTime === undefined ?\n undefined\n : formatTime(time, timeNs),\n ownKind,\n limits\n )\n )\n );\n },\n },\n };\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { joinedOutput } from '../outputs.js';
|
|
2
|
+
import { createSanitizer, DEFAULT_OUTPUT_LIMITS, resolveOutputLimits, truncate, describeBinary, limitKeys, isForeignError, describeObject, stringifyProperty, describeLeftOut, stringifyPrimitive, splitError } from '../utils/text.js';
|
|
3
|
+
import { headerTemplates, mergeStyleSheets, DEFAULT_TEXT_STYLES, paintUnrenderable, paint } from './shared.js';
|
|
4
|
+
|
|
5
|
+
const SAFE_SANITIZER = createSanitizer('safe');
|
|
6
|
+
/**
|
|
7
|
+
* Renders message data with the text styles:
|
|
8
|
+
* - strings: `textHighlight`, on the header line;
|
|
9
|
+
* - errors: `name: message` in `textHighlight` and stack frames in `textDim`,
|
|
10
|
+
* below the header;
|
|
11
|
+
* - objects and arrays: one `key: value` per line below the header, keys in
|
|
12
|
+
* `textNormal` and JSON values in `textHighlight`; empty ones inline in
|
|
13
|
+
* `textDim`;
|
|
14
|
+
* - other values: `textNormal`, on the header line.
|
|
15
|
+
*
|
|
16
|
+
* Strings, symbols, functions and error messages are sanitized as `text`;
|
|
17
|
+
* keys, values and stack frames as `label`. Default: `'safe'` (see
|
|
18
|
+
* `Sanitize`).
|
|
19
|
+
*
|
|
20
|
+
* Never throws: data that can't be read (throwing getters, revoked proxies,
|
|
21
|
+
* broken errors) gives dim placeholders.
|
|
22
|
+
*/
|
|
23
|
+
const renderMessageData = (data, styles, sanitizer = SAFE_SANITIZER, limits = DEFAULT_OUTPUT_LIMITS) => {
|
|
24
|
+
try {
|
|
25
|
+
return renderData(data, styles, sanitizer, limits);
|
|
26
|
+
}
|
|
27
|
+
catch (thrown) {
|
|
28
|
+
return paintUnrenderable(thrown, styles, sanitizer);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const renderError = (error, { textDim = '', textHighlight = '', reset = '' }, { text: sanitizeText, label: sanitizeLabel }, { items, stringLength }) => {
|
|
32
|
+
const [head, frames] = splitError(error);
|
|
33
|
+
let text = `\n${paint(textHighlight, sanitizeText(truncate(head, stringLength)), reset)}`;
|
|
34
|
+
const shown = Math.min(frames.length, items);
|
|
35
|
+
for (let index = 0; index < shown; index++)
|
|
36
|
+
text += `\n${paint(textDim, sanitizeLabel(truncate(frames[index] ?? '', stringLength)), reset)}`;
|
|
37
|
+
if (frames.length > shown)
|
|
38
|
+
text += `\n${paint(textDim, describeLeftOut(frames.length - shown, 'frame'), reset)}`;
|
|
39
|
+
return text;
|
|
40
|
+
};
|
|
41
|
+
const renderData = (data, styles, sanitizer, limits) => {
|
|
42
|
+
const { textDim = '', textNormal = '', textHighlight = '', reset = '', } = styles;
|
|
43
|
+
const { text: sanitizeText, label: sanitizeLabel } = sanitizer;
|
|
44
|
+
const { items, stringLength } = limits;
|
|
45
|
+
if (typeof data === 'string')
|
|
46
|
+
return paint(textHighlight, sanitizeText(truncate(data, stringLength)), reset);
|
|
47
|
+
if (data instanceof Error)
|
|
48
|
+
return renderError(data, styles, sanitizer, limits);
|
|
49
|
+
if (typeof data === 'object' && data !== null) {
|
|
50
|
+
if (ArrayBuffer.isView(data))
|
|
51
|
+
return paint(textNormal, sanitizeLabel(describeBinary(data, items)), reset);
|
|
52
|
+
const [keys, more] = limitKeys(data, items);
|
|
53
|
+
if (!keys.length) {
|
|
54
|
+
// errors of other realms have no enumerable keys either
|
|
55
|
+
if (isForeignError(data))
|
|
56
|
+
return renderError(data, styles, sanitizer, limits);
|
|
57
|
+
const described = describeObject(data, limits);
|
|
58
|
+
if (described !== undefined)
|
|
59
|
+
return paint(textNormal, sanitizeLabel(truncate(described, stringLength)), reset);
|
|
60
|
+
return paint(textDim, Array.isArray(data) ? '[]' : '{}', reset);
|
|
61
|
+
}
|
|
62
|
+
let text = '';
|
|
63
|
+
for (const key of keys)
|
|
64
|
+
text += `\n${paint(textNormal, `${sanitizeLabel(truncate(key, stringLength))}:`, reset)} ${paint(textHighlight, sanitizeLabel(stringifyProperty(data, key, limits)), reset)}`;
|
|
65
|
+
if (more)
|
|
66
|
+
text += `\n${paint(textDim, describeLeftOut(more, 'item'), reset)}`;
|
|
67
|
+
return text;
|
|
68
|
+
}
|
|
69
|
+
// numbers, booleans, null and undefined can't contain controls
|
|
70
|
+
const text = stringifyPrimitive(data);
|
|
71
|
+
return paint(textNormal, typeof data === 'symbol' || typeof data === 'function' ?
|
|
72
|
+
sanitizeLabel(truncate(text, stringLength))
|
|
73
|
+
: text, reset);
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Renders logs of a given kind as styled text and, by default, makes that
|
|
77
|
+
* kind the logger's default, so `logger.info('Server started')` prints:
|
|
78
|
+
*
|
|
79
|
+
* ```
|
|
80
|
+
* 2026/03/16 15:35:00 [i] info Server started
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* Objects and arrays print each property on a new line; errors print their
|
|
84
|
+
* message and stack on new lines. See `renderMessageData` for the styles.
|
|
85
|
+
*/
|
|
86
|
+
const messagePlugin = (options = {}) => {
|
|
87
|
+
const kind = options.kind ?? 'message';
|
|
88
|
+
const sanitizer = createSanitizer(options.sanitize);
|
|
89
|
+
const limits = resolveOutputLimits(options.limits, 'messagePlugin');
|
|
90
|
+
return {
|
|
91
|
+
name: `message:${kind}`,
|
|
92
|
+
...((options.setAsDefault ?? true) && { defaultKind: kind }),
|
|
93
|
+
styles: mergeStyleSheets(DEFAULT_TEXT_STYLES, options.styles),
|
|
94
|
+
templateMaps: {
|
|
95
|
+
[kind]: {
|
|
96
|
+
...headerTemplates(options),
|
|
97
|
+
data: (value, { styles }) => renderMessageData(value, styles, sanitizer, limits),
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
outputs: { [kind]: joinedOutput(options.write) },
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export { messagePlugin, renderMessageData };
|
|
105
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sources":["../../../src/plugins/message.ts"],"sourcesContent":["import { joinedOutput } from '../outputs.js';\nimport type { BakedStyles, LoggerPlugin, StyleSheet } from '../types.js';\nimport {\n createSanitizer,\n DEFAULT_OUTPUT_LIMITS,\n describeBinary,\n describeLeftOut,\n describeObject,\n isForeignError,\n limitKeys,\n resolveOutputLimits,\n splitError,\n stringifyPrimitive,\n stringifyProperty,\n truncate,\n type OutputLimits,\n type Sanitizer,\n} from '../utils/text.js';\nimport {\n DEFAULT_TEXT_STYLES,\n headerTemplates,\n mergeStyleSheets,\n paint,\n paintUnrenderable,\n type HeaderOptions,\n type SanitizeOptions,\n} from './shared.js';\n\nconst SAFE_SANITIZER = createSanitizer('safe');\n\nexport interface MessagePluginOptions extends HeaderOptions, SanitizeOptions {\n /**\n * Output size limits: elements and keys per object, characters per string.\n * `Infinity` turns a limit off. Default: `DEFAULT_OUTPUT_LIMITS`\n * (`{ items: 100, stringLength: 10_000 }`).\n */\n readonly limits?: OutputLimits;\n /** Kind rendered by this plugin. Default: `'message'`. */\n readonly kind?: string;\n /**\n * Make `kind` the logger's default kind, so all logs without an explicit\n * kind are rendered as messages. The last plugin used that sets the\n * default wins. Use `messagePlugin` instead of `jsonPlugin`, not next to\n * it: both render the whole log. Default: `true`.\n */\n readonly setAsDefault?: boolean;\n /** Styles merged over the default text styles. */\n readonly styles?: StyleSheet;\n /** String destination. Default: `console.log`. */\n readonly write?: (text: string) => void;\n}\n\n/**\n * Renders message data with the text styles:\n * - strings: `textHighlight`, on the header line;\n * - errors: `name: message` in `textHighlight` and stack frames in `textDim`,\n * below the header;\n * - objects and arrays: one `key: value` per line below the header, keys in\n * `textNormal` and JSON values in `textHighlight`; empty ones inline in\n * `textDim`;\n * - other values: `textNormal`, on the header line.\n *\n * Strings, symbols, functions and error messages are sanitized as `text`;\n * keys, values and stack frames as `label`. Default: `'safe'` (see\n * `Sanitize`).\n *\n * Never throws: data that can't be read (throwing getters, revoked proxies,\n * broken errors) gives dim placeholders.\n */\nexport const renderMessageData = (\n data: unknown,\n styles: BakedStyles,\n sanitizer: Sanitizer = SAFE_SANITIZER,\n limits: Required<OutputLimits> = DEFAULT_OUTPUT_LIMITS\n): string => {\n try {\n return renderData(data, styles, sanitizer, limits);\n } catch (thrown) {\n return paintUnrenderable(thrown, styles, sanitizer);\n }\n};\n\nconst renderError = (\n error: Error,\n { textDim = '', textHighlight = '', reset = '' }: BakedStyles,\n { text: sanitizeText, label: sanitizeLabel }: Sanitizer,\n { items, stringLength }: Required<OutputLimits>\n): string => {\n const [head, frames] = splitError(error);\n let text = `\\n${paint(textHighlight, sanitizeText(truncate(head, stringLength)), reset)}`;\n const shown = Math.min(frames.length, items);\n for (let index = 0; index < shown; index++)\n text += `\\n${paint(textDim, sanitizeLabel(truncate(frames[index] ?? '', stringLength)), reset)}`;\n if (frames.length > shown)\n text += `\\n${paint(textDim, describeLeftOut(frames.length - shown, 'frame'), reset)}`;\n return text;\n};\n\nconst renderData = (\n data: unknown,\n styles: BakedStyles,\n sanitizer: Sanitizer,\n limits: Required<OutputLimits>\n): string => {\n const {\n textDim = '',\n textNormal = '',\n textHighlight = '',\n reset = '',\n } = styles;\n const { text: sanitizeText, label: sanitizeLabel } = sanitizer;\n const { items, stringLength } = limits;\n\n if (typeof data === 'string')\n return paint(\n textHighlight,\n sanitizeText(truncate(data, stringLength)),\n reset\n );\n\n if (data instanceof Error)\n return renderError(data, styles, sanitizer, limits);\n\n if (typeof data === 'object' && data !== null) {\n if (ArrayBuffer.isView(data))\n return paint(\n textNormal,\n sanitizeLabel(describeBinary(data, items)),\n reset\n );\n const [keys, more] = limitKeys(data, items);\n if (!keys.length) {\n // errors of other realms have no enumerable keys either\n if (isForeignError(data))\n return renderError(data as Error, styles, sanitizer, limits);\n const described = describeObject(data, limits);\n if (described !== undefined)\n return paint(\n textNormal,\n sanitizeLabel(truncate(described, stringLength)),\n reset\n );\n return paint(textDim, Array.isArray(data) ? '[]' : '{}', reset);\n }\n let text = '';\n for (const key of keys)\n text += `\\n${paint(textNormal, `${sanitizeLabel(truncate(key, stringLength))}:`, reset)} ${paint(\n textHighlight,\n sanitizeLabel(stringifyProperty(data, key, limits)),\n reset\n )}`;\n if (more)\n text += `\\n${paint(textDim, describeLeftOut(more, 'item'), reset)}`;\n return text;\n }\n\n // numbers, booleans, null and undefined can't contain controls\n const text = stringifyPrimitive(data);\n return paint(\n textNormal,\n typeof data === 'symbol' || typeof data === 'function' ?\n sanitizeLabel(truncate(text, stringLength))\n : text,\n reset\n );\n};\n\n/* eslint-disable @typescript-eslint/unified-signatures --\n * Separate overloads instead of `string | object`: hovers lead with the text\n * signature and each input shape keeps its own docs. */\n/**\n * Log methods re-declared by `messagePlugin` when it becomes the default kind:\n * the data is a text message, rendered as a styled line.\n */\nexport interface MessageMethods {\n /**\n * Logs a fatal error that leads to an immediate halt of all operations, as\n * a styled text line.\n *\n * @param message Text to display.\n * @param kind Log kind. Default: `'message'`.\n */\n fatal(message: string, kind?: string): void;\n /**\n * Logs a fatal error that leads to an immediate halt of all operations.\n *\n * @param data Object or array (each property on a new line) or error\n * (message and stack on new lines).\n * @param kind Log kind. Default: `'message'`.\n */\n fatal(data: object, kind?: string): void;\n\n /**\n * Logs an error that might lead to a halt of the current operation, as a\n * styled text line.\n *\n * @param message Text to display.\n * @param kind Log kind. Default: `'message'`.\n */\n error(message: string, kind?: string): void;\n /**\n * Logs an error that might lead to a halt of the current operation.\n *\n * @param data Object or array (each property on a new line) or error\n * (message and stack on new lines).\n * @param kind Log kind. Default: `'message'`.\n */\n error(data: object, kind?: string): void;\n\n /**\n * Logs a warning about something that might produce an unexpected result\n * later in the execution, as a styled text line.\n *\n * @param message Text to display.\n * @param kind Log kind. Default: `'message'`.\n */\n warning(message: string, kind?: string): void;\n /**\n * Logs a warning about something that might produce an unexpected result\n * later in the execution.\n *\n * @param data Object or array (each property on a new line) or error\n * (message and stack on new lines).\n * @param kind Log kind. Default: `'message'`.\n */\n warning(data: object, kind?: string): void;\n\n /**\n * Logs an important milestone of the execution flow, relevant in\n * production, as a styled text line.\n *\n * @param message Text to display.\n * @param kind Log kind. Default: `'message'`.\n */\n info(message: string, kind?: string): void;\n /**\n * Logs an important milestone of the execution flow, relevant in\n * production.\n *\n * @param data Object or array (each property on a new line) or error\n * (message and stack on new lines).\n * @param kind Log kind. Default: `'message'`.\n */\n info(data: object, kind?: string): void;\n\n /**\n * Logs information that helps to debug a problem, as a styled text line.\n *\n * @param message Text to display.\n * @param kind Log kind. Default: `'message'`.\n */\n debug(message: string, kind?: string): void;\n /**\n * Logs information that helps to debug a problem.\n *\n * @param data Object or array (each property on a new line) or error\n * (message and stack on new lines).\n * @param kind Log kind. Default: `'message'`.\n */\n debug(data: object, kind?: string): void;\n\n /**\n * Logs an execution checkpoint, to narrow down the execution path, as a\n * styled text line.\n *\n * @param message Text to display.\n * @param kind Log kind. Default: `'message'`.\n */\n trace(message: string, kind?: string): void;\n /**\n * Logs an execution checkpoint, to narrow down the execution path.\n *\n * @param data Object or array (each property on a new line) or error\n * (message and stack on new lines).\n * @param kind Log kind. Default: `'message'`.\n */\n trace(data: object, kind?: string): void;\n\n /**\n * Logs information of importance during a close examination of the\n * execution flow, as a styled text line.\n *\n * @param message Text to display.\n * @param kind Log kind. Default: `'message'`.\n */\n verbose(message: string, kind?: string): void;\n /**\n * Logs information of importance during a close examination of the\n * execution flow.\n *\n * @param data Object or array (each property on a new line) or error\n * (message and stack on new lines).\n * @param kind Log kind. Default: `'message'`.\n */\n verbose(data: object, kind?: string): void;\n}\n/* eslint-enable @typescript-eslint/unified-signatures */\n\n/**\n * Methods typed by `messagePlugin`: the re-declared log methods, unless the\n * plugin does not become the default kind.\n */\nexport type MessagePluginMethods<O extends MessagePluginOptions> =\n O extends { readonly setAsDefault: false } ? object : MessageMethods;\n\n/**\n * Renders logs of a given kind as styled text and, by default, makes that\n * kind the logger's default, so `logger.info('Server started')` prints:\n *\n * ```\n * 2026/03/16 15:35:00 [i] info Server started\n * ```\n *\n * Objects and arrays print each property on a new line; errors print their\n * message and stack on new lines. See `renderMessageData` for the styles.\n */\nexport const messagePlugin = <\n const O extends MessagePluginOptions = MessagePluginOptions,\n>(\n options: O = {} as O\n): LoggerPlugin<MessagePluginMethods<O>> => {\n const kind = options.kind ?? 'message';\n const sanitizer = createSanitizer(options.sanitize);\n const limits = resolveOutputLimits(options.limits, 'messagePlugin');\n return {\n name: `message:${kind}`,\n ...((options.setAsDefault ?? true) && { defaultKind: kind }),\n styles: mergeStyleSheets(DEFAULT_TEXT_STYLES, options.styles),\n templateMaps: {\n [kind]: {\n ...headerTemplates(options),\n data: (value, { styles }) =>\n renderMessageData(value, styles, sanitizer, limits),\n },\n },\n outputs: { [kind]: joinedOutput(options.write) },\n };\n};\n"],"names":[],"mappings":";;;;AA4BA,MAAM,cAAc,GAAG,eAAe,CAAC,MAAM,CAAC;AAwB9C;;;;;;;;;;;;;;;;AAgBG;AACI,MAAM,iBAAiB,GAAG,CAC/B,IAAa,EACb,MAAmB,EACnB,YAAuB,cAAc,EACrC,MAAA,GAAiC,qBAAqB,KAC5C;AACV,IAAA,IAAI;QACF,OAAO,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC;IACpD;IAAE,OAAO,MAAM,EAAE;QACf,OAAO,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;IACrD;AACF;AAEA,MAAM,WAAW,GAAG,CAClB,KAAY,EACZ,EAAE,OAAO,GAAG,EAAE,EAAE,aAAa,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,EAAe,EAC7D,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAa,EACvD,EAAE,KAAK,EAAE,YAAY,EAA0B,KACrC;IACV,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC;IACxC,IAAI,IAAI,GAAG,CAAA,EAAA,EAAK,KAAK,CAAC,aAAa,EAAE,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE;AACzF,IAAA,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAC5C,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,EAAE,KAAK,EAAE;QACxC,IAAI,IAAI,CAAA,EAAA,EAAK,KAAK,CAAC,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA,CAAE;AAClG,IAAA,IAAI,MAAM,CAAC,MAAM,GAAG,KAAK;QACvB,IAAI,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM,GAAG,KAAK,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE;AACvF,IAAA,OAAO,IAAI;AACb,CAAC;AAED,MAAM,UAAU,GAAG,CACjB,IAAa,EACb,MAAmB,EACnB,SAAoB,EACpB,MAA8B,KACpB;AACV,IAAA,MAAM,EACJ,OAAO,GAAG,EAAE,EACZ,UAAU,GAAG,EAAE,EACf,aAAa,GAAG,EAAE,EAClB,KAAK,GAAG,EAAE,GACX,GAAG,MAAM;IACV,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,SAAS;AAC9D,IAAA,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM;IAEtC,IAAI,OAAO,IAAI,KAAK,QAAQ;AAC1B,QAAA,OAAO,KAAK,CACV,aAAa,EACb,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,EAC1C,KAAK,CACN;IAEH,IAAI,IAAI,YAAY,KAAK;QACvB,OAAO,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC;IAErD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE;AAC7C,QAAA,IAAI,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC;AAC1B,YAAA,OAAO,KAAK,CACV,UAAU,EACV,aAAa,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,EAC1C,KAAK,CACN;AACH,QAAA,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC;AAC3C,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;;YAEhB,IAAI,cAAc,CAAC,IAAI,CAAC;gBACtB,OAAO,WAAW,CAAC,IAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC;YAC9D,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC;YAC9C,IAAI,SAAS,KAAK,SAAS;AACzB,gBAAA,OAAO,KAAK,CACV,UAAU,EACV,aAAa,CAAC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,EAChD,KAAK,CACN;YACH,OAAO,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,KAAK,CAAC;QACjE;QACA,IAAI,IAAI,GAAG,EAAE;QACb,KAAK,MAAM,GAAG,IAAI,IAAI;AACpB,YAAA,IAAI,IAAI,CAAA,EAAA,EAAK,KAAK,CAAC,UAAU,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC,CAAA,CAAA,EAAI,KAAK,CAC9F,aAAa,EACb,aAAa,CAAC,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,EACnD,KAAK,CACN,EAAE;AACL,QAAA,IAAI,IAAI;AACN,YAAA,IAAI,IAAI,CAAA,EAAA,EAAK,KAAK,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE;AACrE,QAAA,OAAO,IAAI;IACb;;AAGA,IAAA,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC;AACrC,IAAA,OAAO,KAAK,CACV,UAAU,EACV,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,UAAU;AACpD,QAAA,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;AAC5C,UAAE,IAAI,EACN,KAAK,CACN;AACH,CAAC;AA4ID;;;;;;;;;;AAUG;MACU,aAAa,GAAG,CAG3B,OAAA,GAAa,EAAO,KACqB;AACzC,IAAA,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,SAAS;IACtC,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC;IACnD,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC;IACnE,OAAO;QACL,IAAI,EAAE,CAAA,QAAA,EAAW,IAAI,CAAA,CAAE;AACvB,QAAA,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,IAAI,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QAC5D,MAAM,EAAE,gBAAgB,CAAC,mBAAmB,EAAE,OAAO,CAAC,MAAM,CAAC;AAC7D,QAAA,YAAY,EAAE;YACZ,CAAC,IAAI,GAAG;gBACN,GAAG,eAAe,CAAC,OAAO,CAAC;AAC3B,gBAAA,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,KACtB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC;AACtD,aAAA;AACF,SAAA;AACD,QAAA,OAAO,EAAE,EAAE,CAAC,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;KACjD;AACH;;"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { sec } from 'style-escape-codes';
|
|
2
|
+
import { LOG_TYPES, LOG_TYPE_MAX_LENGTH } from '../levels.js';
|
|
3
|
+
import { describeThrown, textWidth, padTextMiddle } from '../utils/text.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Default text styles shared by the bundled plugins. Plugins may override
|
|
7
|
+
* them by registering the same style names.
|
|
8
|
+
*
|
|
9
|
+
* - `textDim`: secondary information: id, timestamp, symbols, units and
|
|
10
|
+
* stack frames. Gray.
|
|
11
|
+
* - `textNormal`: the terminal's default text style: object keys, graph
|
|
12
|
+
* legend labels, other values.
|
|
13
|
+
* - `textHighlight`: text messages, error messages, object values; graph
|
|
14
|
+
* titles, bars, frames and values. The level's color, bold.
|
|
15
|
+
* - `textBadge`: log type badge, the level's color as background.
|
|
16
|
+
*
|
|
17
|
+
* Colors: red for fatal (its badge white on red), bright red for error,
|
|
18
|
+
* yellow for warning, blue for info, magenta for debug, cyan for trace and
|
|
19
|
+
* gray (bright black) for verbose. They are the terminal's 16 basic colors,
|
|
20
|
+
* so they follow its theme.
|
|
21
|
+
*/
|
|
22
|
+
const DEFAULT_TEXT_STYLES = {
|
|
23
|
+
'*': {
|
|
24
|
+
textDim: sec.fgBrightBlack,
|
|
25
|
+
// no escape codes: the terminal's own foreground, readable on any theme
|
|
26
|
+
textNormal: '',
|
|
27
|
+
},
|
|
28
|
+
fatal: {
|
|
29
|
+
textHighlight: sec.b.fgRed,
|
|
30
|
+
// white on red: the most severe level stands out
|
|
31
|
+
textBadge: sec.b.fgWhite.bgRed,
|
|
32
|
+
},
|
|
33
|
+
error: {
|
|
34
|
+
textHighlight: sec.b.fgBrightRed,
|
|
35
|
+
textBadge: sec.b.fgBlack.bgBrightRed,
|
|
36
|
+
},
|
|
37
|
+
warning: {
|
|
38
|
+
textHighlight: sec.b.fgYellow,
|
|
39
|
+
textBadge: sec.b.fgBlack.bgYellow,
|
|
40
|
+
},
|
|
41
|
+
info: {
|
|
42
|
+
textHighlight: sec.b.fgBlue,
|
|
43
|
+
textBadge: sec.b.fgBlack.bgBlue,
|
|
44
|
+
},
|
|
45
|
+
debug: {
|
|
46
|
+
textHighlight: sec.b.fgMagenta,
|
|
47
|
+
textBadge: sec.b.fgBlack.bgMagenta,
|
|
48
|
+
},
|
|
49
|
+
trace: {
|
|
50
|
+
textHighlight: sec.b.fgCyan,
|
|
51
|
+
textBadge: sec.b.fgBlack.bgCyan,
|
|
52
|
+
},
|
|
53
|
+
verbose: {
|
|
54
|
+
textHighlight: sec.b.fgBrightBlack,
|
|
55
|
+
textBadge: sec.b.bgBrightBlack,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Wraps text in a style and a reset. Empty text or an empty style produce no
|
|
60
|
+
* escape codes.
|
|
61
|
+
*/
|
|
62
|
+
const paint = (style, text, reset) => style && text ? `${style}${text}${reset}` : text;
|
|
63
|
+
/**
|
|
64
|
+
* Dim placeholder for data whose rendering threw, so logging never throws
|
|
65
|
+
* because of the logged data.
|
|
66
|
+
*/
|
|
67
|
+
const paintUnrenderable = (thrown, { textDim = '', reset = '' }, { label }) => paint(textDim, `[Unrenderable: ${label(describeThrown(thrown))}]`, reset);
|
|
68
|
+
/**
|
|
69
|
+
* Merges style sheets group by group, so overriding one style of a type keeps
|
|
70
|
+
* the other base styles of that type.
|
|
71
|
+
*
|
|
72
|
+
* The result has no prototype and reads own groups only, so a `__proto__` key
|
|
73
|
+
* (e.g. from a sheet parsed from JSON) is a plain, unused group instead of
|
|
74
|
+
* replacing the sheet's prototype.
|
|
75
|
+
*/
|
|
76
|
+
const mergeStyleSheets = (base, override) => {
|
|
77
|
+
if (override === undefined)
|
|
78
|
+
return base;
|
|
79
|
+
const result = Object.assign(Object.create(null), base);
|
|
80
|
+
for (const group of Object.keys(override))
|
|
81
|
+
result[group] = {
|
|
82
|
+
...(Object.hasOwn(base, group) ? base[group] : undefined),
|
|
83
|
+
...override[group],
|
|
84
|
+
};
|
|
85
|
+
return result;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Default symbols in front of the type badge: three ASCII characters each,
|
|
89
|
+
* which every terminal and font draws, one column per character. Emoji are
|
|
90
|
+
* missing from some fonts and their width differs between terminals, which
|
|
91
|
+
* shifts the badge.
|
|
92
|
+
*/
|
|
93
|
+
const DEFAULT_SYMBOLS = {
|
|
94
|
+
// fatal: '⛔',
|
|
95
|
+
// error: '❗',
|
|
96
|
+
// warning: '⚠️',
|
|
97
|
+
// info: 'ℹ️',
|
|
98
|
+
// debug: '',
|
|
99
|
+
// trace: '✅',
|
|
100
|
+
// verbose: '',
|
|
101
|
+
fatal: '[X]',
|
|
102
|
+
error: '[!]',
|
|
103
|
+
warning: '/!\\',
|
|
104
|
+
info: '[i]',
|
|
105
|
+
debug: '(?)',
|
|
106
|
+
trace: '/\\/',
|
|
107
|
+
verbose: '...',
|
|
108
|
+
};
|
|
109
|
+
const typeTexts = (text) => ({
|
|
110
|
+
fatal: text('fatal'),
|
|
111
|
+
error: text('error'),
|
|
112
|
+
warning: text('warning'),
|
|
113
|
+
info: text('info'),
|
|
114
|
+
debug: text('debug'),
|
|
115
|
+
trace: text('trace'),
|
|
116
|
+
verbose: text('verbose'),
|
|
117
|
+
});
|
|
118
|
+
/**
|
|
119
|
+
* Text of `type` in `texts`, or `undefined` for other types, e.g. one
|
|
120
|
+
* changed by a transformer: inherited keys (`toString`, `__proto__`) are not
|
|
121
|
+
* strings.
|
|
122
|
+
*/
|
|
123
|
+
const typeText = (texts, type) => {
|
|
124
|
+
const text = texts[type];
|
|
125
|
+
return typeof text === 'string' ? text : undefined;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Badge text of a type: centered in the width of the longest type.
|
|
129
|
+
*/
|
|
130
|
+
const badgeText = (type) => ` ${padTextMiddle(type, LOG_TYPE_MAX_LENGTH)} `;
|
|
131
|
+
const BADGES = typeTexts(badgeText);
|
|
132
|
+
/**
|
|
133
|
+
* Symbol text of each type, resolved once per plugin.
|
|
134
|
+
*
|
|
135
|
+
* @throws TypeError if `symbol` is neither a string nor symbols per type,
|
|
136
|
+
* or a symbol is not a string.
|
|
137
|
+
*/
|
|
138
|
+
const resolveSymbols = (symbol = DEFAULT_SYMBOLS) => {
|
|
139
|
+
if (typeof symbol === 'string')
|
|
140
|
+
return typeTexts(() => symbol);
|
|
141
|
+
const symbols = {};
|
|
142
|
+
// configuration from JavaScript is not type checked
|
|
143
|
+
const record = symbol;
|
|
144
|
+
if (typeof record !== 'object' || record === null || Array.isArray(record))
|
|
145
|
+
throw new TypeError(`symbol: must be a string or symbols per type, got ${record === null ? 'null'
|
|
146
|
+
: Array.isArray(record) ? 'an array'
|
|
147
|
+
: typeof record}.`);
|
|
148
|
+
let width = 0;
|
|
149
|
+
for (const type of LOG_TYPES) {
|
|
150
|
+
// `undefined` keeps the default, like an option that is not set: types
|
|
151
|
+
// without `exactOptionalPropertyTypes` allow it
|
|
152
|
+
const value = record[type] ??
|
|
153
|
+
DEFAULT_SYMBOLS[type];
|
|
154
|
+
if (typeof value !== 'string')
|
|
155
|
+
throw new TypeError(`symbol: the symbol of ${type} must be a string, got ${typeof value}.`);
|
|
156
|
+
symbols[type] = value;
|
|
157
|
+
width = Math.max(width, textWidth(value));
|
|
158
|
+
}
|
|
159
|
+
// padded to the widest symbol plus one space, so the badges line up
|
|
160
|
+
return typeTexts((type) => {
|
|
161
|
+
const value = symbols[type] ?? '';
|
|
162
|
+
return width > 0 ? value + ' '.repeat(width - textWidth(value) + 1) : value;
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Template functions rendering the common log header: dim id, timestamp and
|
|
167
|
+
* symbol, the type badge and a hidden kind.
|
|
168
|
+
*
|
|
169
|
+
* @throws TypeError if a symbol is not a string.
|
|
170
|
+
*/
|
|
171
|
+
const headerTemplates = ({ showId = false, symbol, }) => {
|
|
172
|
+
const symbols = resolveSymbols(symbol);
|
|
173
|
+
return {
|
|
174
|
+
id: (value, { styles: { textDim = '', reset = '' } }) => showId ? `${paint(textDim, `#${String(value)}`, reset)} ` : '',
|
|
175
|
+
timestamp: (value, { styles: { textDim = '', reset = '' } }) => `${paint(textDim, String(value), reset)} `,
|
|
176
|
+
// symbol and badge texts are prepared per type; other types (changed by
|
|
177
|
+
// a transformer) get no symbol and a badge built per log
|
|
178
|
+
type: (value, { styles: { textDim = '', textBadge = '', reset = '' } }) => {
|
|
179
|
+
const type = String(value);
|
|
180
|
+
return `${paint(textDim, typeText(symbols, type) ?? '', reset)}${paint(textBadge, typeText(BADGES, type) ?? badgeText(type), reset)} `;
|
|
181
|
+
},
|
|
182
|
+
kind: () => '',
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
export { DEFAULT_SYMBOLS, DEFAULT_TEXT_STYLES, headerTemplates, mergeStyleSheets, paint, paintUnrenderable };
|
|
187
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sources":["../../../src/plugins/shared.ts"],"sourcesContent":["import { sec } from 'style-escape-codes';\nimport { LOG_TYPE_MAX_LENGTH, LOG_TYPES } from '../levels.js';\nimport type {\n BakedStyles,\n LogType,\n StyleSheet,\n TemplateMap,\n} from '../types.js';\nimport {\n describeThrown,\n padTextMiddle,\n textWidth,\n type Sanitize,\n type Sanitizer,\n} from '../utils/text.js';\n\n/**\n * Default text styles shared by the bundled plugins. Plugins may override\n * them by registering the same style names.\n *\n * - `textDim`: secondary information: id, timestamp, symbols, units and\n * stack frames. Gray.\n * - `textNormal`: the terminal's default text style: object keys, graph\n * legend labels, other values.\n * - `textHighlight`: text messages, error messages, object values; graph\n * titles, bars, frames and values. The level's color, bold.\n * - `textBadge`: log type badge, the level's color as background.\n *\n * Colors: red for fatal (its badge white on red), bright red for error,\n * yellow for warning, blue for info, magenta for debug, cyan for trace and\n * gray (bright black) for verbose. They are the terminal's 16 basic colors,\n * so they follow its theme.\n */\nexport const DEFAULT_TEXT_STYLES: StyleSheet = {\n '*': {\n textDim: sec.fgBrightBlack,\n // no escape codes: the terminal's own foreground, readable on any theme\n textNormal: '',\n },\n fatal: {\n textHighlight: sec.b.fgRed,\n // white on red: the most severe level stands out\n textBadge: sec.b.fgWhite.bgRed,\n },\n error: {\n textHighlight: sec.b.fgBrightRed,\n textBadge: sec.b.fgBlack.bgBrightRed,\n },\n warning: {\n textHighlight: sec.b.fgYellow,\n textBadge: sec.b.fgBlack.bgYellow,\n },\n info: {\n textHighlight: sec.b.fgBlue,\n textBadge: sec.b.fgBlack.bgBlue,\n },\n debug: {\n textHighlight: sec.b.fgMagenta,\n textBadge: sec.b.fgBlack.bgMagenta,\n },\n trace: {\n textHighlight: sec.b.fgCyan,\n textBadge: sec.b.fgBlack.bgCyan,\n },\n verbose: {\n textHighlight: sec.b.fgBrightBlack,\n textBadge: sec.b.bgBrightBlack,\n },\n};\n\n/**\n * Wraps text in a style and a reset. Empty text or an empty style produce no\n * escape codes.\n */\nexport const paint = (style: string, text: string, reset: string): string =>\n style && text ? `${style}${text}${reset}` : text;\n\n/**\n * Dim placeholder for data whose rendering threw, so logging never throws\n * because of the logged data.\n */\nexport const paintUnrenderable = (\n thrown: unknown,\n { textDim = '', reset = '' }: BakedStyles,\n { label }: Sanitizer\n): string =>\n paint(textDim, `[Unrenderable: ${label(describeThrown(thrown))}]`, reset);\n\n/**\n * Merges style sheets group by group, so overriding one style of a type keeps\n * the other base styles of that type.\n *\n * The result has no prototype and reads own groups only, so a `__proto__` key\n * (e.g. from a sheet parsed from JSON) is a plain, unused group instead of\n * replacing the sheet's prototype.\n */\nexport const mergeStyleSheets = (\n base: StyleSheet,\n override: StyleSheet | undefined\n): StyleSheet => {\n if (override === undefined) return base;\n const result = Object.assign(Object.create(null) as StyleSheet, base);\n for (const group of Object.keys(override) as (keyof StyleSheet)[])\n result[group] = {\n ...(Object.hasOwn(base, group) ? base[group] : undefined),\n ...override[group],\n };\n return result;\n};\n\nexport interface SanitizeOptions {\n /**\n * Sanitization of logged text: strings, object keys and values, errors and\n * graph labels. See `Sanitize`. Default: `'safe'`.\n */\n readonly sanitize?: Sanitize;\n}\n\n/**\n * Default symbols in front of the type badge: three ASCII characters each,\n * which every terminal and font draws, one column per character. Emoji are\n * missing from some fonts and their width differs between terminals, which\n * shifts the badge.\n */\nexport const DEFAULT_SYMBOLS: Readonly<Record<LogType, string>> = {\n // fatal: '⛔',\n // error: '❗',\n // warning: '⚠️',\n // info: 'ℹ️',\n // debug: '',\n // trace: '✅',\n // verbose: '',\n fatal: '[X]',\n error: '[!]',\n warning: '/!\\\\',\n info: '[i]',\n debug: '(?)',\n trace: '/\\\\/',\n verbose: '...',\n};\n\n/** One symbol for every log type, or symbols per type. */\nexport type Symbols = string | Readonly<Partial<Record<LogType, string>>>;\n\nexport interface HeaderOptions {\n /** Show the log id. Default: `false`. */\n readonly showId?: boolean;\n /**\n * Symbol in front of the type badge. A string is used as is for every\n * type (`''` for none). Symbols per type are merged over\n * `DEFAULT_SYMBOLS` (`undefined` keeps the default) and padded with spaces\n * to the widest one plus one, so the badges line up. Default:\n * `DEFAULT_SYMBOLS`.\n */\n readonly symbol?: Symbols;\n}\n\n/**\n * Text of each log type: a plain object with one property per type, built\n * as a literal so property reads stay fast. Read it with `typeText`.\n */\ntype TypeTexts = Readonly<Record<LogType, string>>;\n\nconst typeTexts = (text: (type: LogType) => string): TypeTexts => ({\n fatal: text('fatal'),\n error: text('error'),\n warning: text('warning'),\n info: text('info'),\n debug: text('debug'),\n trace: text('trace'),\n verbose: text('verbose'),\n});\n\n/**\n * Text of `type` in `texts`, or `undefined` for other types, e.g. one\n * changed by a transformer: inherited keys (`toString`, `__proto__`) are not\n * strings.\n */\nconst typeText = (texts: TypeTexts, type: string): string | undefined => {\n const text: unknown = texts[type as LogType];\n return typeof text === 'string' ? text : undefined;\n};\n\n/**\n * Badge text of a type: centered in the width of the longest type.\n */\nconst badgeText = (type: string): string =>\n ` ${padTextMiddle(type, LOG_TYPE_MAX_LENGTH)} `;\n\nconst BADGES = typeTexts(badgeText);\n\n/**\n * Symbol text of each type, resolved once per plugin.\n *\n * @throws TypeError if `symbol` is neither a string nor symbols per type,\n * or a symbol is not a string.\n */\nconst resolveSymbols = (symbol: Symbols = DEFAULT_SYMBOLS): TypeTexts => {\n if (typeof symbol === 'string') return typeTexts(() => symbol);\n const symbols: Partial<Record<LogType, string>> = {};\n // configuration from JavaScript is not type checked\n const record: unknown = symbol;\n if (typeof record !== 'object' || record === null || Array.isArray(record))\n throw new TypeError(\n `symbol: must be a string or symbols per type, got ${\n record === null ? 'null'\n : Array.isArray(record) ? 'an array'\n : typeof record\n }.`\n );\n let width = 0;\n for (const type of LOG_TYPES) {\n // `undefined` keeps the default, like an option that is not set: types\n // without `exactOptionalPropertyTypes` allow it\n const value: unknown =\n (record as Partial<Record<LogType, unknown>>)[type] ??\n DEFAULT_SYMBOLS[type];\n if (typeof value !== 'string')\n throw new TypeError(\n `symbol: the symbol of ${type} must be a string, got ${typeof value}.`\n );\n symbols[type] = value;\n width = Math.max(width, textWidth(value));\n }\n // padded to the widest symbol plus one space, so the badges line up\n return typeTexts((type) => {\n const value = symbols[type] ?? '';\n return width > 0 ? value + ' '.repeat(width - textWidth(value) + 1) : value;\n });\n};\n\n/**\n * Template functions rendering the common log header: dim id, timestamp and\n * symbol, the type badge and a hidden kind.\n *\n * @throws TypeError if a symbol is not a string.\n */\nexport const headerTemplates = ({\n showId = false,\n symbol,\n}: HeaderOptions): TemplateMap => {\n const symbols = resolveSymbols(symbol);\n return {\n id: (value, { styles: { textDim = '', reset = '' } }) =>\n showId ? `${paint(textDim, `#${String(value)}`, reset)} ` : '',\n timestamp: (value, { styles: { textDim = '', reset = '' } }) =>\n `${paint(textDim, String(value), reset)} `,\n // symbol and badge texts are prepared per type; other types (changed by\n // a transformer) get no symbol and a badge built per log\n type: (value, { styles: { textDim = '', textBadge = '', reset = '' } }) => {\n const type = String(value);\n return `${paint(textDim, typeText(symbols, type) ?? '', reset)}${paint(\n textBadge,\n typeText(BADGES, type) ?? badgeText(type),\n reset\n )} `;\n },\n kind: () => '',\n };\n};\n"],"names":[],"mappings":";;;;AAgBA;;;;;;;;;;;;;;;;AAgBG;AACI,MAAM,mBAAmB,GAAe;AAC7C,IAAA,GAAG,EAAE;QACH,OAAO,EAAE,GAAG,CAAC,aAAa;;AAE1B,QAAA,UAAU,EAAE,EAAE;AACf,KAAA;AACD,IAAA,KAAK,EAAE;AACL,QAAA,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK;;AAE1B,QAAA,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK;AAC/B,KAAA;AACD,IAAA,KAAK,EAAE;AACL,QAAA,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC,WAAW;AAChC,QAAA,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW;AACrC,KAAA;AACD,IAAA,OAAO,EAAE;AACP,QAAA,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ;AAC7B,QAAA,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ;AAClC,KAAA;AACD,IAAA,IAAI,EAAE;AACJ,QAAA,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM;AAC3B,QAAA,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM;AAChC,KAAA;AACD,IAAA,KAAK,EAAE;AACL,QAAA,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC,SAAS;AAC9B,QAAA,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS;AACnC,KAAA;AACD,IAAA,KAAK,EAAE;AACL,QAAA,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM;AAC3B,QAAA,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM;AAChC,KAAA;AACD,IAAA,OAAO,EAAE;AACP,QAAA,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC,aAAa;AAClC,QAAA,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,aAAa;AAC/B,KAAA;;AAGH;;;AAGG;AACI,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,IAAY,EAAE,KAAa,KAC9D,KAAK,IAAI,IAAI,GAAG,CAAA,EAAG,KAAK,CAAA,EAAG,IAAI,CAAA,EAAG,KAAK,CAAA,CAAE,GAAG;AAE9C;;;AAGG;AACI,MAAM,iBAAiB,GAAG,CAC/B,MAAe,EACf,EAAE,OAAO,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,EAAe,EACzC,EAAE,KAAK,EAAa,KAEpB,KAAK,CAAC,OAAO,EAAE,kBAAkB,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK;AAE1E;;;;;;;AAOG;MACU,gBAAgB,GAAG,CAC9B,IAAgB,EAChB,QAAgC,KAClB;IACd,IAAI,QAAQ,KAAK,SAAS;AAAE,QAAA,OAAO,IAAI;AACvC,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAe,EAAE,IAAI,CAAC;IACrE,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAyB;QAC/D,MAAM,CAAC,KAAK,CAAC,GAAG;YACd,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;YACzD,GAAG,QAAQ,CAAC,KAAK,CAAC;SACnB;AACH,IAAA,OAAO,MAAM;AACf;AAUA;;;;;AAKG;AACI,MAAM,eAAe,GAAsC;;;;;;;;AAQhE,IAAA,KAAK,EAAE,KAAK;AACZ,IAAA,KAAK,EAAE,KAAK;AACZ,IAAA,OAAO,EAAE,MAAM;AACf,IAAA,IAAI,EAAE,KAAK;AACX,IAAA,KAAK,EAAE,KAAK;AACZ,IAAA,KAAK,EAAE,MAAM;AACb,IAAA,OAAO,EAAE,KAAK;;AAyBhB,MAAM,SAAS,GAAG,CAAC,IAA+B,MAAiB;AACjE,IAAA,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC;AACpB,IAAA,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC;AACpB,IAAA,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;AACxB,IAAA,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;AAClB,IAAA,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC;AACpB,IAAA,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC;AACpB,IAAA,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;AACzB,CAAA,CAAC;AAEF;;;;AAIG;AACH,MAAM,QAAQ,GAAG,CAAC,KAAgB,EAAE,IAAY,KAAwB;AACtE,IAAA,MAAM,IAAI,GAAY,KAAK,CAAC,IAAe,CAAC;AAC5C,IAAA,OAAO,OAAO,IAAI,KAAK,QAAQ,GAAG,IAAI,GAAG,SAAS;AACpD,CAAC;AAED;;AAEG;AACH,MAAM,SAAS,GAAG,CAAC,IAAY,KAC7B,CAAA,CAAA,EAAI,aAAa,CAAC,IAAI,EAAE,mBAAmB,CAAC,GAAG;AAEjD,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC;AAEnC;;;;;AAKG;AACH,MAAM,cAAc,GAAG,CAAC,MAAA,GAAkB,eAAe,KAAe;IACtE,IAAI,OAAO,MAAM,KAAK,QAAQ;AAAE,QAAA,OAAO,SAAS,CAAC,MAAM,MAAM,CAAC;IAC9D,MAAM,OAAO,GAAqC,EAAE;;IAEpD,MAAM,MAAM,GAAY,MAAM;AAC9B,IAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QACxE,MAAM,IAAI,SAAS,CACjB,CAAA,kDAAA,EACE,MAAM,KAAK,IAAI,GAAG;cAChB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG;AAC1B,kBAAE,OAAO,MACX,CAAA,CAAA,CAAG,CACJ;IACH,IAAI,KAAK,GAAG,CAAC;AACb,IAAA,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE;;;AAG5B,QAAA,MAAM,KAAK,GACR,MAA4C,CAAC,IAAI,CAAC;YACnD,eAAe,CAAC,IAAI,CAAC;QACvB,IAAI,OAAO,KAAK,KAAK,QAAQ;YAC3B,MAAM,IAAI,SAAS,CACjB,CAAA,sBAAA,EAAyB,IAAI,0BAA0B,OAAO,KAAK,CAAA,CAAA,CAAG,CACvE;AACH,QAAA,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK;AACrB,QAAA,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;IAC3C;;AAEA,IAAA,OAAO,SAAS,CAAC,CAAC,IAAI,KAAI;QACxB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE;QACjC,OAAO,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK;AAC7E,IAAA,CAAC,CAAC;AACJ,CAAC;AAED;;;;;AAKG;AACI,MAAM,eAAe,GAAG,CAAC,EAC9B,MAAM,GAAG,KAAK,EACd,MAAM,GACQ,KAAiB;AAC/B,IAAA,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC;IACtC,OAAO;AACL,QAAA,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,KAClD,MAAM,GAAG,CAAA,EAAG,KAAK,CAAC,OAAO,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,CAAA,CAAE,EAAE,KAAK,CAAC,GAAG,GAAG,EAAE;AAChE,QAAA,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,KACzD,CAAA,EAAG,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAA,CAAA,CAAG;;;QAG5C,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,SAAS,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,KAAI;AACxE,YAAA,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC;AAC1B,YAAA,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,CAAA,EAAG,KAAK,CACpE,SAAS,EACT,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,EACzC,KAAK,CACN,GAAG;QACN,CAAC;AACD,QAAA,IAAI,EAAE,MAAM,EAAE;KACf;AACH;;"}
|