2025-11-27 09:09:43 +01:00

138 lines
3.1 KiB
TypeScript

export type AuditRow = Record<string, unknown> & { id: string | number };
export interface AuditApiResponse {
total?: number;
limit?: number;
page?: number;
data?: unknown;
items?: unknown[];
audits?: unknown[];
logs?: unknown[];
results?: unknown[];
records?: unknown[];
meta?: { total?: number };
pagination?: { total?: number };
}
export interface AuditQueryResult {
rows: AuditRow[];
total: number;
payload: AuditApiResponse;
pageIndex: number;
}
export const DEFAULT_PAGE_SIZE = 25;
const CANDIDATE_ARRAY_KEYS: (keyof AuditApiResponse)[] = [
"items",
"audits",
"logs",
"results",
"records",
];
export const normalizeValue = (value: unknown): string | number => {
if (value === null || value === undefined) {
return "";
}
if (typeof value === "string" || typeof value === "number") {
return value;
}
if (typeof value === "boolean") {
return value ? "true" : "false";
}
return JSON.stringify(value);
};
export const extractArray = (payload: AuditApiResponse): unknown[] => {
if (Array.isArray(payload)) {
return payload;
}
for (const key of CANDIDATE_ARRAY_KEYS) {
const candidate = payload[key];
if (Array.isArray(candidate)) {
return candidate;
}
}
const dataRecord =
payload.data &&
typeof payload.data === "object" &&
!Array.isArray(payload.data)
? (payload.data as Record<string, unknown>)
: null;
if (dataRecord) {
for (const key of CANDIDATE_ARRAY_KEYS) {
const candidate = dataRecord[key];
if (Array.isArray(candidate)) {
return candidate;
}
}
}
if (Array.isArray(payload.data)) {
return payload.data;
}
return [];
};
export const resolveTotal = (
payload: AuditApiResponse,
fallback: number
): number => {
const fromPayload = payload.total;
const fromMeta = payload.meta?.total;
const fromPagination = payload.pagination?.total;
const fromData =
payload.data &&
typeof payload.data === "object" &&
!Array.isArray(payload.data)
? (payload.data as { total?: number }).total
: undefined;
return (
(typeof fromPayload === "number" && fromPayload) ||
(typeof fromMeta === "number" && fromMeta) ||
(typeof fromPagination === "number" && fromPagination) ||
(typeof fromData === "number" && fromData) ||
fallback
);
};
export const normalizeRows = (
entries: unknown[],
pageIndex: number
): AuditRow[] =>
entries.map((entry, index) => {
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
return {
id: `${pageIndex}-${index}`,
value: normalizeValue(entry),
};
}
const record = entry as Record<string, unknown>;
const normalized: Record<string, unknown> = {};
Object.entries(record).forEach(([key, value]) => {
normalized[key] = normalizeValue(value);
});
const identifier =
record.id ??
record.audit_id ??
record.log_id ??
record._id ??
`${pageIndex}-${index}`;
return {
id: (identifier as string | number) ?? `${pageIndex}-${index}`,
...normalized,
};
});