refactor: extract CLI argument parsing into shared utility

This commit is contained in:
weishu
2025-12-26 20:45:37 +08:00
parent 5d79a3f1ef
commit b497abda98
3 changed files with 82 additions and 16 deletions
+2 -1
View File
@@ -9,6 +9,7 @@ import { existsSync, mkdirSync } from 'node:fs'
import { homedir } from 'node:os'
import { join } from 'node:path'
import packageJson from '../package.json'
import { getCliArgs } from '@/utils/cliArgs'
class Configuration {
public readonly serverUrl: string
@@ -32,7 +33,7 @@ class Configuration {
this._cliApiToken = process.env.CLI_API_TOKEN || ''
// Check if we're running as daemon based on process args
const args = process.argv.slice(2)
const args = getCliArgs()
this.isDaemonProcess = args.length >= 2 && args[0] === 'daemon' && (args[1] === 'start-sync')
// Directory configuration - Priority: HAPI_HOME env > default home dir
+2 -15
View File
@@ -30,24 +30,11 @@ import { initializeToken } from './ui/tokenInit'
import { ensureRuntimeAssets } from './runtime/assets'
import { runHappyMcpStdioBridge } from './codex/happyMcpStdioBridge'
import { withBunRuntimeEnv } from './utils/bunRuntime'
import { getCliArgs } from './utils/cliArgs'
(async () => {
const args = (() => {
if (!isBunCompiled()) {
return process.argv.slice(2)
}
const arg1 = process.argv[1] || ''
if (arg1 === process.execPath) {
return process.argv.slice(2)
}
if (arg1.endsWith('.js') || arg1.endsWith('.mjs') || arg1.endsWith('.ts')) {
return process.argv.slice(2)
}
return process.argv.slice(1)
})()
const args = getCliArgs()
if (args.includes('-v') || args.includes('--version')) {
console.log(`hapi version: ${packageJson.version}`)
+78
View File
@@ -0,0 +1,78 @@
import { basename } from 'node:path';
function resolveRawArgv(): string[] {
const bunArgv = globalThis.Bun?.argv;
if (Array.isArray(bunArgv) && bunArgv.length > 0) {
return bunArgv;
}
return process.argv;
}
function isEntrypointPath(value: string, bunMain: string): boolean {
if (!value) {
return false;
}
if (value === bunMain) {
return true;
}
return /\.(c|m)?(ts|js)$/.test(value);
}
function hasRuntimeWrapper(preArgs: string[], execPath: string, execBase: string, bunMain: string): boolean {
if (preArgs.length === 0) {
return false;
}
if (preArgs[0] === 'bun') {
return true;
}
if (preArgs.length < 2) {
return false;
}
if (preArgs[0] !== execPath && preArgs[0] !== execBase) {
return false;
}
return isEntrypointPath(preArgs[1], bunMain);
}
export function normalizeCliArgs(rawArgv: string[]): string[] {
if (!Array.isArray(rawArgv) || rawArgv.length === 0) {
return [];
}
const execPath = process.execPath;
const execBase = basename(execPath);
const bunMain = globalThis.Bun?.main ?? '';
const dashIndex = rawArgv.indexOf('--');
let argv = rawArgv.slice();
if (dashIndex >= 0) {
const preArgs = rawArgv.slice(0, dashIndex);
const postArgs = rawArgv.slice(dashIndex + 1);
argv = hasRuntimeWrapper(preArgs, execPath, execBase, bunMain)
? postArgs
: [...preArgs, ...postArgs];
}
let startIndex = 0;
while (startIndex < argv.length) {
const value = argv[startIndex] || '';
const nextValue = argv[startIndex + 1] || '';
if (
value === 'bun' &&
(nextValue === bunMain || nextValue === execPath || nextValue === execBase || isEntrypointPath(nextValue, bunMain))
) {
startIndex += 2;
continue;
}
if (value === execPath || value === execBase || isEntrypointPath(value, bunMain)) {
startIndex += 1;
continue;
}
break;
}
return argv.slice(startIndex);
}
export function getCliArgs(): string[] {
return normalizeCliArgs(resolveRawArgv());
}