chore: migrate to oxlint and oxfmt

Co-authored-by: Christoph Nakazawa <christoph.pojer@gmail.com>
This commit is contained in:
Peter Steinberger
2026-01-14 14:31:43 +00:00
parent 912ebffc63
commit c379191f80
1480 changed files with 28608 additions and 43547 deletions

View File

@@ -4,38 +4,28 @@ import { stripRedundantSubsystemPrefixForConsole } from "../logging.js";
describe("stripRedundantSubsystemPrefixForConsole", () => {
it("drops '<subsystem>:' prefix", () => {
expect(
stripRedundantSubsystemPrefixForConsole("discord: hello", "discord"),
).toBe("hello");
expect(stripRedundantSubsystemPrefixForConsole("discord: hello", "discord")).toBe("hello");
});
it("drops '<Subsystem>:' prefix case-insensitively", () => {
expect(
stripRedundantSubsystemPrefixForConsole("WhatsApp: hello", "whatsapp"),
).toBe("hello");
expect(stripRedundantSubsystemPrefixForConsole("WhatsApp: hello", "whatsapp")).toBe("hello");
});
it("drops '<subsystem> ' prefix", () => {
expect(
stripRedundantSubsystemPrefixForConsole(
"discord gateway: closed",
"discord",
),
).toBe("gateway: closed");
expect(stripRedundantSubsystemPrefixForConsole("discord gateway: closed", "discord")).toBe(
"gateway: closed",
);
});
it("drops '[subsystem]' prefix", () => {
expect(
stripRedundantSubsystemPrefixForConsole(
"[discord] connection stalled",
"discord",
),
).toBe("connection stalled");
expect(stripRedundantSubsystemPrefixForConsole("[discord] connection stalled", "discord")).toBe(
"connection stalled",
);
});
it("keeps messages that do not start with the subsystem", () => {
expect(
stripRedundantSubsystemPrefixForConsole("discordant: hello", "discord"),
).toBe("discordant: hello");
expect(stripRedundantSubsystemPrefixForConsole("discordant: hello", "discord")).toBe(
"discordant: hello",
);
});
});

View File

