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
68 lines
1.9 KiB
TypeScript
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 };
|
|
}
|