mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-02 18:22:42 -08:00
fix: suppress startup warnings for help output
This commit is contained in:
111
src/core/services/app-lifecycle.test.ts
Normal file
111
src/core/services/app-lifecycle.test.ts
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import test from 'node:test';
|
||||||
|
import { CliArgs } from '../../cli/args';
|
||||||
|
import { AppLifecycleServiceDeps, startAppLifecycle } from './app-lifecycle';
|
||||||
|
|
||||||
|
function makeArgs(overrides: Partial<CliArgs> = {}): CliArgs {
|
||||||
|
return {
|
||||||
|
background: false,
|
||||||
|
start: false,
|
||||||
|
stop: false,
|
||||||
|
toggle: false,
|
||||||
|
toggleVisibleOverlay: false,
|
||||||
|
settings: false,
|
||||||
|
show: false,
|
||||||
|
hide: false,
|
||||||
|
showVisibleOverlay: false,
|
||||||
|
hideVisibleOverlay: false,
|
||||||
|
copySubtitle: false,
|
||||||
|
copySubtitleMultiple: false,
|
||||||
|
mineSentence: false,
|
||||||
|
mineSentenceMultiple: false,
|
||||||
|
updateLastCardFromClipboard: false,
|
||||||
|
refreshKnownWords: false,
|
||||||
|
toggleSecondarySub: false,
|
||||||
|
triggerFieldGrouping: false,
|
||||||
|
triggerSubsync: false,
|
||||||
|
markAudioCard: false,
|
||||||
|
openRuntimeOptions: false,
|
||||||
|
anilistStatus: false,
|
||||||
|
anilistLogout: false,
|
||||||
|
anilistSetup: false,
|
||||||
|
anilistRetryQueue: false,
|
||||||
|
jellyfin: false,
|
||||||
|
jellyfinLogin: false,
|
||||||
|
jellyfinLogout: false,
|
||||||
|
jellyfinLibraries: false,
|
||||||
|
jellyfinItems: false,
|
||||||
|
jellyfinSubtitles: false,
|
||||||
|
jellyfinSubtitleUrlsOnly: false,
|
||||||
|
jellyfinPlay: false,
|
||||||
|
jellyfinRemoteAnnounce: false,
|
||||||
|
jellyfinPreviewAuth: false,
|
||||||
|
texthooker: false,
|
||||||
|
help: false,
|
||||||
|
autoStartOverlay: false,
|
||||||
|
generateConfig: false,
|
||||||
|
backupOverwrite: false,
|
||||||
|
debug: false,
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDeps(overrides: Partial<AppLifecycleServiceDeps> = {}) {
|
||||||
|
const calls: string[] = [];
|
||||||
|
let lockCalls = 0;
|
||||||
|
|
||||||
|
const deps: AppLifecycleServiceDeps = {
|
||||||
|
shouldStartApp: () => false,
|
||||||
|
parseArgs: () => makeArgs(),
|
||||||
|
requestSingleInstanceLock: () => {
|
||||||
|
lockCalls += 1;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
quitApp: () => {
|
||||||
|
calls.push('quitApp');
|
||||||
|
},
|
||||||
|
onSecondInstance: () => {},
|
||||||
|
handleCliCommand: () => {},
|
||||||
|
printHelp: () => {
|
||||||
|
calls.push('printHelp');
|
||||||
|
},
|
||||||
|
logNoRunningInstance: () => {
|
||||||
|
calls.push('logNoRunningInstance');
|
||||||
|
},
|
||||||
|
whenReady: () => {},
|
||||||
|
onWindowAllClosed: () => {},
|
||||||
|
onWillQuit: () => {},
|
||||||
|
onActivate: () => {},
|
||||||
|
isDarwinPlatform: () => false,
|
||||||
|
onReady: async () => {},
|
||||||
|
onWillQuitCleanup: () => {},
|
||||||
|
shouldRestoreWindowsOnActivate: () => false,
|
||||||
|
restoreWindowsOnActivate: () => {},
|
||||||
|
shouldQuitOnWindowAllClosed: () => true,
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
|
||||||
|
return { deps, calls, getLockCalls: () => lockCalls };
|
||||||
|
}
|
||||||
|
|
||||||
|
test('startAppLifecycle handles --help without acquiring single-instance lock', () => {
|
||||||
|
const { deps, calls, getLockCalls } = createDeps({
|
||||||
|
shouldStartApp: () => false,
|
||||||
|
});
|
||||||
|
|
||||||
|
startAppLifecycle(makeArgs({ help: true }), deps);
|
||||||
|
|
||||||
|
assert.equal(getLockCalls(), 0);
|
||||||
|
assert.deepEqual(calls, ['printHelp', 'quitApp']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('startAppLifecycle still acquires lock for startup commands', () => {
|
||||||
|
const { deps, getLockCalls } = createDeps({
|
||||||
|
shouldStartApp: () => true,
|
||||||
|
whenReady: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
startAppLifecycle(makeArgs({ start: true }), deps);
|
||||||
|
|
||||||
|
assert.equal(getLockCalls(), 1);
|
||||||
|
});
|
||||||
@@ -87,6 +87,12 @@ export function createAppLifecycleDepsRuntime(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function startAppLifecycle(initialArgs: CliArgs, deps: AppLifecycleServiceDeps): void {
|
export function startAppLifecycle(initialArgs: CliArgs, deps: AppLifecycleServiceDeps): void {
|
||||||
|
if (initialArgs.help && !deps.shouldStartApp(initialArgs)) {
|
||||||
|
deps.printHelp();
|
||||||
|
deps.quitApp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const gotTheLock = deps.requestSingleInstanceLock();
|
const gotTheLock = deps.requestSingleInstanceLock();
|
||||||
if (!gotTheLock) {
|
if (!gotTheLock) {
|
||||||
deps.quitApp();
|
deps.quitApp();
|
||||||
@@ -101,12 +107,6 @@ export function startAppLifecycle(initialArgs: CliArgs, deps: AppLifecycleServic
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (initialArgs.help && !deps.shouldStartApp(initialArgs)) {
|
|
||||||
deps.printHelp();
|
|
||||||
deps.quitApp();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!deps.shouldStartApp(initialArgs)) {
|
if (!deps.shouldStartApp(initialArgs)) {
|
||||||
if (initialArgs.stop && !initialArgs.start) {
|
if (initialArgs.stop && !initialArgs.start) {
|
||||||
deps.quitApp();
|
deps.quitApp();
|
||||||
|
|||||||
39
src/main-entry-runtime.test.ts
Normal file
39
src/main-entry-runtime.test.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import test from 'node:test';
|
||||||
|
import {
|
||||||
|
sanitizeHelpEnv,
|
||||||
|
sanitizeBackgroundEnv,
|
||||||
|
shouldDetachBackgroundLaunch,
|
||||||
|
shouldHandleHelpOnlyAtEntry,
|
||||||
|
} from './main-entry-runtime';
|
||||||
|
|
||||||
|
test('shouldHandleHelpOnlyAtEntry detects help-only invocation', () => {
|
||||||
|
assert.equal(shouldHandleHelpOnlyAtEntry(['--help'], {}), true);
|
||||||
|
assert.equal(shouldHandleHelpOnlyAtEntry(['--help', '--start'], {}), false);
|
||||||
|
assert.equal(shouldHandleHelpOnlyAtEntry(['--start'], {}), false);
|
||||||
|
assert.equal(shouldHandleHelpOnlyAtEntry(['--help'], { ELECTRON_RUN_AS_NODE: '1' }), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sanitizeHelpEnv suppresses warnings and lsfg layer', () => {
|
||||||
|
const env = sanitizeHelpEnv({
|
||||||
|
VK_INSTANCE_LAYERS: 'foo:lsfg-vk:bar',
|
||||||
|
});
|
||||||
|
assert.equal(env.NODE_NO_WARNINGS, '1');
|
||||||
|
assert.equal('VK_INSTANCE_LAYERS' in env, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sanitizeBackgroundEnv marks background child and keeps warning suppression', () => {
|
||||||
|
const env = sanitizeBackgroundEnv({
|
||||||
|
VK_INSTANCE_LAYERS: 'foo:lsfg-vk:bar',
|
||||||
|
});
|
||||||
|
assert.equal(env.SUBMINER_BACKGROUND_CHILD, '1');
|
||||||
|
assert.equal(env.NODE_NO_WARNINGS, '1');
|
||||||
|
assert.equal('VK_INSTANCE_LAYERS' in env, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('shouldDetachBackgroundLaunch only for first background invocation', () => {
|
||||||
|
assert.equal(shouldDetachBackgroundLaunch(['--background'], {}), true);
|
||||||
|
assert.equal(shouldDetachBackgroundLaunch(['--background'], { SUBMINER_BACKGROUND_CHILD: '1' }), false);
|
||||||
|
assert.equal(shouldDetachBackgroundLaunch(['--background'], { ELECTRON_RUN_AS_NODE: '1' }), false);
|
||||||
|
assert.equal(shouldDetachBackgroundLaunch(['--start'], {}), false);
|
||||||
|
});
|
||||||
42
src/main-entry-runtime.ts
Normal file
42
src/main-entry-runtime.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { CliArgs, parseArgs, shouldStartApp } from './cli/args';
|
||||||
|
|
||||||
|
const BACKGROUND_ARG = '--background';
|
||||||
|
const BACKGROUND_CHILD_ENV = 'SUBMINER_BACKGROUND_CHILD';
|
||||||
|
|
||||||
|
function removeLsfgLayer(env: NodeJS.ProcessEnv): void {
|
||||||
|
if (typeof env.VK_INSTANCE_LAYERS === 'string' && /lsfg/i.test(env.VK_INSTANCE_LAYERS)) {
|
||||||
|
delete env.VK_INSTANCE_LAYERS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseCliArgs(argv: string[]): CliArgs {
|
||||||
|
return parseArgs(argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function shouldDetachBackgroundLaunch(argv: string[], env: NodeJS.ProcessEnv): boolean {
|
||||||
|
if (env.ELECTRON_RUN_AS_NODE === '1') return false;
|
||||||
|
if (!argv.includes(BACKGROUND_ARG)) return false;
|
||||||
|
if (env[BACKGROUND_CHILD_ENV] === '1') return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function shouldHandleHelpOnlyAtEntry(argv: string[], env: NodeJS.ProcessEnv): boolean {
|
||||||
|
if (env.ELECTRON_RUN_AS_NODE === '1') return false;
|
||||||
|
const args = parseCliArgs(argv);
|
||||||
|
return args.help && !shouldStartApp(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sanitizeHelpEnv(baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
||||||
|
const env = { ...baseEnv };
|
||||||
|
if (!env.NODE_NO_WARNINGS) {
|
||||||
|
env.NODE_NO_WARNINGS = '1';
|
||||||
|
}
|
||||||
|
removeLsfgLayer(env);
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sanitizeBackgroundEnv(baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
||||||
|
const env = sanitizeHelpEnv(baseEnv);
|
||||||
|
env[BACKGROUND_CHILD_ENV] = '1';
|
||||||
|
return env;
|
||||||
|
}
|
||||||
@@ -1,26 +1,13 @@
|
|||||||
import { spawn } from 'node:child_process';
|
import { spawn } from 'node:child_process';
|
||||||
|
import { printHelp } from './cli/help';
|
||||||
|
import {
|
||||||
|
sanitizeBackgroundEnv,
|
||||||
|
sanitizeHelpEnv,
|
||||||
|
shouldDetachBackgroundLaunch,
|
||||||
|
shouldHandleHelpOnlyAtEntry,
|
||||||
|
} from './main-entry-runtime';
|
||||||
|
|
||||||
const BACKGROUND_ARG = '--background';
|
const DEFAULT_TEXTHOOKER_PORT = 5174;
|
||||||
const BACKGROUND_CHILD_ENV = 'SUBMINER_BACKGROUND_CHILD';
|
|
||||||
|
|
||||||
function shouldDetachBackgroundLaunch(argv: string[], env: NodeJS.ProcessEnv): boolean {
|
|
||||||
if (env.ELECTRON_RUN_AS_NODE === '1') return false;
|
|
||||||
if (!argv.includes(BACKGROUND_ARG)) return false;
|
|
||||||
if (env[BACKGROUND_CHILD_ENV] === '1') return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sanitizeBackgroundEnv(baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
||||||
const env = { ...baseEnv };
|
|
||||||
env[BACKGROUND_CHILD_ENV] = '1';
|
|
||||||
if (!env.NODE_NO_WARNINGS) {
|
|
||||||
env.NODE_NO_WARNINGS = '1';
|
|
||||||
}
|
|
||||||
if (typeof env.VK_INSTANCE_LAYERS === 'string' && /lsfg/i.test(env.VK_INSTANCE_LAYERS)) {
|
|
||||||
delete env.VK_INSTANCE_LAYERS;
|
|
||||||
}
|
|
||||||
return env;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldDetachBackgroundLaunch(process.argv, process.env)) {
|
if (shouldDetachBackgroundLaunch(process.argv, process.env)) {
|
||||||
const child = spawn(process.execPath, process.argv.slice(1), {
|
const child = spawn(process.execPath, process.argv.slice(1), {
|
||||||
@@ -32,4 +19,14 @@ if (shouldDetachBackgroundLaunch(process.argv, process.env)) {
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shouldHandleHelpOnlyAtEntry(process.argv, process.env)) {
|
||||||
|
const sanitizedEnv = sanitizeHelpEnv(process.env);
|
||||||
|
process.env.NODE_NO_WARNINGS = sanitizedEnv.NODE_NO_WARNINGS;
|
||||||
|
if (!sanitizedEnv.VK_INSTANCE_LAYERS) {
|
||||||
|
delete process.env.VK_INSTANCE_LAYERS;
|
||||||
|
}
|
||||||
|
printHelp(DEFAULT_TEXTHOOKER_PORT);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
require('./main.js');
|
require('./main.js');
|
||||||
|
|||||||
Reference in New Issue
Block a user