@@ -28,8 +28,7 @@ function normalizeConsoleStyle(style?: string): ConsoleStyle {
function resolveConsoleSettings(): ConsoleSettings {
const cfg: ClawdbotConfig["logging"] | undefined =
(loggingState.overrideSettings as LoggerSettings | null) ??
loadConfig().logging;
(loggingState.overrideSettings as LoggerSettings | null) ?? loadConfig().logging;
const level = normalizeConsoleLevel(cfg?.consoleLevel);
const style = normalizeConsoleStyle(cfg?.consoleStyle);
return { level, style };
@@ -64,11 +63,8 @@ export function setConsoleSubsystemFilter(filters?: string[] | null): void {
loggingState.consoleSubsystemFilter = null;
return;
}
const normalized = filters
.map((value) => value.trim())
.filter((value) => value.length > 0);
loggingState.consoleSubsystemFilter =
normalized.length > 0 ? normalized : null;
const normalized = filters.map((value) => value.trim()).filter((value) => value.length > 0);
loggingState.consoleSubsystemFilter = normalized.length > 0 ? normalized : null;
}
export function shouldLogSubsystemToConsole(subsystem: string): boolean {
@@ -76,9 +72,7 @@ export function shouldLogSubsystemToConsole(subsystem: string): boolean {
if (!filter || filter.length === 0) {
return true;
}
return filter.some(
(prefix) => subsystem === prefix || subsystem.startsWith(`${prefix}/`),
);
return filter.some((prefix) => subsystem === prefix || subsystem.startsWith(`${prefix}/`));
}
const SUPPRESSED_CONSOLE_PREFIXES = [
@@ -91,9 +85,7 @@ const SUPPRESSED_CONSOLE_PREFIXES = [
function shouldSuppressConsoleMessage(message: string): boolean {
if (isVerbose()) return false;
return SUPPRESSED_CONSOLE_PREFIXES.some((prefix) =>
message.startsWith(prefix),
);
return SUPPRESSED_CONSOLE_PREFIXES.some((prefix) => message.startsWith(prefix));
}
function isEpipeError(err: unknown): boolean {

View File

@@ -12,9 +12,7 @@ export type LogLevel = (typeof ALLOWED_LOG_LEVELS)[number];
export function normalizeLogLevel(level?: string, fallback: LogLevel = "info") {
const candidate = (level ?? fallback).trim();
return ALLOWED_LOG_LEVELS.includes(candidate as LogLevel)
? (candidate as LogLevel)
: fallback;
return ALLOWED_LOG_LEVELS.includes(candidate as LogLevel) ? (candidate as LogLevel) : fallback;
}
export function levelToMinLevel(level: LogLevel): number {

View File

@@ -34,8 +34,7 @@ export type LoggerResolvedSettings = ResolvedSettings;
function resolveSettings(): ResolvedSettings {
const cfg: ClawdbotConfig["logging"] | undefined =
(loggingState.overrideSettings as LoggerSettings | null) ??
loadConfig().logging;
(loggingState.overrideSettings as LoggerSettings | null) ?? loadConfig().logging;
const level = normalizeLogLevel(cfg?.level, "info");
const file = cfg?.file ?? defaultRollingPathForToday();
return { level, file };
@@ -47,9 +46,7 @@ function settingsChanged(a: ResolvedSettings | null, b: ResolvedSettings) {
}
export function isFileLogLevelEnabled(level: LogLevel): boolean {
const settings =
(loggingState.cachedSettings as ResolvedSettings | null) ??
resolveSettings();
const settings = (loggingState.cachedSettings as ResolvedSettings | null) ?? resolveSettings();
if (!loggingState.cachedSettings) loggingState.cachedSettings = settings;
if (settings.level === "silent") return false;
return levelToMinLevel(level) <= levelToMinLevel(settings.level);
@@ -106,10 +103,7 @@ export function getChildLogger(
}
// Baileys expects a pino-like logger shape. Provide a lightweight adapter.
export function toPinoLikeLogger(
logger: TsLogger<LogObj>,
level: LogLevel,
): PinoLikeLogger {
export function toPinoLikeLogger(logger: TsLogger<LogObj>, level: LogLevel): PinoLikeLogger {
const buildChild = (bindings?: Record<string, unknown>) =>
toPinoLikeLogger(
logger.getSubLogger({
@@ -180,11 +174,7 @@ function pruneOldRollingLogs(dir: string): void {
const cutoff = Date.now() - MAX_LOG_AGE_MS;
for (const entry of entries) {
if (!entry.isFile()) continue;
if (
!entry.name.startsWith(`${LOG_PREFIX}-`) ||
!entry.name.endsWith(LOG_SUFFIX)
)
continue;
if (!entry.name.startsWith(`${LOG_PREFIX}-`) || !entry.name.endsWith(LOG_SUFFIX)) continue;
const fullPath = path.join(dir, entry.name);
try {
const stat = fs.statSync(fullPath);

View File

@@ -20,9 +20,7 @@ describe("parseLogLine", () => {
expect(parsed?.time).toBe("2026-01-09T01:38:41.523Z");
expect(parsed?.level).toBe("info");
expect(parsed?.subsystem).toBe("gateway/channels/whatsapp");
expect(parsed?.message).toBe(
'{"subsystem":"gateway/channels/whatsapp"} connected',
);
expect(parsed?.message).toBe('{"subsystem":"gateway/channels/whatsapp"} connected');
expect(parsed?.raw).toBe(line);
});

View File

@@ -26,8 +26,7 @@ function parseMetaName(raw?: unknown): { subsystem?: string; module?: string } {
try {
const parsed = JSON.parse(raw) as Record<string, unknown>;
return {
subsystem:
typeof parsed.subsystem === "string" ? parsed.subsystem : undefined,
subsystem: typeof parsed.subsystem === "string" ? parsed.subsystem : undefined,
module: typeof parsed.module === "string" ? parsed.module : undefined,
};
} catch {
@@ -40,8 +39,7 @@ export function parseLogLine(raw: string): ParsedLogLine | null {
const parsed = JSON.parse(raw) as Record<string, unknown>;
const meta = parsed._meta as Record<string, unknown> | undefined;
const nameMeta = parseMetaName(meta?.name);
const levelRaw =
typeof meta?.logLevelName === "string" ? meta.logLevelName : undefined;
const levelRaw = typeof meta?.logLevelName === "string" ? meta.logLevelName : undefined;
return {
time:
typeof parsed.time === "string"

View File

@@ -71,11 +71,7 @@ describe("redactSensitiveText", () => {
patterns: defaults,
});
expect(output).toBe(
[
"-----BEGIN PRIVATE KEY-----",
"…redacted…",
"-----END PRIVATE KEY-----",
].join("\n"),
["-----BEGIN PRIVATE KEY-----", "…redacted…", "-----END PRIVATE KEY-----"].join("\n"),
);
});

View File

@@ -76,9 +76,7 @@ function redactPemBlock(block: string): string {
function redactMatch(match: string, groups: string[]): string {
if (match.includes("PRIVATE KEY-----")) return redactPemBlock(match);
const token =
groups
.filter((value) => typeof value === "string" && value.length > 0)
.at(-1) ?? match;
groups.filter((value) => typeof value === "string" && value.length > 0).at(-1) ?? match;
const masked = maskToken(token);
if (token === match) return masked;
return match.replace(token, masked);
@@ -102,10 +100,7 @@ function resolveConfigRedaction(): RedactOptions {
};
}
export function redactSensitiveText(
text: string,
options?: RedactOptions,
): string {
export function redactSensitiveText(text: string, options?: RedactOptions): string {
if (!text) return text;
const resolved = options ?? resolveConfigRedaction();
if (normalizeMode(resolved.mode) === "off") return text;

View File

@@ -22,10 +22,7 @@ export type SubsystemLogger = {
child: (name: string) => SubsystemLogger;
};
function shouldLogToConsole(
level: LogLevel,
settings: { level: LogLevel },
): boolean {
function shouldLogToConsole(level: LogLevel, settings: { level: LogLevel }): boolean {
if (settings.level === "silent") return false;
const current = levelToMinLevel(level);
const min = levelToMinLevel(settings.level);
@@ -47,37 +44,18 @@ function getColorForConsole(): ChalkInstance {
process.env.FORCE_COLOR.trim() !== "0";
if (process.env.NO_COLOR && !hasForceColor) return new Chalk({ level: 0 });
const hasTty = Boolean(process.stdout.isTTY || process.stderr.isTTY);
return hasTty || isRichConsoleEnv()
? new Chalk({ level: 1 })
: new Chalk({ level: 0 });
return hasTty || isRichConsoleEnv() ? new Chalk({ level: 1 }) : new Chalk({ level: 0 });
}
const SUBSYSTEM_COLORS = [
"cyan",
"green",
"yellow",
"blue",
"magenta",
"red",
] as const;
const SUBSYSTEM_COLOR_OVERRIDES: Record<
string,
(typeof SUBSYSTEM_COLORS)[number]
> = {
const SUBSYSTEM_COLORS = ["cyan", "green", "yellow", "blue", "magenta", "red"] as const;
const SUBSYSTEM_COLOR_OVERRIDES: Record<string, (typeof SUBSYSTEM_COLORS)[number]> = {
"gmail-watcher": "blue",
};
const SUBSYSTEM_PREFIXES_TO_DROP = [
"gateway",
"channels",
"providers",
] as const;
const SUBSYSTEM_PREFIXES_TO_DROP = ["gateway", "channels", "providers"] as const;
const SUBSYSTEM_MAX_SEGMENTS = 2;
const CHANNEL_SUBSYSTEM_PREFIXES = new Set<string>(CHAT_CHANNEL_ORDER);
function pickSubsystemColor(
color: ChalkInstance,
subsystem: string,
): ChalkInstance {
function pickSubsystemColor(color: ChalkInstance, subsystem: string): ChalkInstance {
const override = SUBSYSTEM_COLOR_OVERRIDES[subsystem];
if (override) return color[override];
let hash = 0;
@@ -94,9 +72,7 @@ function formatSubsystemForConsole(subsystem: string): string {
const original = parts.join("/") || subsystem;
while (
parts.length > 0 &&
SUBSYSTEM_PREFIXES_TO_DROP.includes(
parts[0] as (typeof SUBSYSTEM_PREFIXES_TO_DROP)[number],
)
SUBSYSTEM_PREFIXES_TO_DROP.includes(parts[0] as (typeof SUBSYSTEM_PREFIXES_TO_DROP)[number])
) {
parts.shift();
}
@@ -132,10 +108,7 @@ export function stripRedundantSubsystemPrefixForConsole(
const prefix = message.slice(0, displaySubsystem.length);
if (prefix.toLowerCase() !== displaySubsystem.toLowerCase()) return message;
const next = message.slice(
displaySubsystem.length,
displaySubsystem.length + 1,
);
const next = message.slice(displaySubsystem.length, displaySubsystem.length + 1);
if (next !== ":" && next !== " ") return message;
let i = displaySubsystem.length;
@@ -153,9 +126,7 @@ function formatConsoleLine(opts: {
meta?: Record<string, unknown>;
}): string {
const displaySubsystem =
opts.style === "json"
? opts.subsystem
: formatSubsystemForConsole(opts.subsystem);
opts.style === "json" ? opts.subsystem : formatSubsystemForConsole(opts.subsystem);
if (opts.style === "json") {
return JSON.stringify({
time: new Date().toISOString(),
@@ -176,14 +147,8 @@ function formatConsoleLine(opts: {
: opts.level === "debug" || opts.level === "trace"
? color.gray
: color.cyan;
const displayMessage = stripRedundantSubsystemPrefixForConsole(
opts.message,
displaySubsystem,
);
const time =
opts.style === "pretty"
? color.gray(new Date().toISOString().slice(11, 19))
: "";
const displayMessage = stripRedundantSubsystemPrefixForConsole(opts.message, displaySubsystem);
const time = opts.style === "pretty" ? color.gray(new Date().toISOString().slice(11, 19)) : "";
const prefixToken = prefixColor(prefix);
const head = [time, prefixToken].filter(Boolean).join(" ");
return `${head} ${levelColor(displayMessage)}`;
@@ -192,16 +157,10 @@ function formatConsoleLine(opts: {
function writeConsoleLine(level: LogLevel, line: string) {
const sanitized =
process.platform === "win32" && process.env.GITHUB_ACTIONS === "true"
? line
.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "?")
.replace(/[\uD800-\uDFFF]/g, "?")
? line.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "?").replace(/[\uD800-\uDFFF]/g, "?")
: line;
const sink = loggingState.rawConsole ?? console;
if (
loggingState.forceConsoleToStderr ||
level === "error" ||
level === "fatal"
) {
if (loggingState.forceConsoleToStderr || level === "error" || level === "fatal") {
(sink.error ?? console.error)(sanitized);
} else if (level === "warn") {
(sink.warn ?? console.warn)(sanitized);
@@ -218,9 +177,9 @@ function logToFile(
) {
if (level === "silent") return;
const safeLevel = level as Exclude<LogLevel, "silent">;
const method = (fileLogger as unknown as Record<string, unknown>)[
safeLevel
] as unknown as ((...args: unknown[]) => void) | undefined;
const method = (fileLogger as unknown as Record<string, unknown>)[safeLevel] as unknown as
| ((...args: unknown[]) => void)
| undefined;
if (typeof method !== "function") return;
if (meta && Object.keys(meta).length > 0) {
method.call(fileLogger, meta, message);
@@ -235,11 +194,7 @@ export function createSubsystemLogger(subsystem: string): SubsystemLogger {
if (!fileLogger) fileLogger = getChildLogger({ subsystem });
return fileLogger;
};
const emit = (
level: LogLevel,
message: string,
meta?: Record<string, unknown>,
) => {
const emit = (level: LogLevel, message: string, meta?: Record<string, unknown>) => {
const consoleSettings = getConsoleSettings();
let consoleMessageOverride: string | undefined;
let fileMeta = meta;
@@ -258,10 +213,7 @@ export function createSubsystemLogger(subsystem: string): SubsystemLogger {
const line = formatConsoleLine({
level,
subsystem,
message:
consoleSettings.style === "json"
? message
: (consoleMessageOverride ?? message),
message: consoleSettings.style === "json" ? message : (consoleMessageOverride ?? message),
style: consoleSettings.style,
meta: fileMeta,
});