Files
authentik/packages/logger-js/lib/shared.js
dependabot[bot] 8262989de0 web: bump typescript from 5.9.3 to 6.0.2 in /web (#21107)
* Bump related TS packages.

* Fix type.

* Fix styles.

* web: bump typescript from 5.9.3 to 6.0.2 in /web

Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.9.3 to 6.0.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.9.3...v6.0.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Partial upgrade.

* Add dep.

* Re-add preinstall.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-26 01:35:40 +01:00

286 lines
6.2 KiB
JavaScript

/**
* @file Console logger for browser environments.
*
* @remarks
* The repetition of log levels, typedefs, and method signatures is intentional
* to give IDEs and type checkers a mapping of log methods to the TypeScript
* provided JSDoc comments.
*
* Additionally, no wrapper functions are used to avoid the browser's console
* reported call site being the wrapper instead of the actual caller.
*
* @import {
* ChildLoggerOptions,
* LoggerOptions,
* Logger as PinoLogger,
* BaseLogger as PinoBaseLogger,
* Level as PinoLevel,
* LogFn as PinoLogFn
* } from "pino"
*/
/* eslint-disable no-console */
/**
* @typedef {PinoLogger} Logger
*/
/**
* @typedef {PinoLevel} Level
*/
/**
* @typedef {PinoLogFn} LogFn
*/
/**
* @typedef {Pick<PinoBaseLogger, Exclude<Level, "fatal">>} BaseLogger
*/
//#region Constants
/**
* Labels log levels in the browser console.
* @satisfies {Record<Level, string>}
*/
export const LogLevelLabel = /** @type {const} */ ({
info: "[INFO]",
warn: "[WARN]",
error: "[ERROR]",
debug: "[DEBUG]",
trace: "[TRACE]",
fatal: "[FATAL]",
});
/**
* Predefined log levels.
*/
export const LogLevels = /** @type {Level[]} */ (Object.keys(LogLevelLabel));
/**
* @callback LoggerFactory
* @param {string | null} [prefix]
* @param {...string} args
* @returns {Logger}
*/
/**
* Colors for log levels in the browser console.
*
* @remarks
*
* The colors are derived from Carbon Design System's palette to ensure
* sufficient contrast and accessibility across light and dark themes.
*/
const LogLevelColors = /** @type {const} */ ({
info: `light-dark(#0043CE, #4589FF)`,
warn: `light-dark(#F1C21B, #F1C21B)`,
error: `light-dark(#DA1E28, #FA4D56)`,
debug: `light-dark(#8A3FFC, #A56EFF)`,
trace: `light-dark(#8A3FFC, #A56EFF)`,
fatal: `light-dark(#DA1E28, #FA4D56)`,
});
//#region Functions
/**
* Creates a logger with the given prefix.
*
* @type {LoggerFactory}
*/
function createConsoleLogger(prefix, ...args) {
const msgPrefix = prefix ? `(${prefix}):` : ":";
/**
* @type {Partial<Logger>}
*/
const logger = {
msgPrefix,
};
for (const level of LogLevels) {
const label = LogLevelLabel[level];
// @ts-expect-error Alias the log method to the appropriate console method,
// defaulting to console.log if the level is not supported.
const method = level in console ? console[level] : console.log;
logger[level] = method.bind(console, `${label} ${msgPrefix}`, ...args);
}
return /** @type {Logger} */ (logger);
}
/**
* @typedef {Logger} FixtureLogger
*/
/**
* @this {Logger}
* @param {string} fixtureName
* @param {string} [testName]
* @param {ChildLoggerOptions} [options]
* @returns {FixtureLogger}
*/
export function fixture(fixtureName, testName, options) {
return this.child(
{ name: fixtureName },
{
msgPrefix: `[${testName}] `,
...options,
},
);
}
/**
* @this {Logger}
* @param {Record<string, unknown>} bindings
* @param {ChildLoggerOptions} [_options]
* @returns {Logger}
*/
export function child(bindings, _options) {
const prefix = typeof bindings.name === "string" ? bindings.name : null;
return Object.assign(createConsoleLogger(prefix), { ...bindings });
}
/**
* @this {{ child: typeof child }}
* @param {string} label
* @returns {IConsoleLogger}
*/
export function prefix(label) {
// @ts-expect-error Create a child logger with the given prefix.
return this.child({ name: label });
}
/**
* @typedef {object} CustomLoggerMethods
* @property {typeof fixture} fixture
* @property {typeof prefix} prefix
* @property {typeof child} child
*/
/**
* @typedef {Record<Level, LogFn>} BaseConsoleLogger
*/
/**
* @typedef {BaseConsoleLogger & CustomLoggerMethods} IConsoleLogger
*/
/**
* @type {CustomLoggerMethods}
*/
export const customLoggerMethods = {
fixture,
prefix,
child,
};
/**
* Creates a lightweight logger that mimics the Pino API but falls back to
* console methods when Pino is not available.
* @param {LoggerOptions<never, false>} options
* @return {IConsoleLogger}
*/
export function pinoLight(options) {
const baseLogger = createConsoleLogger(options.name);
/**
* @type {IConsoleLogger}
*/
const logger = {
...baseLogger,
fixture,
prefix,
child,
};
return logger;
}
//#endregion
//#region Functions
/**
* Creates a logger with the given prefix.
*
* @param {string} [prefix]
* @param {...string} args
* @returns {Logger}
*
*/
export function createLogger(prefix, ...args) {
const msgPrefix = prefix ? `(${prefix}):` : ":";
/**
* @type {Partial<Logger>}
*/
const logger = {
msgPrefix,
};
for (const level of LogLevels) {
const label = LogLevelLabel[level];
const color = LogLevelColors[level];
// @ts-expect-error Alias the log method to the appropriate console method,
// defaulting to console.log if the level is not supported.
const method = level in console ? console[level] : console.log;
logger[level] = method.bind(
console,
`%c${label}%c ${msgPrefix}%c`,
`font-weight: 700; color: ${color};`,
`font-weight: 600; color: CanvasText;`,
"",
...args,
);
}
return /** @type {Logger} */ (logger);
}
//#endregion
//#region Console Logger
/**
* A singleton logger instance for the browser.
*
* ```js
* import { ConsoleLogger } from "#logger/browser";
*
* ConsoleLogger.info("Hello, world!");
* ```
*
* @implements {IConsoleLogger}
* @runtime browser
*/
// @ts-expect-error Logging properties are dynamically assigned.
export class ConsoleLogger {
/** @type {typeof console.info} */
static info;
/** @type {typeof console.warn} */
static warn;
/** @type {typeof console.error} */
static error;
/** @type {typeof console.debug} */
static debug;
/** @type {typeof console.trace} */
static trace;
/**
* Creates a logger with the given prefix.
* @param {string} logPrefix
*/
static prefix(logPrefix) {
return createLogger(logPrefix);
}
}
Object.assign(ConsoleLogger, createLogger());
//#endregion