import { resolve } from 'node:path'; import type { CliContext } from './types.js'; export type { CliContext } from './types.js'; import { existsSync, readFileSync } from 'node:fs'; function detectPackageManager(cwd: string): CliContext['packageManager'] { // Check for lock files in cwd if (existsSync(resolve(cwd, 'bun.lockb')) || existsSync(resolve(cwd, 'bun.lock'))) { return 'bun'; } if (existsSync(resolve(cwd, 'pnpm-lock.yaml'))) { return 'pnpm'; } if (existsSync(resolve(cwd, 'yarn.lock'))) { return 'yarn'; } if (existsSync(resolve(cwd, 'package-lock.json'))) { return 'npm'; } // Check package.json packageManager field const packageJsonPath = resolve(cwd, 'package.json'); if (existsSync(packageJsonPath)) { try { const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as { packageManager?: string }; const packageManager = packageJson.packageManager || ''; if (packageManager.startsWith('bun@')) return 'bun'; if (packageManager.startsWith('pnpm@')) return 'pnpm'; if (packageManager.startsWith('yarn@')) return 'yarn'; if (packageManager.startsWith('npm@')) return 'npm'; } catch { // Ignore parse errors } } // Check environment variables if (process.env.npm_config_user_agent) { const ua = process.env.npm_config_user_agent; if (ua.includes('bun')) return 'bun'; if (ua.includes('pnpm')) return 'pnpm'; if (ua.includes('yarn')) return 'yarn'; if (ua.includes('npm')) return 'npm'; } return 'unknown'; } function detectCI(): boolean { const ciEnvVars = [ 'CI', 'GITHUB_ACTIONS', 'GITLAB_CI', 'CIRCLECI', 'TRAVIS', 'APPVEYOR', 'BUILDKITE', 'DRONE', 'JENKINS_URL', 'TF_BUILD', 'CODEBUILD_BUILD_ID', 'TEAMCITY_VERSION', 'SEMAPHORE', 'WERCKER', 'MAGNUM', 'SNAP_CI', 'BUDDY', 'BUILDBOX', 'AGOLA', 'WOODPECKER', ]; return ciEnvVars.some(varName => process.env[varName] !== undefined); } export function createContext(options: Record = {}): CliContext { // Detect cwd (respect --cwd override) const cwd = typeof options.cwd === 'string' ? resolve(options.cwd) : process.cwd(); // Detect environment const nodeEnv = process.env.NODE_ENV; const apophisEnv = process.env.APOPHIS_ENV; // Detect TTY const isTTY = process.stdout.isTTY === true; // Detect CI const isCI = detectCI(); // Package manager detection const packageManager = detectPackageManager(cwd); // Normalize options const format = options.format === 'json' || options.format === 'ndjson' ? options.format : 'human'; const color = options.color === 'always' || options.color === 'never' ? options.color : 'auto'; return { cwd, env: { nodeEnv, apophisEnv, }, isTTY, isCI, nodeVersion: process.version, packageManager, selfPath: process.argv[1], options: { config: typeof options.config === 'string' ? options.config : undefined, profile: typeof options.profile === 'string' ? options.profile : undefined, format, color, quiet: options.quiet === true, verbose: options.verbose === true, artifactDir: typeof options.artifactDir === 'string' ? options.artifactDir : undefined, }, }; }