This is related to #580 and a PR fixing this should target the tanstack-db branch.
Problem
The parseEventData function in src/lib/hooks/useRealtimeUpdates.ts:110-403 is ~290 lines of manual type checking with nested typeof checks for each event type:
function parseEventData(data: string): SyncEvent | null {
try {
const parsed: unknown = JSON.parse(data);
if (typeof parsed !== "object" || parsed === null || !("type" in parsed)) return null;
const event = parsed as Record<string, unknown>;
if (
event.type === "new_entry" &&
(typeof event.subscriptionId === "string" || event.subscriptionId === null) &&
typeof event.entryId === "string" &&
typeof event.updatedAt === "string"
) {
return { type: "new_entry" as const, ... };
}
// ... 250+ more lines of the same pattern for each event type
}
}
Why this should change
- Error-prone: Easy to miss a field validation or get a type wrong. No compiler help — all runtime
typeof checks.
- Duplicated validation: The server already has Zod schemas for these exact event types in
src/server/trpc/routers/sync.ts:155-170+. The same shapes are validated in two places with two different mechanisms.
- Hard to maintain: Adding a field to an event requires updating both the server Zod schema and this manual parser, with no compile-time link between them.
Suggestion
Use Zod (already a dependency) to validate SSE events. The server-side sync router already defines Zod schemas for these events — they could be shared or mirrored:
// Shared event schemas (e.g., src/lib/events/schemas.ts)
const newEntryEventSchema = z.object({
type: z.literal("new_entry"),
subscriptionId: z.string().nullable(),
entryId: z.string(),
updatedAt: z.string(),
timestamp: z.string().optional().default(() => new Date().toISOString()),
feedType: z.enum(["web", "email", "saved"]).optional(),
});
const syncEventSchema = z.discriminatedUnion("type", [
newEntryEventSchema,
entryUpdatedEventSchema,
entryStateChangedEventSchema,
// ...
]);
// Usage
function parseEventData(data: string): SyncEvent | null {
try {
const result = syncEventSchema.safeParse(JSON.parse(data));
return result.success ? result.data : null;
} catch {
return null;
}
}
This would reduce ~290 lines to ~50, add compile-time type safety, and could share schemas with the server.
This is related to #580 and a PR fixing this should target the
tanstack-dbbranch.Problem
The
parseEventDatafunction insrc/lib/hooks/useRealtimeUpdates.ts:110-403is ~290 lines of manual type checking with nestedtypeofchecks for each event type:Why this should change
typeofchecks.src/server/trpc/routers/sync.ts:155-170+. The same shapes are validated in two places with two different mechanisms.Suggestion
Use Zod (already a dependency) to validate SSE events. The server-side sync router already defines Zod schemas for these events — they could be shared or mirrored:
This would reduce ~290 lines to ~50, add compile-time type safety, and could share schemas with the server.