Files
AetherForge/server/web/src/help/buildManager.ts
drjones df81eb7744 Add fleet ops dashboard, Calibrate enforcement, and dead-code cleanup.
Ship live alerts, pool status, AI monitor, remote agent commands, build manager, and uninstall flow; wire Calibrate settings (WS ping, pool traffic log, retention limits) at runtime and exclude server/data from git.
2026-05-27 09:16:04 -07:00

50 lines
1.5 KiB
TypeScript

/** Shallow diff between two plain objects for blueprint comparison. */
export function blueprintDiff(
base: Record<string, unknown>,
current: Record<string, unknown>
): { key: string; kind: 'added' | 'removed' | 'changed'; from?: unknown; to?: unknown }[] {
const keys = new Set([...Object.keys(base), ...Object.keys(current)]);
const out: { key: string; kind: 'added' | 'removed' | 'changed'; from?: unknown; to?: unknown }[] = [];
for (const key of keys) {
const a = base[key];
const b = current[key];
const hasA = key in base;
const hasB = key in current;
if (!hasA && hasB) {
out.push({ key, kind: 'added', to: b });
} else if (hasA && !hasB) {
out.push({ key, kind: 'removed', from: a });
} else if (JSON.stringify(a) !== JSON.stringify(b)) {
out.push({ key, kind: 'changed', from: a, to: b });
}
}
return out.sort((x, y) => x.key.localeCompare(y.key));
}
/** Build partial forge request from a stored build record. */
export function buildRequestFromRecord(
record: {
worker_name: string;
server_url: string;
wallet: string;
threads: number;
pool_host: string;
pool_port: number;
pool_tls: boolean;
pool_pass: string;
},
defaults: Record<string, unknown>
): Record<string, unknown> {
return {
...defaults,
worker_name: record.worker_name,
server_url: record.server_url,
wallet: record.wallet,
threads: record.threads,
pool_host: record.pool_host,
pool_port: record.pool_port,
pool_tls: record.pool_tls,
pool_pass: record.pool_pass,
};
}