refactor: extract config generation startup flow

This commit is contained in:
2026-02-10 00:55:43 -08:00
parent aacb13c71e
commit dce1981f44
4 changed files with 110 additions and 12 deletions

View File

@@ -16,7 +16,7 @@
"docs:build": "vitepress build docs",
"docs:preview": "vitepress preview docs --host 0.0.0.0 --port 4173 --strictPort",
"test:config": "pnpm run build && node --test dist/config/config.test.js",
"test:core": "pnpm run build && node --test dist/cli/args.test.js dist/cli/help.test.js dist/core/services/cli-command-service.test.js dist/core/services/numeric-shortcut-session-service.test.js dist/core/services/secondary-subtitle-service.test.js dist/core/services/mpv-render-metrics-service.test.js dist/core/services/mpv-runtime-service.test.js dist/core/services/runtime-options-runtime-service.test.js dist/core/services/overlay-modal-restore-service.test.js dist/core/services/runtime-config-service.test.js dist/core/services/overlay-bridge-runtime-service.test.js dist/core/services/overlay-visibility-facade-service.test.js dist/core/services/overlay-broadcast-runtime-service.test.js dist/core/services/app-ready-runtime-service.test.js dist/core/services/app-shutdown-runtime-service.test.js dist/core/services/mpv-client-deps-runtime-service.test.js dist/core/services/app-lifecycle-deps-runtime-service.test.js dist/core/services/runtime-options-manager-runtime-service.test.js dist/core/services/config-warning-runtime-service.test.js dist/core/services/app-logging-runtime-service.test.js dist/core/services/startup-resource-runtime-service.test.js",
"test:core": "pnpm run build && node --test dist/cli/args.test.js dist/cli/help.test.js dist/core/services/cli-command-service.test.js dist/core/services/numeric-shortcut-session-service.test.js dist/core/services/secondary-subtitle-service.test.js dist/core/services/mpv-render-metrics-service.test.js dist/core/services/mpv-runtime-service.test.js dist/core/services/runtime-options-runtime-service.test.js dist/core/services/overlay-modal-restore-service.test.js dist/core/services/runtime-config-service.test.js dist/core/services/overlay-bridge-runtime-service.test.js dist/core/services/overlay-visibility-facade-service.test.js dist/core/services/overlay-broadcast-runtime-service.test.js dist/core/services/app-ready-runtime-service.test.js dist/core/services/app-shutdown-runtime-service.test.js dist/core/services/mpv-client-deps-runtime-service.test.js dist/core/services/app-lifecycle-deps-runtime-service.test.js dist/core/services/runtime-options-manager-runtime-service.test.js dist/core/services/config-warning-runtime-service.test.js dist/core/services/app-logging-runtime-service.test.js dist/core/services/startup-resource-runtime-service.test.js dist/core/services/config-generation-runtime-service.test.js",
"test:subtitle": "pnpm run build && node --test dist/subtitle/stages.test.js dist/subtitle/pipeline.test.js",
"generate:config-example": "pnpm run build && node dist/generate-config-example.js",
"start": "pnpm run build && electron . --start",

View File

@@ -0,0 +1,67 @@
import test from "node:test";
import assert from "node:assert/strict";
import { runGenerateConfigFlowRuntimeService } from "./config-generation-runtime-service";
import { CliArgs } from "../../cli/args";
function makeArgs(overrides: Partial<CliArgs> = {}): CliArgs {
return {
start: false,
stop: false,
toggle: false,
toggleVisibleOverlay: false,
toggleInvisibleOverlay: false,
settings: false,
show: false,
hide: false,
showVisibleOverlay: false,
hideVisibleOverlay: false,
showInvisibleOverlay: false,
hideInvisibleOverlay: false,
copySubtitle: false,
copySubtitleMultiple: false,
mineSentence: false,
mineSentenceMultiple: false,
updateLastCardFromClipboard: false,
toggleSecondarySub: false,
triggerFieldGrouping: false,
triggerSubsync: false,
markAudioCard: false,
openRuntimeOptions: false,
texthooker: false,
help: false,
autoStartOverlay: false,
generateConfig: false,
backupOverwrite: false,
verbose: false,
...overrides,
};
}
test("runGenerateConfigFlowRuntimeService starts flow when generateConfig is set and app should not start", async () => {
const calls: string[] = [];
const handled = runGenerateConfigFlowRuntimeService(
makeArgs({ generateConfig: true }),
{
shouldStartApp: () => false,
generateConfig: async () => 7,
onSuccess: (code) => calls.push(`success:${code}`),
onError: () => calls.push("error"),
},
);
assert.equal(handled, true);
await new Promise((resolve) => setImmediate(resolve));
assert.deepEqual(calls, ["success:7"]);
});
test("runGenerateConfigFlowRuntimeService returns false when flow should not run", () => {
const handled = runGenerateConfigFlowRuntimeService(
makeArgs({ generateConfig: true, start: true }),
{
shouldStartApp: () => true,
generateConfig: async () => 0,
onSuccess: () => {},
onError: () => {},
},
);
assert.equal(handled, false);
});

View File

@@ -0,0 +1,26 @@
import { CliArgs } from "../../cli/args";
export interface ConfigGenerationRuntimeDeps {
shouldStartApp: (args: CliArgs) => boolean;
generateConfig: (args: CliArgs) => Promise<number>;
onSuccess: (exitCode: number) => void;
onError: (error: Error) => void;
}
export function runGenerateConfigFlowRuntimeService(
args: CliArgs,
deps: ConfigGenerationRuntimeDeps,
): boolean {
if (!args.generateConfig || deps.shouldStartApp(args)) {
return false;
}
deps.generateConfig(args)
.then((exitCode) => {
deps.onSuccess(exitCode);
})
.catch((error: Error) => {
deps.onError(error);
});
return true;
}

View File

@@ -211,6 +211,7 @@ import {
createMecabTokenizerAndCheckRuntimeService,
createSubtitleTimingTrackerRuntimeService,
} from "./core/services/startup-resource-runtime-service";
import { runGenerateConfigFlowRuntimeService } from "./core/services/config-generation-runtime-service";
import {
runSubsyncManualFromIpcRuntimeService,
triggerSubsyncFromConfigRuntimeService,
@@ -455,22 +456,26 @@ const backendOverride = initialArgs.backend ?? null;
const autoStartOverlay = initialArgs.autoStartOverlay;
const texthookerOnlyMode = initialArgs.texthooker;
if (initialArgs.generateConfig && !shouldStartApp(initialArgs)) {
generateDefaultConfigFile(initialArgs, {
configDir: CONFIG_DIR,
defaultConfig: DEFAULT_CONFIG,
generateTemplate: (config) => generateConfigTemplate(config as never),
})
.then((exitCode) => {
if (
!runGenerateConfigFlowRuntimeService(initialArgs, {
shouldStartApp: (args) => shouldStartApp(args),
generateConfig: async (args) =>
generateDefaultConfigFile(args, {
configDir: CONFIG_DIR,
defaultConfig: DEFAULT_CONFIG,
generateTemplate: (config) => generateConfigTemplate(config as never),
}),
onSuccess: (exitCode) => {
process.exitCode = exitCode;
app.quit();
})
.catch((error: Error) => {
},
onError: (error) => {
console.error(`Failed to generate config: ${error.message}`);
process.exitCode = 1;
app.quit();
});
} else {
},
})
) {
startAppLifecycleService(initialArgs, createAppLifecycleDepsRuntimeService({
app,
platform: process.platform,