refactor: extract app logging runtime adapters

This commit is contained in:
2026-02-10 00:46:28 -08:00
parent 355a5ae37a
commit 80ef464885
4 changed files with 62 additions and 11 deletions

View File

@@ -0,0 +1,28 @@
import test from "node:test";
import assert from "node:assert/strict";
import { createAppLoggingRuntimeService } from "./app-logging-runtime-service";
test("createAppLoggingRuntimeService routes logs and formats config warnings", () => {
const lines: string[] = [];
const logger = {
log: (line: string) => lines.push(`log:${line}`),
warn: (line: string) => lines.push(`warn:${line}`),
error: (line: string) => lines.push(`error:${line}`),
};
const runtime = createAppLoggingRuntimeService(logger);
runtime.logInfo("hello");
runtime.logWarning("careful");
runtime.logNoRunningInstance();
runtime.logConfigWarning({
path: "x.y",
value: "bad",
fallback: "good",
message: "invalid",
});
assert.equal(lines[0], "log:hello");
assert.equal(lines[1], "warn:careful");
assert.equal(lines[2], "error:No running instance. Use --start to launch the app.");
assert.match(lines[3], /^warn:\[config\] x\.y: invalid /);
});

View File

@@ -0,0 +1,28 @@
import { ConfigValidationWarning } from "../../types";
import { logConfigWarningRuntimeService } from "./config-warning-runtime-service";
export interface AppLoggingRuntime {
logInfo: (message: string) => void;
logWarning: (message: string) => void;
logNoRunningInstance: () => void;
logConfigWarning: (warning: ConfigValidationWarning) => void;
}
export function createAppLoggingRuntimeService(
logger: Pick<Console, "log" | "warn" | "error"> = console,
): AppLoggingRuntime {
return {
logInfo: (message) => {
logger.log(message);
},
logWarning: (message) => {
logger.warn(message);
},
logNoRunningInstance: () => {
logger.error("No running instance. Use --start to launch the app.");
},
logConfigWarning: (warning) => {
logConfigWarningRuntimeService(warning, (line) => logger.warn(line));
},
};
}

View File

@@ -206,7 +206,7 @@ import { runAppShutdownRuntimeService } from "./core/services/app-shutdown-runti
import { createMpvIpcClientDepsRuntimeService } from "./core/services/mpv-client-deps-runtime-service";
import { createAppLifecycleDepsRuntimeService } from "./core/services/app-lifecycle-deps-runtime-service";
import { createRuntimeOptionsManagerRuntimeService } from "./core/services/runtime-options-manager-runtime-service";
import { logConfigWarningRuntimeService } from "./core/services/config-warning-runtime-service";
import { createAppLoggingRuntimeService } from "./core/services/app-logging-runtime-service";
import {
runSubsyncManualFromIpcRuntimeService,
triggerSubsyncFromConfigRuntimeService,
@@ -236,6 +236,7 @@ const isDev =
process.argv.includes("--dev") || process.argv.includes("--debug");
const texthookerService = new TexthookerService();
const subtitleWsService = new SubtitleWebSocketService();
const appLogger = createAppLoggingRuntimeService();
function getDefaultSocketPath(): string {
if (process.platform === "win32") {
@@ -473,9 +474,7 @@ if (initialArgs.generateConfig && !shouldStartApp(initialArgs)) {
parseArgs: (argv) => parseArgs(argv),
handleCliCommand: (args, source) => handleCliCommand(args, source),
printHelp: () => printHelp(DEFAULT_TEXTHOOKER_PORT),
logNoRunningInstance: () => {
console.error("No running instance. Use --start to launch the app.");
},
logNoRunningInstance: () => appLogger.logNoRunningInstance(),
onReady: async () => {
await runAppReadyRuntimeService({
loadSubtitlePosition: () => loadSubtitlePosition(),
@@ -533,9 +532,7 @@ if (initialArgs.generateConfig && !shouldStartApp(initialArgs)) {
},
getResolvedConfig: () => getResolvedConfig(),
getConfigWarnings: () => configService.getWarnings(),
logConfigWarning: (warning) => {
logConfigWarningRuntimeService(warning, (line) => console.warn(line));
},
logConfigWarning: (warning) => appLogger.logConfigWarning(warning),
initRuntimeOptionsManager: () => {
runtimeOptionsManager = createRuntimeOptionsManagerRuntimeService({
getAnkiConfig: () => configService.getConfig().ankiConnect,
@@ -559,9 +556,7 @@ if (initialArgs.generateConfig && !shouldStartApp(initialArgs)) {
startSubtitleWebsocket: (port) => {
subtitleWsService.start(port, () => currentSubText);
},
log: (message) => {
console.log(message);
},
log: (message) => appLogger.logInfo(message),
createMecabTokenizerAndCheck: async () => {
mecabTokenizer = new MecabTokenizer();
await mecabTokenizer.checkAvailability();