Files
2026-08-20 15:08:32 +00:00

64 lines
2.0 KiB
JavaScript

import { windowParams, clampLimit, clampOffset, SORTABLE_KEYS } from "./query.js";
// Enums are rejected when present-but-invalid (400); numeric/date params are
// leniently clamped so an odd page size still returns sensible data.
const TYPES = ["core", "audit"];
const DIRS = ["asc", "desc"];
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
export const isUuid = (s) => typeof s === "string" && UUID_RE.test(s);
export function parseWindow(query = {}) {
return windowParams(query);
}
const MAX_VERIFY_TARGETS = 200;
const splitList = (v) => (typeof v === "string" ? v.split(",") : []).map((s) => s.trim()).filter(Boolean);
// `ids` are event UUIDs (core tab); `auditIds` are audit records (audit tab,
// where rows share an event UUID). The cap applies to both lists combined.
export function parseVerifyTargets(query = {}) {
const eventUuids = [...new Set(splitList(query.ids).filter(isUuid))].slice(0, MAX_VERIFY_TARGETS);
const auditIds = [...new Set(splitList(query.auditIds).map(Number))]
.filter((n) => Number.isInteger(n) && n > 0)
.slice(0, Math.max(0, MAX_VERIFY_TARGETS - eventUuids.length));
return { eventUuids, auditIds };
}
export function parseTransactionsQuery(query = {}) {
const type = query.type ?? "core";
if (!TYPES.includes(type)) {
return { ok: false, error: `type must be one of ${TYPES.join(", ")}` };
}
let sort = query.sort;
if (sort != null && !SORTABLE_KEYS.includes(sort)) {
return { ok: false, error: `sort must be one of ${SORTABLE_KEYS.join(", ")}` };
}
if (sort == null) sort = undefined;
const dir = query.dir ?? "desc";
if (!DIRS.includes(dir)) {
return { ok: false, error: `dir must be one of ${DIRS.join(", ")}` };
}
const { from, to } = windowParams(query);
const q = typeof query.q === "string" ? query.q.slice(0, 200) : "";
return {
ok: true,
value: {
type,
from,
to,
q,
sort,
dir,
limit: clampLimit(query.limit),
offset: clampOffset(query.offset),
},
};
}