albion/agent/src/config.ts
Заид Омар Медхат 337dac78ba
All checks were successful
Deploy / deploy (push) Successful in 3m58s
Client/server split, Postgres, auth, Windows agent, Docker deploy
- Extract world-parse + packet capture into @albion/shared (reused by
  server and a new standalone agent workspace).
- Migrate the data layer from SQLite/better-sqlite3 to shared Postgres
  (async pg with a ?->$n helper; economy engine preloads the item/recipe
  graph so its sync recursion still works).
- API-key auth (ALBION_API_KEY) on all /api routes except health; web UI
  sends it via a fetch wrapper + key-entry gate; server serves the built
  UI with a path-traversal-safe static handler (drops @fastify/static).
- Windows companion agent: pushes world map + captured market orders to
  /api/ingest/*; runs on the gaming PC where the game traffic lives.
- Docker + docker-compose (external proxy + backend networks for Nginx
  Proxy Manager and shared Postgres) and a Forgejo deploy workflow.
- Validated end-to-end against Postgres 16 and a full compose run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 04:10:08 +05:00

54 lines
1.8 KiB
TypeScript

import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
/**
* Agent config, resolved from (in order): env vars, a config file, defaults.
* Config file lives at %APPDATA%\albion-agent\config.json (or ALBION_AGENT_CONFIG).
*/
export interface AgentConfig {
serverUrl: string; // e.g. https://albion.example.com
apiKey: string;
gamePath: string; // folder containing the "game" directory, e.g. E:\albion
interfaces: string[]; // tshark interface ids; empty = all
orderFlushSeconds: number;
}
const DEFAULTS: AgentConfig = {
serverUrl: 'http://127.0.0.1:4310',
apiKey: '',
gamePath: 'E:\\albion',
interfaces: [],
orderFlushSeconds: 15,
};
export function configPath(): string {
if (process.env.ALBION_AGENT_CONFIG) return process.env.ALBION_AGENT_CONFIG;
const base = process.env.APPDATA ?? path.join(os.homedir(), '.config');
return path.join(base, 'albion-agent', 'config.json');
}
export function loadConfig(): AgentConfig {
let fileCfg: Partial<AgentConfig> = {};
const p = configPath();
if (fs.existsSync(p)) {
try {
fileCfg = JSON.parse(fs.readFileSync(p, 'utf8'));
} catch {
console.warn(`Could not parse ${p}, ignoring.`);
}
}
return {
serverUrl: process.env.ALBION_SERVER_URL ?? fileCfg.serverUrl ?? DEFAULTS.serverUrl,
apiKey: process.env.ALBION_API_KEY ?? fileCfg.apiKey ?? DEFAULTS.apiKey,
gamePath: process.env.ALBION_GAME_PATH ?? fileCfg.gamePath ?? DEFAULTS.gamePath,
interfaces: fileCfg.interfaces ?? DEFAULTS.interfaces,
orderFlushSeconds: fileCfg.orderFlushSeconds ?? DEFAULTS.orderFlushSeconds,
};
}
export function saveConfig(cfg: AgentConfig): void {
const p = configPath();
fs.mkdirSync(path.dirname(p), { recursive: true });
fs.writeFileSync(p, JSON.stringify(cfg, null, 2));
}