const path = require('path'); const { randomUUID } = require('crypto'); const { snapshotsSystemDir, snapshotsTenantsDir } = require('./paths'); const { readJsonIfExists, writeJson } = require('./fs'); const { listAllResources } = require('./resources'); function buildResourceDiff(resource) { return { in_sync: JSON.stringify(resource.desired_state || {}) === JSON.stringify(resource.current_state || {}), desired_state: resource.desired_state || {}, current_state: resource.current_state || {}, }; } function filterTenantResources(resources, tenantId) { const filtered = {}; for (const [resourceType, items] of Object.entries(resources)) { filtered[resourceType] = items.filter((item) => { if (!item) { return false; } if (resourceType === 'tenant') { return item.id === tenantId; } return item.desired_state && item.desired_state.tenant_id === tenantId; }); } return filtered; } async function createSnapshot(scope, context) { const resources = await listAllResources(); const selected = scope === 'system' ? resources : filterTenantResources(resources, scope.replace('tenant:', '')); const snapshot = { snapshot_id: randomUUID(), schema_version: 'v1', scope, created_at: new Date().toISOString(), request_id: context.request_id, correlation_id: context.correlation_id, resources: selected, diffs: Object.fromEntries( Object.entries(selected).map(([resourceType, items]) => [ resourceType, items.map((item) => ({ resource_id: item.id, diff: buildResourceDiff(item), })), ]) ), }; const filePath = scope === 'system' ? path.join(snapshotsSystemDir, 'latest.json') : path.join(snapshotsTenantsDir, `${scope.replace('tenant:', '')}.json`); await writeJson(filePath, snapshot); return snapshot; } async function getLatestSystemSnapshot() { return readJsonIfExists(path.join(snapshotsSystemDir, 'latest.json')); } async function getLatestTenantSnapshot(tenantId) { return readJsonIfExists(path.join(snapshotsTenantsDir, `${tenantId}.json`)); } module.exports = { createSnapshot, getLatestSystemSnapshot, getLatestTenantSnapshot, };