feat: add shared time, games and feed contracts
Time is this product's subject, so the vocabulary lives in one module: remaining, progress through a window, and urgency. Urgency is derived from absolute time left, deliberately independent of proportion — a 90-day event with three hours left is as urgent as a 3-day one. An unannounced end is never urgent and has no progress: "we don't know" and "loads of time" are different facts, and conflating them is what this product exists to avoid. Games carry a hue for identity only. Urgency is a separate axis, so one glance answers both "whose event is this?" and "how long have I got?". Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3b2feadf5d
commit
45ad5b39da
@@ -0,0 +1,29 @@
|
||||
import { z } from "zod";
|
||||
import { GachaEvent, GameId } from "./schema.ts";
|
||||
|
||||
/**
|
||||
* The wire contract between server and client.
|
||||
*
|
||||
* The client refuses a `schemaVersion` it does not know rather than guessing at
|
||||
* unfamiliar fields. Additive fields do not bump it; removing or retyping one
|
||||
* does. See docs/DATA-MODEL.md § Schema versioning.
|
||||
*/
|
||||
export const SCHEMA_VERSION = 1;
|
||||
|
||||
export const SourceHealth = z.object({
|
||||
sourceId: z.string(),
|
||||
game: GameId,
|
||||
url: z.string().url(),
|
||||
lastSuccessAt: z.string().datetime().nullable(),
|
||||
eventCount: z.number().int().nonnegative(),
|
||||
});
|
||||
|
||||
export const EventFeed = z.object({
|
||||
schemaVersion: z.literal(SCHEMA_VERSION),
|
||||
generatedAt: z.string().datetime(),
|
||||
events: z.array(GachaEvent),
|
||||
sources: z.array(SourceHealth),
|
||||
});
|
||||
|
||||
export type SourceHealth = z.infer<typeof SourceHealth>;
|
||||
export type EventFeed = z.infer<typeof EventFeed>;
|
||||
Reference in New Issue
Block a user