99 lines
3.7 KiB
TypeScript
99 lines
3.7 KiB
TypeScript
import { getDbClient } from "@hivegrid/db/client.server";
|
|
import { runWithRlsContext } from "@hivegrid/db/rls-context.server";
|
|
import type {
|
|
KwpContractAlarmInput,
|
|
KwpContractDiffVM,
|
|
} from "@hivegrid/view-models";
|
|
import { KWP_PROJECT_CAPABILITY } from "@hivegrid/integrations/kwp-resource-client.server";
|
|
|
|
const MAX_DIFF_PATHS = 100;
|
|
|
|
function redactedDiff(value: unknown): KwpContractDiffVM | null {
|
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
const diff = (value as Record<string, unknown>).diff;
|
|
if (!diff || typeof diff !== "object" || Array.isArray(diff)) return null;
|
|
const row = diff as Record<string, unknown>;
|
|
const paths = (key: string) => Array.isArray(row[key])
|
|
? row[key]!.filter((item): item is string => typeof item === "string").slice(0, MAX_DIFF_PATHS)
|
|
: [];
|
|
return {
|
|
added: paths("added"),
|
|
removed: paths("removed"),
|
|
changed: paths("changed"),
|
|
truncated: row.truncated === true,
|
|
};
|
|
}
|
|
|
|
export async function getKwpContractAdminSnapshot(
|
|
actorUserId: string,
|
|
): Promise<readonly KwpContractAlarmInput[]> {
|
|
return runWithRlsContext({ userId: actorUserId }, async () => {
|
|
const db = getDbClient();
|
|
const states = await db.kwpCapabilityState.findMany({
|
|
where: { capability: KWP_PROJECT_CAPABILITY, status: "paused" },
|
|
orderBy: [{ pausedAt: "desc" }, { updatedAt: "desc" }],
|
|
take: 200,
|
|
});
|
|
if (states.length === 0) return [];
|
|
|
|
const tenantIds = [...new Set(states.map((row) => row.tenantId))];
|
|
const connectionPairs = states.map((row) => ({
|
|
tenantId: row.tenantId,
|
|
dataConnectionId: row.dataConnectionId,
|
|
}));
|
|
const [tenants, reports, snapshots] = await Promise.all([
|
|
db.tenant.findMany({
|
|
where: { id: { in: tenantIds } },
|
|
select: { id: true, name: true },
|
|
}),
|
|
db.kwpErrorReport.findMany({
|
|
where: {
|
|
capability: KWP_PROJECT_CAPABILITY,
|
|
resolvedAt: null,
|
|
OR: connectionPairs,
|
|
},
|
|
orderBy: { createdAt: "desc" },
|
|
}),
|
|
db.kwpApiContractSnapshot.findMany({
|
|
where: {
|
|
capability: KWP_PROJECT_CAPABILITY,
|
|
OR: connectionPairs,
|
|
},
|
|
orderBy: { validatedAt: "desc" },
|
|
}),
|
|
]);
|
|
const tenantNames = new Map(tenants.map((row) => [row.id, row.name]));
|
|
const pairKey = (tenantId: string, connectionId: string) => `${tenantId}\u0000${connectionId}`;
|
|
const latestReports = new Map<string, (typeof reports)[number]>();
|
|
for (const report of reports) {
|
|
const key = pairKey(report.tenantId, report.dataConnectionId);
|
|
if (!latestReports.has(key)) latestReports.set(key, report);
|
|
}
|
|
const latestSnapshots = new Map<string, (typeof snapshots)[number]>();
|
|
for (const snapshot of snapshots) {
|
|
const key = pairKey(snapshot.tenantId, snapshot.dataConnectionId);
|
|
if (!latestSnapshots.has(key)) latestSnapshots.set(key, snapshot);
|
|
}
|
|
|
|
return states.map((state) => {
|
|
const key = pairKey(state.tenantId, state.dataConnectionId);
|
|
const report = latestReports.get(key);
|
|
const snapshot = latestSnapshots.get(key);
|
|
return {
|
|
id: state.id,
|
|
tenantId: state.tenantId,
|
|
tenantName: tenantNames.get(state.tenantId) ?? state.tenantId,
|
|
connectionId: state.dataConnectionId,
|
|
reasonCode: state.reasonCode,
|
|
observedFingerprint: state.observedFingerprint,
|
|
adapterRevision: state.adapterRevision,
|
|
capabilityRevision: state.revision,
|
|
pausedAt: state.pausedAt?.toISOString() ?? null,
|
|
lastCheckedAt: state.lastCheckedAt?.toISOString() ?? null,
|
|
lastValidatedAt: snapshot?.validatedAt.toISOString() ?? null,
|
|
diff: redactedDiff(report?.redactedDetails),
|
|
};
|
|
});
|
|
});
|
|
}
|