Files
prowler/ui/actions/attack-paths/scans.adapter.ts
Alejandro Bailo 50556df713 feat(ui): add findings grouped view (#10425)
Co-authored-by: Adrián Jesús Peña Rodríguez <adrianjpr@gmail.com>
Co-authored-by: Alan Buscaglia <gentlemanprogramming@gmail.com>
2026-03-30 14:17:36 +02:00

79 lines
2.4 KiB
TypeScript

import { formatDuration } from "@/lib/date-utils";
import { MetaDataProps } from "@/types";
import { AttackPathScan, AttackPathScansResponse } from "@/types/attack-paths";
/**
* Adapts raw scan API responses to enriched domain models
* - Transforms raw scan data with computed properties
* - Co-locates related data for better performance
* - Preserves pagination metadata for list operations
*
* Uses plugin architecture for extensibility:
* - Handles scan-specific response transformation
* - Can be composed with backend service plugins
* - Maintains separation of concerns between API layer and business logic
*/
/**
* Adapt attack path scans response with enriched data
*
* @param response - Raw API response from attack-paths-scans endpoint
* @returns Enriched scans data with metadata and computed properties
*/
export function adaptAttackPathScansResponse(
response: AttackPathScansResponse | undefined,
): {
data: AttackPathScan[];
metadata?: MetaDataProps;
} {
if (!response?.data) {
return { data: [] };
}
// Enrich scan data with computed properties
const enrichedData = response.data.map((scan) => ({
...scan,
attributes: {
...scan.attributes,
// Format duration for display
durationLabel: scan.attributes.duration
? formatDuration(scan.attributes.duration)
: null,
// Check if scan is recent (completed within last 24 hours)
isRecent: isRecentScan(scan.attributes.completed_at),
},
}));
// Transform links to MetaDataProps format if pagination exists
const metadata: MetaDataProps | undefined = response.links
? {
pagination: {
// Links-based pagination doesn't have traditional page numbers
// but we preserve the structure for consistency
page: 1,
pages: 1,
count: enrichedData.length,
itemsPerPage: [10, 25, 50, 100],
},
version: "1.0",
}
: undefined;
return { data: enrichedData, metadata };
}
/**
* Check if a scan is recent (completed within last 24 hours)
*
* @param completedAt - Completion timestamp
* @returns true if scan completed within last 24 hours
*/
function isRecentScan(completedAt: string | null): boolean {
if (!completedAt) return false;
const completionTime = new Date(completedAt).getTime();
const oneDayAgo = Date.now() - 24 * 60 * 60 * 1000;
return completionTime > oneDayAgo;
}