- Add TIP Proxy Network (packages/proxy-agent): SOCKS5 proxy agent for residential IP bypass of CloudFront WAF blocks - Add /api/proxy/* routes: node registration, heartbeat, load balancing - Add image extraction to Flexoptix catalog scraper (GraphQL small_image) - Add image extraction to Optcore scraper (Playwright gallery img) - Fix Fluxlight price scraping (BigCommerce HTML structure: data-product-price-without-tax) - Add SmartOptics scraper (8 DWDM/coherent products, og:image extraction) - Fix findOrCreateScrapedTransceiver to update image_url for existing records - Add image backfill script (backfill-images.ts): 178 Flexoptix images added - Fix DB connection pool: max 5, idleTimeoutMillis 10s (was unlimited, caused >100 connections) - Add proxy.ts utility for scraper proxy rotation
77 lines
1.9 KiB
TypeScript
77 lines
1.9 KiB
TypeScript
/**
|
|
* Config management — persists agent config to ~/.tip-agent/config.json
|
|
*/
|
|
import * as fs from "fs";
|
|
import * as path from "path";
|
|
import * as os from "os";
|
|
|
|
const CONFIG_DIR = path.join(os.homedir(), ".tip-agent");
|
|
const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
|
|
export interface AgentConfig {
|
|
token: string;
|
|
port: number;
|
|
maxGb: number;
|
|
name: string;
|
|
serverUrl: string;
|
|
pid?: number;
|
|
startedAt?: string;
|
|
}
|
|
|
|
const DEFAULTS: Partial<AgentConfig> = {
|
|
port: 1080,
|
|
maxGb: 10,
|
|
name: os.hostname(),
|
|
serverUrl: "https://transceiver-db.context-x.org",
|
|
};
|
|
|
|
export function loadConfig(): AgentConfig | null {
|
|
if (!fs.existsSync(CONFIG_FILE)) return null;
|
|
try {
|
|
const raw = fs.readFileSync(CONFIG_FILE, "utf8");
|
|
return JSON.parse(raw) as AgentConfig;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function saveConfig(cfg: Partial<AgentConfig>): AgentConfig {
|
|
if (!fs.existsSync(CONFIG_DIR)) {
|
|
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
}
|
|
const existing = loadConfig() ?? {};
|
|
const merged = { ...DEFAULTS, ...existing, ...cfg } as AgentConfig;
|
|
fs.writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2), "utf8");
|
|
return merged;
|
|
}
|
|
|
|
export function clearConfig(): void {
|
|
if (fs.existsSync(CONFIG_FILE)) {
|
|
fs.unlinkSync(CONFIG_FILE);
|
|
}
|
|
}
|
|
|
|
export function getPidFile(): string {
|
|
return path.join(CONFIG_DIR, "agent.pid");
|
|
}
|
|
|
|
export function savePid(pid: number): void {
|
|
if (!fs.existsSync(CONFIG_DIR)) {
|
|
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
}
|
|
fs.writeFileSync(getPidFile(), String(pid), "utf8");
|
|
}
|
|
|
|
export function loadPid(): number | null {
|
|
const pidFile = getPidFile();
|
|
if (!fs.existsSync(pidFile)) return null;
|
|
const raw = fs.readFileSync(pidFile, "utf8").trim();
|
|
const pid = parseInt(raw, 10);
|
|
return isNaN(pid) ? null : pid;
|
|
}
|
|
|
|
export function clearPid(): void {
|
|
const pidFile = getPidFile();
|
|
if (fs.existsSync(pidFile)) fs.unlinkSync(pidFile);
|
|
}
|