Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | 2x 2x 2x 2x 2x 2x 2x 6x 2x 10x 10x 6x 4x 4x 4x 4x 4x 6x 2x 8x 8x 1x 8x 8x 8x 8x 8x 8x 7x 2x 4x 4x 1x 3x 3x 3x | // Copyright 2026 ForgeKit Contributors
// SPDX-License-Identifier: Apache-2.0
// https://github.com/SubhanshuMG/ForgeKit
import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
import * as crypto from 'crypto';
export interface ForgeKitConfig {
telemetry: boolean;
userId: string;
firstRun: boolean;
ai?: {
provider: 'openai' | 'anthropic';
model?: string;
};
plugins?: string[];
envSync?: {
defaultEnvironment?: string;
};
}
const CONFIG_DIR = path.join(os.homedir(), '.forgekit');
const CONFIG_PATH = path.join(CONFIG_DIR, 'config.json');
export { CONFIG_DIR };
function defaultConfig(): ForgeKitConfig {
return {
telemetry: false,
userId: '',
firstRun: true,
};
}
export function loadConfig(): ForgeKitConfig {
try {
const raw = fs.readFileSync(CONFIG_PATH, 'utf-8');
const parsed = JSON.parse(raw);
const config: ForgeKitConfig = {
telemetry: typeof parsed.telemetry === 'boolean' ? parsed.telemetry : false,
userId: typeof parsed.userId === 'string' ? parsed.userId : '',
firstRun: typeof parsed.firstRun === 'boolean' ? parsed.firstRun : true,
};
// Preserve optional fields if present
Iif (parsed.ai && typeof parsed.ai === 'object') {
config.ai = parsed.ai;
}
Iif (Array.isArray(parsed.plugins)) {
config.plugins = parsed.plugins;
}
Iif (parsed.envSync && typeof parsed.envSync === 'object') {
config.envSync = parsed.envSync;
}
return config;
} catch {
return defaultConfig();
}
}
export function saveConfig(config: ForgeKitConfig): void {
try {
if (!fs.existsSync(CONFIG_DIR)) {
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
}
// Merge with existing config to preserve unknown fields
let existing: Record<string, unknown> = {};
try {
existing = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'));
} catch {
// No existing config
}
const merged = { ...existing, ...config };
const tmpPath = CONFIG_PATH + '.tmp';
fs.writeFileSync(tmpPath, JSON.stringify(merged, null, 2), { encoding: 'utf-8', mode: 0o600 });
fs.renameSync(tmpPath, CONFIG_PATH);
} catch {
// Never throw from config writes
}
}
export function getUserId(): string {
const config = loadConfig();
if (config.userId) {
return config.userId;
}
const userId = crypto.randomUUID();
saveConfig({ ...config, userId });
return userId;
}
|