Files
Lukas May 34578d39c6 refactor: Restructure monorepo to apps/server/ and apps/web/ layout
Move src/ → apps/server/ and packages/web/ → apps/web/ to adopt
standard monorepo conventions (apps/ for runnable apps, packages/
for reusable libraries). Update all config files, shared package
imports, test fixtures, and documentation to reflect new paths.

Key fixes:
- Update workspace config to ["apps/*", "packages/*"]
- Update tsconfig.json rootDir/include for apps/server/
- Add apps/web/** to vitest exclude list
- Update drizzle.config.ts schema path
- Fix ensure-schema.ts migration path detection (3 levels up in dev,
  2 levels up in dist)
- Fix tests/integration/cli-server.test.ts import paths
- Update packages/shared imports to apps/server/ paths
- Update all docs/ files with new paths
2026-03-03 11:22:53 +01:00

68 lines
1.9 KiB
TypeScript

import { existsSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import { homedir, platform } from 'node:os';
import { execa } from 'execa';
export interface ExtractedAccount {
email: string;
accountUuid: string;
configJson: object;
credentials: string;
}
/**
* Resolve the Claude Code config path with fallback logic.
* Primary: ~/.claude/.claude.json (if it exists and has oauthAccount)
* Fallback: ~/.claude.json
*/
function getClaudeConfigPath(): string {
const home = homedir();
const primary = join(home, '.claude', '.claude.json');
const fallback = join(home, '.claude.json');
if (existsSync(primary)) {
try {
const json = JSON.parse(readFileSync(primary, 'utf-8'));
if (json.oauthAccount) return primary;
} catch {
// invalid JSON, fall through
}
}
return fallback;
}
export async function extractCurrentClaudeAccount(): Promise<ExtractedAccount> {
const home = homedir();
// 1. Read Claude config (with fallback logic matching ccswitch)
const configPath = getClaudeConfigPath();
const configRaw = readFileSync(configPath, 'utf-8');
const configJson = JSON.parse(configRaw);
const email = configJson.oauthAccount?.emailAddress;
const accountUuid = configJson.oauthAccount?.accountUuid;
if (!email || !accountUuid) {
throw new Error('No Claude account found. Please log in with `claude` first.');
}
// 2. Read credentials (platform-specific)
let credentials: string;
if (platform() === 'darwin') {
// macOS: read from Keychain
const { stdout } = await execa('security', [
'find-generic-password',
'-s', 'Claude Code-credentials',
'-w',
]);
credentials = stdout;
} else {
// Linux: read from file
const credPath = join(home, '.claude', '.credentials.json');
credentials = readFileSync(credPath, 'utf-8');
}
return { email, accountUuid, configJson, credentials };
}