fix(housekeeping): complete people read fidelity
CI / check (pull_request) Successful in 31s
CI / deploy (pull_request) Skipped
CI / release (pull_request) Skipped

This commit is contained in:
Simo committed 2026-08-29 10:34:44 +02:00
1 parent d1382c839e
commit 7920d4f46c
8 files changed
+564 -37

No files matched your search

@@ -92,15 +92,15 @@ export interface PeopleGuildSummary {
readonly id: number;
readonly name: string;
readonly description: string;
readonly ownerId: number;
readonly userId: number;
readonly ownerUsername: string | null;
readonly roomId: number;
readonly memberCount: number;
readonly createdAt: string | null;
readonly href: `/ase/people/community/guilds/${number}`;
}
export interface PeopleGuildDetail extends PeopleGuildSummary {
readonly roomId: number;
readonly threadCount: number;
readonly members: readonly {
readonly id: number;
@@ -166,6 +166,13 @@ export interface PeopleTicketSummary {
| `/ase/people/support/help-tickets/${number}`;
}
export interface PeopleTicketDeskSummary extends PeopleTicketSummary {
readonly source: "cms";
readonly category: string;
readonly assigneeId: number | null;
readonly messageCount: number;
}
export interface PeopleTicketDetail extends PeopleTicketSummary {
readonly category: string;
readonly assigneeId: number | null;
@@ -188,6 +195,7 @@ export interface PeopleHelpTicketSummary {
readonly userId: number | null;
readonly username: string | null;
readonly updatedAt: string | null;
readonly replyCount: number;
readonly href: `/ase/people/support/help-tickets/${number}`;
}
@@ -462,7 +470,25 @@ const DATE_KEYS = new Set([
]);
export function assertPeopleSerializable(value: unknown): void {
function visit(current: unknown, key = ""): void {
function permitsZeroSentinel(parent: unknown, key: string): boolean {
if (typeof parent !== "object" || parent === null) return false;
const href = Reflect.get(parent, "href");
if (typeof href !== "string") return false;
if (href.startsWith("/ase/people/community/guilds/")) {
return key === "userId" || key === "roomId";
}
if (href.startsWith("/ase/people/moderation/cfh/")) {
return (
key === "senderId" ||
key === "reportedId" ||
key === "roomId" ||
key === "moderatorId"
);
}
return false;
}
function visit(current: unknown, key = "", parent?: unknown): void {
if (
current === null ||
typeof current === "string" ||
@@ -480,13 +506,17 @@ export function assertPeopleSerializable(value: unknown): void {
if (typeof current === "number") {
if (!Number.isSafeInteger(current))
throw new Error("invalid People number");
if ((key === "id" || key.endsWith("Id")) && current <= 0) {
if (
(key === "id" || key.endsWith("Id")) &&
current <= 0 &&
!(current === 0 && permitsZeroSentinel(parent, key))
) {
throw new Error("invalid People identifier");
}
return;
}
if (Array.isArray(current)) {
for (const item of current) visit(item);
for (const item of current) visit(item, "", current);
return;
}
if (typeof current !== "object" || current instanceof Date) {
@@ -494,7 +524,7 @@ export function assertPeopleSerializable(value: unknown): void {
}
for (const [childKey, child] of Object.entries(current)) {
if (child === undefined) throw new Error("undefined People value");
visit(child, childKey);
visit(child, childKey, current);
}
}
visit(value);