@ttt-productions/q-core 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants/business.d.ts +12 -0
- package/dist/constants/business.d.ts.map +1 -1
- package/dist/constants/business.js +24 -0
- package/dist/constants/business.js.map +1 -1
- package/dist/constants/media.d.ts +1 -0
- package/dist/constants/media.d.ts.map +1 -1
- package/dist/constants/media.js +5 -0
- package/dist/constants/media.js.map +1 -1
- package/dist/constants/sports.js.map +1 -1
- package/dist/constants/storage-keys.js.map +1 -1
- package/dist/doc-schemas/admin-notifications.d.ts +1 -0
- package/dist/doc-schemas/admin-notifications.d.ts.map +1 -1
- package/dist/doc-schemas/admin-notifications.js +4 -0
- package/dist/doc-schemas/admin-notifications.js.map +1 -1
- package/dist/doc-schemas/atoms.d.ts +2 -0
- package/dist/doc-schemas/atoms.d.ts.map +1 -1
- package/dist/doc-schemas/audit-event.d.ts +2 -0
- package/dist/doc-schemas/audit-event.d.ts.map +1 -1
- package/dist/doc-schemas/catalogs.js.map +1 -1
- package/dist/doc-schemas/gallery.d.ts +1 -0
- package/dist/doc-schemas/gallery.d.ts.map +1 -1
- package/dist/doc-schemas/gallery.js +3 -0
- package/dist/doc-schemas/gallery.js.map +1 -1
- package/dist/doc-schemas/game-location.js.map +1 -1
- package/dist/doc-schemas/game-stats.js.map +1 -1
- package/dist/doc-schemas/league-team.js.map +1 -1
- package/dist/doc-schemas/migration-console.d.ts +2 -0
- package/dist/doc-schemas/migration-console.d.ts.map +1 -1
- package/dist/doc-schemas/migration-console.js +5 -0
- package/dist/doc-schemas/migration-console.js.map +1 -1
- package/dist/doc-schemas/pending-media.d.ts +1 -0
- package/dist/doc-schemas/pending-media.d.ts.map +1 -1
- package/dist/doc-schemas/pending-media.js +8 -0
- package/dist/doc-schemas/pending-media.js.map +1 -1
- package/dist/doc-schemas/registry.d.ts +12 -0
- package/dist/doc-schemas/registry.d.ts.map +1 -1
- package/dist/doc-schemas/registry.js.map +1 -1
- package/dist/doc-schemas/sport-game.js.map +1 -1
- package/dist/doc-schemas/stats-operation.d.ts.map +1 -1
- package/dist/doc-schemas/stats-operation.js +6 -11
- package/dist/doc-schemas/stats-operation.js.map +1 -1
- package/dist/doc-schemas/system.d.ts +7 -0
- package/dist/doc-schemas/system.d.ts.map +1 -1
- package/dist/doc-schemas/system.js +4 -1
- package/dist/doc-schemas/system.js.map +1 -1
- package/dist/doc-schemas/user-profile.d.ts +1 -0
- package/dist/doc-schemas/user-profile.d.ts.map +1 -1
- package/dist/doc-schemas/user-profile.js +5 -0
- package/dist/doc-schemas/user-profile.js.map +1 -1
- package/dist/doc-schemas/waiver-template.d.ts +1 -0
- package/dist/doc-schemas/waiver-template.d.ts.map +1 -1
- package/dist/doc-schemas/waiver-template.js +10 -1
- package/dist/doc-schemas/waiver-template.js.map +1 -1
- package/dist/doc-schemas/waivers-and-hardware.d.ts +1 -0
- package/dist/doc-schemas/waivers-and-hardware.d.ts.map +1 -1
- package/dist/doc-schemas/waivers-and-hardware.js +17 -9
- package/dist/doc-schemas/waivers-and-hardware.js.map +1 -1
- package/dist/ids/index.js.map +1 -1
- package/dist/ids/minted-ids.d.ts +1 -0
- package/dist/ids/minted-ids.d.ts.map +1 -1
- package/dist/ids/minted-ids.js +6 -0
- package/dist/ids/minted-ids.js.map +1 -1
- package/dist/ids/stats-operation-ids.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/input-formats/index.d.ts +2 -2
- package/dist/input-formats/index.d.ts.map +1 -1
- package/dist/input-formats/index.js +2 -2
- package/dist/input-formats/index.js.map +1 -1
- package/dist/media/file-origins.js.map +1 -1
- package/dist/notifications/archive-all.d.ts +2 -0
- package/dist/notifications/archive-all.d.ts.map +1 -0
- package/dist/notifications/archive-all.js +6 -0
- package/dist/notifications/archive-all.js.map +1 -0
- package/dist/notifications/index.d.ts +1 -0
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +1 -0
- package/dist/notifications/index.js.map +1 -1
- package/dist/paths/collection-refs.js.map +1 -1
- package/dist/paths/collections.js.map +1 -1
- package/dist/paths/path-builders.js.map +1 -1
- package/dist/paths/utils.js.map +1 -1
- package/dist/schemas/account-settings.js.map +1 -1
- package/dist/schemas/admin-notifications.d.ts +1 -0
- package/dist/schemas/admin-notifications.d.ts.map +1 -1
- package/dist/schemas/admin-notifications.js +4 -2
- package/dist/schemas/admin-notifications.js.map +1 -1
- package/dist/schemas/app-config.d.ts +2 -2
- package/dist/schemas/app-config.d.ts.map +1 -1
- package/dist/schemas/app-config.js +9 -5
- package/dist/schemas/app-config.js.map +1 -1
- package/dist/schemas/atoms.js.map +1 -1
- package/dist/schemas/awards.d.ts +16 -4
- package/dist/schemas/awards.d.ts.map +1 -1
- package/dist/schemas/awards.js +10 -6
- package/dist/schemas/awards.js.map +1 -1
- package/dist/schemas/game-locations.d.ts +4 -4
- package/dist/schemas/game-locations.d.ts.map +1 -1
- package/dist/schemas/game-locations.js +11 -3
- package/dist/schemas/game-locations.js.map +1 -1
- package/dist/schemas/hardware-loan-contracts.js.map +1 -1
- package/dist/schemas/migration-console.d.ts +1 -0
- package/dist/schemas/migration-console.d.ts.map +1 -1
- package/dist/schemas/pictures.d.ts +3 -0
- package/dist/schemas/pictures.d.ts.map +1 -1
- package/dist/schemas/schedules.js.map +1 -1
- package/dist/schemas/scoring.js.map +1 -1
- package/dist/schemas/stats.d.ts +2 -0
- package/dist/schemas/stats.d.ts.map +1 -1
- package/dist/schemas/stats.js.map +1 -1
- package/dist/schemas/team-joining.js.map +1 -1
- package/dist/schemas/teams.d.ts +3 -2
- package/dist/schemas/teams.d.ts.map +1 -1
- package/dist/schemas/teams.js +19 -9
- package/dist/schemas/teams.js.map +1 -1
- package/dist/schemas/uploads.js.map +1 -1
- package/dist/schemas/users.d.ts +7 -3
- package/dist/schemas/users.d.ts.map +1 -1
- package/dist/schemas/users.js +10 -3
- package/dist/schemas/users.js.map +1 -1
- package/dist/schemas/waiver-templates.d.ts +1 -0
- package/dist/schemas/waiver-templates.d.ts.map +1 -1
- package/dist/schemas/waiver-templates.js +4 -1
- package/dist/schemas/waiver-templates.js.map +1 -1
- package/dist/sports/basketball-scoring.js.map +1 -1
- package/dist/sports/basketball.js.map +1 -1
- package/dist/sports/bulk-entry.js.map +1 -1
- package/dist/sports/contribution.js.map +1 -1
- package/dist/sports/curling-scoring.js.map +1 -1
- package/dist/sports/finalized-record.js.map +1 -1
- package/dist/sports/football-scoring.js.map +1 -1
- package/dist/sports/index.d.ts +1 -0
- package/dist/sports/index.d.ts.map +1 -1
- package/dist/sports/index.js +1 -0
- package/dist/sports/index.js.map +1 -1
- package/dist/sports/ledger-continuity.d.ts +13 -0
- package/dist/sports/ledger-continuity.d.ts.map +1 -0
- package/dist/sports/ledger-continuity.js +19 -0
- package/dist/sports/ledger-continuity.js.map +1 -0
- package/dist/sports/rankings.js.map +1 -1
- package/dist/sports/rollup-check.js.map +1 -1
- package/dist/sports/scoring.js.map +1 -1
- package/dist/sports/store-driver.js.map +1 -1
- package/dist/types/audit.d.ts +1 -1
- package/dist/types/audit.d.ts.map +1 -1
- package/dist/types/audit.js +5 -2
- package/dist/types/audit.js.map +1 -1
- package/dist/types/documents.js.map +1 -1
- package/dist/types/notifications.js.map +1 -1
- package/dist/types/picture-owners.js.map +1 -1
- package/dist/types/sports.js.map +1 -1
- package/dist/types/stats.js.map +1 -1
- package/dist/types/unions.d.ts +4 -2
- package/dist/types/unions.d.ts.map +1 -1
- package/dist/types/unions.js +6 -0
- package/dist/types/unions.js.map +1 -1
- package/dist/upload-variables/index.d.ts +3 -0
- package/dist/upload-variables/index.d.ts.map +1 -0
- package/dist/upload-variables/index.js +3 -0
- package/dist/upload-variables/index.js.map +1 -0
- package/dist/upload-variables/on-progress.d.ts +4 -0
- package/dist/upload-variables/on-progress.d.ts.map +1 -0
- package/dist/upload-variables/on-progress.js +10 -0
- package/dist/upload-variables/on-progress.js.map +1 -0
- package/dist/upload-variables/picture-upload-variables.d.ts +32 -0
- package/dist/upload-variables/picture-upload-variables.d.ts.map +1 -0
- package/dist/upload-variables/picture-upload-variables.js +21 -0
- package/dist/upload-variables/picture-upload-variables.js.map +1 -0
- package/dist/utils/account-status.js.map +1 -1
- package/dist/utils/app-config.d.ts +17 -3
- package/dist/utils/app-config.d.ts.map +1 -1
- package/dist/utils/app-config.js +21 -14
- package/dist/utils/app-config.js.map +1 -1
- package/dist/utils/app-routes.js.map +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/league-calendar.js.map +1 -1
- package/dist/utils/league-mode.js.map +1 -1
- package/dist/utils/team-member-actions.js.map +1 -1
- package/package.json +94 -90
|
@@ -46,4 +46,16 @@ export declare const MAX_SCHEDULE_WEEK_TITLE_LENGTH = 100;
|
|
|
46
46
|
export declare const MAX_SCHEDULE_WEEK_GAMES = 20;
|
|
47
47
|
export declare const LEAGUE_TIME_ZONE = "America/New_York";
|
|
48
48
|
export declare const MAX_GAME_MEMO_LENGTH = 30;
|
|
49
|
+
export declare const countCapReachedMessage: (subject: string, limit: number, noun: string) => string;
|
|
50
|
+
export declare const MAX_ACTIVE_TEAM_MEMBERS = 100;
|
|
51
|
+
export declare const TEAM_FULL_MESSAGE: string;
|
|
52
|
+
export declare const MAX_ROSTER_SEED_MEMBERSHIPS_PER_TEAM = 100;
|
|
53
|
+
export declare const MAX_DEPARTED_ROSTER_ENTRIES_PER_TEAM = 20;
|
|
54
|
+
export declare const MAX_ROSTER_ENTRIES_PER_TEAM: number;
|
|
55
|
+
export declare const MAX_TEAMS_PER_LEAGUE = 498;
|
|
56
|
+
export declare const MAX_GAMES_PER_LEAGUE = 1000;
|
|
57
|
+
export declare const LEAGUE_TEAMS_FULL_MESSAGE: string;
|
|
58
|
+
export declare const LEAGUE_GAMES_FULL_MESSAGE: string;
|
|
59
|
+
export declare const MAX_STAT_EVENTS_PER_GAME = 5000;
|
|
60
|
+
export declare const GAME_STAT_LOG_FULL_MESSAGE: string;
|
|
49
61
|
//# sourceMappingURL=business.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"business.d.ts","sourceRoot":"","sources":["../../src/constants/business.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,eAAO,MAAM,oCAAoC,KAAK,CAAC;AACvD,eAAO,MAAM,oCAAoC,MAAM,CAAC;AACxD,eAAO,MAAM,kCAAkC,MAAM,CAAC;AAEtD,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAGlD,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAGtC,eAAO,MAAM,gBAAgB;;;;;;EAGnB,CAAC;AACX,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AAC5E,eAAO,MAAM,yBAAyB,EAA8C,CAClF,qBAAqB,EACrB,GAAG,qBAAqB,EAAE,CAC3B,CAAC;AAGF,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAIxC,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAI1C,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAG5C,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAGzC,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAG5C,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAG3C,eAAO,MAAM,sCAAsC,MAAM,CAAC;AAG1D,eAAO,MAAM,8BAA8B,OAAO,CAAC;AACnD,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAEnD,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAGzC,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAIlD,eAAO,MAAM,gCAAgC,MAAM,CAAC;AACpD,eAAO,MAAM,+BAA+B,QAAQ,CAAC;AAGrD,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,eAAO,MAAM,uCAAuC,MAAM,CAAC;AAC3D,eAAO,MAAM,+BAA+B,KAAK,CAAC;AAClD,eAAO,MAAM,qCAAqC,KAAK,CAAC;AACxD,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAIjD,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAG1C,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAGnD,eAAO,MAAM,oBAAoB,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"business.d.ts","sourceRoot":"","sources":["../../src/constants/business.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,eAAO,MAAM,oCAAoC,KAAK,CAAC;AACvD,eAAO,MAAM,oCAAoC,MAAM,CAAC;AACxD,eAAO,MAAM,kCAAkC,MAAM,CAAC;AAEtD,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAGlD,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAGtC,eAAO,MAAM,gBAAgB;;;;;;EAGnB,CAAC;AACX,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AAC5E,eAAO,MAAM,yBAAyB,EAA8C,CAClF,qBAAqB,EACrB,GAAG,qBAAqB,EAAE,CAC3B,CAAC;AAGF,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAIxC,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAI1C,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAG5C,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAGzC,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAG5C,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAG3C,eAAO,MAAM,sCAAsC,MAAM,CAAC;AAG1D,eAAO,MAAM,8BAA8B,OAAO,CAAC;AACnD,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAEnD,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAGzC,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAIlD,eAAO,MAAM,gCAAgC,MAAM,CAAC;AACpD,eAAO,MAAM,+BAA+B,QAAQ,CAAC;AAGrD,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,eAAO,MAAM,uCAAuC,MAAM,CAAC;AAC3D,eAAO,MAAM,+BAA+B,KAAK,CAAC;AAClD,eAAO,MAAM,qCAAqC,KAAK,CAAC;AACxD,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAIjD,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAG1C,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAGnD,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAIvC,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,EAAE,OAAO,MAAM,EAAE,MAAM,MAAM,KAAG,MAC3B,CAAC;AAI5D,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,iBAAiB,QAA0E,CAAC;AAEzG,eAAO,MAAM,oCAAoC,MAA0B,CAAC;AAG5E,eAAO,MAAM,oCAAoC,KAAK,CAAC;AAEvD,eAAO,MAAM,2BAA2B,QAAiE,CAAC;AAK1G,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,oBAAoB,OAAO,CAAC;AACzC,eAAO,MAAM,yBAAyB,QAAuE,CAAC;AAC9G,eAAO,MAAM,yBAAyB,QAAuE,CAAC;AAI9G,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,0BAA0B,QAAkF,CAAC"}
|
|
@@ -70,4 +70,28 @@ export const MAX_SCHEDULE_WEEK_GAMES = 20;
|
|
|
70
70
|
export const LEAGUE_TIME_ZONE = 'America/New_York';
|
|
71
71
|
// A scorer's note on one person in a game ("red shirt", "#9").
|
|
72
72
|
export const MAX_GAME_MEMO_LENGTH = 30;
|
|
73
|
+
// How a refusal at a count cap reads: the thing that is full, its limit, and what it holds.
|
|
74
|
+
export const countCapReachedMessage = (subject, limit, noun) => `${subject} already has the maximum of ${limit} ${noun}.`;
|
|
75
|
+
// A team's size. Every way onto a team is refused at this many active members, inside the
|
|
76
|
+
// admission's transaction, so a game's roster can always be seeded and checked in one read.
|
|
77
|
+
export const MAX_ACTIVE_TEAM_MEMBERS = 100;
|
|
78
|
+
export const TEAM_FULL_MESSAGE = countCapReachedMessage('This team', MAX_ACTIVE_TEAM_MEMBERS, 'members');
|
|
79
|
+
// The memberships one game-roster seed reads for a team: every membership is active, so the cap.
|
|
80
|
+
export const MAX_ROSTER_SEED_MEMBERSHIPS_PER_TEAM = MAX_ACTIVE_TEAM_MEMBERS;
|
|
81
|
+
// Departed players a team's side of an open game may keep beside its members: a player who recorded
|
|
82
|
+
// stats in the game keeps their entry after leaving the team.
|
|
83
|
+
export const MAX_DEPARTED_ROSTER_ENTRIES_PER_TEAM = 20;
|
|
84
|
+
// The entries one team's side of a game may hold, so a reconcile or finalize reads them in one page.
|
|
85
|
+
export const MAX_ROSTER_ENTRIES_PER_TEAM = MAX_ACTIVE_TEAM_MEMBERS + MAX_DEPARTED_ROSTER_ENTRIES_PER_TEAM;
|
|
86
|
+
// A league's size. Standings, schedules, and rankings need a league's complete set of teams and
|
|
87
|
+
// games, so creation is refused at these caps rather than any read being cut short. The team cap is
|
|
88
|
+
// also the most teams one mode switch rewrites in its one transaction.
|
|
89
|
+
export const MAX_TEAMS_PER_LEAGUE = 498;
|
|
90
|
+
export const MAX_GAMES_PER_LEAGUE = 1000;
|
|
91
|
+
export const LEAGUE_TEAMS_FULL_MESSAGE = countCapReachedMessage('This league', MAX_TEAMS_PER_LEAGUE, 'teams');
|
|
92
|
+
export const LEAGUE_GAMES_FULL_MESSAGE = countCapReachedMessage('This league', MAX_GAMES_PER_LEAGUE, 'games');
|
|
93
|
+
// A game's stat log. A write that would take a game's `statEventSequence` past it is refused with
|
|
94
|
+
// nothing written, which also bounds the game's live play-by-play.
|
|
95
|
+
export const MAX_STAT_EVENTS_PER_GAME = 5000;
|
|
96
|
+
export const GAME_STAT_LOG_FULL_MESSAGE = countCapReachedMessage('This game', MAX_STAT_EVENTS_PER_GAME, 'recorded stats');
|
|
73
97
|
//# sourceMappingURL=business.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"business.js","sourceRoot":"","sources":["../../src/constants/business.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,6FAA6F;AAE7F,6EAA6E;AAC7E,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAC1C,qEAAqE;AACrE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AACrC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AACtC,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,MAAM,CAAC,MAAM,oCAAoC,GAAG,EAAE,CAAC;AACvD,MAAM,CAAC,MAAM,oCAAoC,GAAG,GAAG,CAAC;AACxD,MAAM,CAAC,MAAM,kCAAkC,GAAG,GAAG,CAAC;AAEtD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAC3C,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAChD,MAAM,CAAC,MAAM,6BAA6B,GAAG,IAAI,CAAC;AAClD,mGAAmG;AACnG,uEAAuE;AACvE,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AACtC,gGAAgG;AAChG,2EAA2E;AAC3E,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;IAC5B,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,EAAE;CACpC,CAAC;AAEX,MAAM,CAAC,MAAM,yBAAyB,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAG9E,CAAC;AAEF,kCAAkC;AAClC,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AACvC,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC;AAExC,oGAAoG;AACpG,wFAAwF;AACxF,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAC9C,gFAAgF;AAChF,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAE1C,sGAAsG;AACtG,iCAAiC;AACjC,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAC1C,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAE5C,yEAAyE;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAEzC,wFAAwF;AACxF,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAE5C,qEAAqE;AACrE,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C,+FAA+F;AAC/F,MAAM,CAAC,MAAM,sCAAsC,GAAG,GAAG,CAAC;AAE1D,sCAAsC;AACtC,MAAM,CAAC,MAAM,8BAA8B,GAAG,IAAI,CAAC;AACnD,MAAM,CAAC,MAAM,+BAA+B,GAAG,GAAG,CAAC;AACnD,mFAAmF;AACnF,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAEzC,iCAAiC;AACjC,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AACjD,MAAM,CAAC,MAAM,6BAA6B,GAAG,IAAI,CAAC;AAElD,mGAAmG;AACnG,4CAA4C;AAC5C,MAAM,CAAC,MAAM,gCAAgC,GAAG,GAAG,CAAC;AACpD,MAAM,CAAC,MAAM,+BAA+B,GAAG,KAAK,CAAC;AAErD,mGAAmG;AACnG,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AACjD,MAAM,CAAC,MAAM,uCAAuC,GAAG,GAAG,CAAC;AAC3D,MAAM,CAAC,MAAM,+BAA+B,GAAG,EAAE,CAAC;AAClD,MAAM,CAAC,MAAM,qCAAqC,GAAG,EAAE,CAAC;AACxD,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AAEjD,mGAAmG;AACnG,8EAA8E;AAC9E,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,CAAC;AAClD,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAE1C,2EAA2E;AAC3E,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AAEnD,+DAA+D;AAC/D,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC","sourcesContent":["// Business limits and policy values both app roots enforce. A form reads these for its\
|
|
1
|
+
{"version":3,"file":"business.js","sourceRoot":"","sources":["../../src/constants/business.ts"],"names":[],"mappings":"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","sourcesContent":["// Business limits and policy values both app roots enforce. A form reads these for its\n// `maxLength` / zod bound and the callable's input schema reads the same constant (ENG-005).\n\n// Display names, team names, and ghost player names share one length policy.\nexport const MIN_DISPLAY_NAME_LENGTH = 3;\nexport const MAX_DISPLAY_NAME_LENGTH = 50;\n// The shortest password an account takes: Firebase Auth's own floor.\nexport const PASSWORD_MIN_LENGTH = 6;\nexport const MIN_TEAM_NAME_LENGTH = 3;\nexport const MAX_TEAM_NAME_LENGTH = 50;\n\nexport const MIN_TEAM_JOIN_REQUEST_MESSAGE_LENGTH = 10;\nexport const MAX_TEAM_JOIN_REQUEST_MESSAGE_LENGTH = 500;\nexport const MAX_TEAM_INVITATION_MESSAGE_LENGTH = 500;\n\nexport const MIN_LEAGUE_TITLE_LENGTH = 3;\nexport const MAX_LEAGUE_TITLE_LENGTH = 100;\nexport const MIN_LEAGUE_DESCRIPTION_LENGTH = 10;\nexport const MAX_LEAGUE_DESCRIPTION_LENGTH = 5000;\n// How many teams in a pool reach the playoffs. The cap only bounds the input: no league comes near\n// it, and a cutoff above a pool's team count simply admits every team.\nexport const MAX_PLAYOFF_CUTOFF = 100;\n// The equipment a referee can be loaned. The catalog is this constant: adding an item is a code\n// change, and a contract records each item's id and name as it was loaned.\nexport const HARDWARE_CATALOG = [\n { id: 'ipad', name: 'iPad' },\n { id: 'ipad-charger', name: 'iPad Charger' },\n] as const;\nexport type HardwareCatalogItemId = (typeof HARDWARE_CATALOG)[number]['id'];\nexport const HARDWARE_CATALOG_ITEM_IDS = HARDWARE_CATALOG.map((item) => item.id) as [\n HardwareCatalogItemId,\n ...HardwareCatalogItemId[],\n];\n\n// An award's name in the catalog.\nexport const MIN_AWARD_NAME_LENGTH = 3;\nexport const MAX_AWARD_NAME_LENGTH = 60;\n\n// The most people one award grant may reach once its teams and leagues are resolved to their active\n// members: every grant of one call commits in one transaction, beside its audit events.\nexport const MAX_AWARD_GRANT_RECIPIENTS = 200;\n// The most users, teams, or leagues one award grant call may name in each list.\nexport const MAX_AWARD_GRANT_TARGETS = 20;\n\n// The reason an admin gives for a repair action — a backfill, a recalculation, a reopen — recorded on\n// its audit event (BACKEND-212).\nexport const MIN_REPAIR_REASON_LENGTH = 3;\nexport const MAX_REPAIR_REASON_LENGTH = 500;\n\n// The most uids one `updateAdminList` call may grant or revoke per list.\nexport const MAX_ADMIN_LIST_CHANGES = 20;\n\n// A team may be created in a league until this many days after the league's start date.\nexport const TEAM_CREATION_CUTOFF_DAYS = 14;\n\n// Contact phone numbers are stored as typed, bounded only in length.\nexport const MAX_CONTACT_PHONE_LENGTH = 30;\n\n// The failure a roster obligation records when a reconciliation run fails, cut to this length.\nexport const MAX_ROSTER_SYNC_FAILURE_MESSAGE_LENGTH = 500;\n\n// `_appConfig/app` operator messages.\nexport const MAX_MAINTENANCE_MESSAGE_LENGTH = 2000;\nexport const MAX_ANNOUNCEMENT_MESSAGE_LENGTH = 300;\n// `_appConfig/app.appVersion` — the version a live client compares itself against.\nexport const MAX_APP_VERSION_LENGTH = 64;\n\n// `_appConfig/landingPage` copy.\nexport const MAX_LANDING_HERO_TITLE_LENGTH = 200;\nexport const MAX_LANDING_ABOUT_TEXT_LENGTH = 5000;\n\n// Waiver template wording. A signed waiver carries its own copy of the title and text, so the text\n// cap also bounds every signature document.\nexport const MAX_WAIVER_TEMPLATE_TITLE_LENGTH = 120;\nexport const MAX_WAIVER_TEMPLATE_TEXT_LENGTH = 20000;\n\n// Game locations: the venue, its address, the courts or sheets inside it, and the directions memo.\nexport const MAX_GAME_LOCATION_NAME_LENGTH = 100;\nexport const MAX_GAME_LOCATION_STREET_ADDRESS_LENGTH = 200;\nexport const MAX_GAME_LOCATION_SUB_LOCATIONS = 50;\nexport const MAX_GAME_LOCATION_SUB_LOCATION_LENGTH = 60;\nexport const MAX_GAME_LOCATION_MEMO_LENGTH = 500;\n\n// A week of the schedule: its title, and the games one save creates with it — each seeded with its\n// teams' rosters in the same transaction, so a larger week is saved in parts.\nexport const MAX_SCHEDULE_WEEK_TITLE_LENGTH = 100;\nexport const MAX_SCHEDULE_WEEK_GAMES = 20;\n\n// The timezone a game's `dayKey` (its local calendar date) is computed in.\nexport const LEAGUE_TIME_ZONE = 'America/New_York';\n\n// A scorer's note on one person in a game (\"red shirt\", \"#9\").\nexport const MAX_GAME_MEMO_LENGTH = 30;\n\n\n// How a refusal at a count cap reads: the thing that is full, its limit, and what it holds.\nexport const countCapReachedMessage = (subject: string, limit: number, noun: string): string =>\n `${subject} already has the maximum of ${limit} ${noun}.`;\n\n// A team's size. Every way onto a team is refused at this many active members, inside the\n// admission's transaction, so a game's roster can always be seeded and checked in one read.\nexport const MAX_ACTIVE_TEAM_MEMBERS = 100;\nexport const TEAM_FULL_MESSAGE = countCapReachedMessage('This team', MAX_ACTIVE_TEAM_MEMBERS, 'members');\n// The memberships one game-roster seed reads for a team: every membership is active, so the cap.\nexport const MAX_ROSTER_SEED_MEMBERSHIPS_PER_TEAM = MAX_ACTIVE_TEAM_MEMBERS;\n// Departed players a team's side of an open game may keep beside its members: a player who recorded\n// stats in the game keeps their entry after leaving the team.\nexport const MAX_DEPARTED_ROSTER_ENTRIES_PER_TEAM = 20;\n// The entries one team's side of a game may hold, so a reconcile or finalize reads them in one page.\nexport const MAX_ROSTER_ENTRIES_PER_TEAM = MAX_ACTIVE_TEAM_MEMBERS + MAX_DEPARTED_ROSTER_ENTRIES_PER_TEAM;\n\n// A league's size. Standings, schedules, and rankings need a league's complete set of teams and\n// games, so creation is refused at these caps rather than any read being cut short. The team cap is\n// also the most teams one mode switch rewrites in its one transaction.\nexport const MAX_TEAMS_PER_LEAGUE = 498;\nexport const MAX_GAMES_PER_LEAGUE = 1000;\nexport const LEAGUE_TEAMS_FULL_MESSAGE = countCapReachedMessage('This league', MAX_TEAMS_PER_LEAGUE, 'teams');\nexport const LEAGUE_GAMES_FULL_MESSAGE = countCapReachedMessage('This league', MAX_GAMES_PER_LEAGUE, 'games');\n\n// A game's stat log. A write that would take a game's `statEventSequence` past it is refused with\n// nothing written, which also bounds the game's live play-by-play.\nexport const MAX_STAT_EVENTS_PER_GAME = 5000;\nexport const GAME_STAT_LOG_FULL_MESSAGE = countCapReachedMessage('This game', MAX_STAT_EVENTS_PER_GAME, 'recorded stats');\n"]}
|
|
@@ -8,6 +8,7 @@ export declare const PICTURE_RETIREMENT_PAGE_SIZE = 50;
|
|
|
8
8
|
export declare const GALLERY_RETIREMENT_PICTURES_PER_RUN = 100;
|
|
9
9
|
export declare const STAGING_LIST_PAGE_SIZE = 1000;
|
|
10
10
|
export declare const MAX_STAGING_DELETES_PER_RUN = 500;
|
|
11
|
+
export declare const MAX_STAGING_EXAMINED_PER_RUN: number;
|
|
11
12
|
export declare const MAX_V1_PICTURE_CARRY_ATTEMPTS = 3;
|
|
12
13
|
export declare const MAX_STAGING_UPLOAD_PATH_LENGTH = 300;
|
|
13
14
|
//# sourceMappingURL=media.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/constants/media.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAI/C,eAAO,MAAM,yBAAyB,QAAiB,CAAC;AAIxD,eAAO,MAAM,0BAA0B,QAAiB,CAAC;AAIzD,eAAO,MAAM,wBAAwB,QAAe,CAAC;AAIrD,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,eAAO,MAAM,qCAAqC,IAAI,CAAC;AACvD,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,eAAO,MAAM,mCAAmC,MAAM,CAAC;AACvD,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,2BAA2B,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/constants/media.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAI/C,eAAO,MAAM,yBAAyB,QAAiB,CAAC;AAIxD,eAAO,MAAM,0BAA0B,QAAiB,CAAC;AAIzD,eAAO,MAAM,wBAAwB,QAAe,CAAC;AAIrD,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,eAAO,MAAM,qCAAqC,IAAI,CAAC;AACvD,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,eAAO,MAAM,mCAAmC,MAAM,CAAC;AACvD,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAK/C,eAAO,MAAM,4BAA4B,QAA6B,CAAC;AAIvE,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAG/C,eAAO,MAAM,8BAA8B,MAAM,CAAC"}
|
package/dist/constants/media.js
CHANGED
|
@@ -23,6 +23,11 @@ export const PICTURE_RETIREMENT_PAGE_SIZE = 50;
|
|
|
23
23
|
export const GALLERY_RETIREMENT_PICTURES_PER_RUN = 100;
|
|
24
24
|
export const STAGING_LIST_PAGE_SIZE = 1000;
|
|
25
25
|
export const MAX_STAGING_DELETES_PER_RUN = 500;
|
|
26
|
+
// The most staged objects one abandoned-staging pass examines before it stops and saves its
|
|
27
|
+
// position. Kept objects (young, with a live row, unreadable) cost nothing against the delete cap, so
|
|
28
|
+
// this is what bounds a pass over a long kept stretch; two listing pages keep the pass well inside
|
|
29
|
+
// the sweep's timeout beside its other passes, and the next run resumes after the last one examined.
|
|
30
|
+
export const MAX_STAGING_EXAMINED_PER_RUN = 2 * STAGING_LIST_PAGE_SIZE;
|
|
26
31
|
// How many times the migration console's picture carry enqueues one source before reporting it as refused by the
|
|
27
32
|
// pipeline.
|
|
28
33
|
export const MAX_V1_PICTURE_CARRY_ATTEMPTS = 3;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.js","sourceRoot":"","sources":["../../src/constants/media.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,mGAAmG;AACnG,6CAA6C;AAE7C,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,CAAC;AAC5B,MAAM,OAAO,GAAG,EAAE,GAAG,SAAS,CAAC;AAE/B,iGAAiG;AACjG,yCAAyC;AACzC,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,+FAA+F;AAC/F,wFAAwF;AACxF,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,GAAG,SAAS,CAAC;AAExD,oGAAoG;AACpG,oEAAoE;AACpE,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,SAAS,CAAC;AAEzD,6FAA6F;AAC7F,4FAA4F;AAC5F,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,GAAG,OAAO,CAAC;AAErD,kGAAkG;AAClG,2BAA2B;AAC3B,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AACjD,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAC,CAAC;AACvD,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAC/C,MAAM,CAAC,MAAM,mCAAmC,GAAG,GAAG,CAAC;AACvD,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"media.js","sourceRoot":"","sources":["../../src/constants/media.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,mGAAmG;AACnG,6CAA6C;AAE7C,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,CAAC;AAC5B,MAAM,OAAO,GAAG,EAAE,GAAG,SAAS,CAAC;AAE/B,iGAAiG;AACjG,yCAAyC;AACzC,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,+FAA+F;AAC/F,wFAAwF;AACxF,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,GAAG,SAAS,CAAC;AAExD,oGAAoG;AACpG,oEAAoE;AACpE,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,SAAS,CAAC;AAEzD,6FAA6F;AAC7F,4FAA4F;AAC5F,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,GAAG,OAAO,CAAC;AAErD,kGAAkG;AAClG,2BAA2B;AAC3B,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AACjD,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAC,CAAC;AACvD,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAC/C,MAAM,CAAC,MAAM,mCAAmC,GAAG,GAAG,CAAC;AACvD,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAC/C,4FAA4F;AAC5F,sGAAsG;AACtG,mGAAmG;AACnG,qGAAqG;AACrG,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,GAAG,sBAAsB,CAAC;AAEvE,iHAAiH;AACjH,YAAY;AACZ,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,+FAA+F;AAC/F,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,CAAC","sourcesContent":["// Upload pipeline policy: the processing claim, the maintenance sweep's windows and bounds, and the\n// retry ceiling of the migration console's picture carry. The generic claim and lease machinery is\n// media-schemas'; the numbers are Q-Sports'.\n\nconst MINUTE_MS = 60 * 1000;\nconst HOUR_MS = 60 * MINUTE_MS;\n\n// Processing attempts a picture upload gets, the first included. A second attempt exists only to\n// recover a crashed or killed first one.\nexport const MEDIA_PROCESSING_MAX_ATTEMPTS = 2;\n\n// How long a processing claim owns its row before a redelivery may reclaim it. Longer than the\n// processing trigger's timeout, so a live attempt is never reclaimed from under itself.\nexport const MEDIA_PROCESSING_LEASE_MS = 10 * MINUTE_MS;\n\n// An upload still `pending` or `processing` this long after it was accepted, past its lease, has no\n// live attempt left driving it, and the maintenance sweep fails it.\nexport const STALE_PENDING_MEDIA_AGE_MS = 30 * MINUTE_MS;\n\n// A staged object this old with no `pending` or `processing` upload row is abandoned — never\n// accepted, consumed by a signing, or left by a finished upload — and the sweep deletes it.\nexport const ABANDONED_STAGING_AGE_MS = 24 * HOUR_MS;\n\n// The maintenance sweep's per-run bounds (BACKEND-112). Each pass stops at its bound and the next\n// scheduled run continues.\nexport const STALE_PENDING_MEDIA_PAGE_SIZE = 100;\nexport const MAX_STALE_PENDING_MEDIA_PAGES_PER_RUN = 5;\nexport const PICTURE_RETIREMENT_PAGE_SIZE = 50;\nexport const GALLERY_RETIREMENT_PICTURES_PER_RUN = 100;\nexport const STAGING_LIST_PAGE_SIZE = 1000;\nexport const MAX_STAGING_DELETES_PER_RUN = 500;\n// The most staged objects one abandoned-staging pass examines before it stops and saves its\n// position. Kept objects (young, with a live row, unreadable) cost nothing against the delete cap, so\n// this is what bounds a pass over a long kept stretch; two listing pages keep the pass well inside\n// the sweep's timeout beside its other passes, and the next run resumes after the last one examined.\nexport const MAX_STAGING_EXAMINED_PER_RUN = 2 * STAGING_LIST_PAGE_SIZE;\n\n// How many times the migration console's picture carry enqueues one source before reporting it as refused by the\n// pipeline.\nexport const MAX_V1_PICTURE_CARRY_ATTEMPTS = 3;\n\n// The longest staging path a callable accepts: `uploads/{origin}/{uid}/{uuid}` is far shorter.\nexport const MAX_STAGING_UPLOAD_PATH_LENGTH = 300;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sports.js","sourceRoot":"","sources":["../../src/constants/sports.ts"],"names":[],"mappings":"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","sourcesContent":["// Sport rule values that are persisted or validated on both sides of the boundary. What a sport\r\n// DOES with them — applying an event, recomputing a score — belongs to its adapter (SPORT-003).\r\n\r\nimport {\r\n BASKETBALL_ASSIST_EVENT_TYPE,\r\n BASKETBALL_BULK_EDIT_EVENT_TYPE,\r\n BASKETBALL_ONE_POINT_EVENT_TYPE,\r\n BASKETBALL_REBOUND_EVENT_TYPE,\r\n BASKETBALL_THREE_POINT_EVENT_TYPE,\r\n BASKETBALL_TIMEOUT_EVENT_TYPE,\r\n BASKETBALL_TWO_POINT_EVENT_TYPE,\r\n FOOTBALL_BULK_EDIT_EVENT_TYPE,\r\n FOOTBALL_ONE_POINT_EVENT_TYPE,\r\n FOOTBALL_SIX_POINT_EVENT_TYPE,\r\n FOOTBALL_TWO_POINT_EVENT_TYPE,\r\n} from '../types/sports.js';\r\nimport type { BasketballPlayerStatKey, BasketballStatEventType, FootballStatEventType } from '../types/sports.js';\r\nimport type {\r\n FinalizationNotReadyReason,\r\n GameRepairRefusal,\r\n StatEventRefusalCode,\r\n StatsIntegrityRefusal,\r\n} from '../types/stats.js';\r\n\r\n// Points a basketball stat event adds to its team's score. BULK_EDIT carries its own `value`.\r\nexport const BASKETBALL_POINTS_BY_EVENT_TYPE = {\r\n [BASKETBALL_ONE_POINT_EVENT_TYPE]: 1,\r\n [BASKETBALL_TWO_POINT_EVENT_TYPE]: 2,\r\n [BASKETBALL_THREE_POINT_EVENT_TYPE]: 3,\r\n [BASKETBALL_REBOUND_EVENT_TYPE]: 0,\r\n [BASKETBALL_ASSIST_EVENT_TYPE]: 0,\r\n [BASKETBALL_TIMEOUT_EVENT_TYPE]: 0,\r\n [BASKETBALL_BULK_EDIT_EVENT_TYPE]: 0,\r\n} as const satisfies Record<BasketballStatEventType, number>;\r\n\r\n// Basketball fantasy points (FP): each player counter times its weight. Every weight is a multiple\r\n// of one half, so FP summed across games equals FP of the summed counters exactly.\r\nexport const BASKETBALL_FANTASY_POINT_WEIGHTS = {\r\n points: 1,\r\n rebounds: 1.5,\r\n assists: 2,\r\n} as const satisfies Record<BasketballPlayerStatKey, number>;\r\n\r\n// A curling game is this many rounds; `roundScores` has exactly this many slots.\r\nexport const CURLING_ROUND_COUNT = 14;\r\n\r\n// A scored curling round is worth 1..MAX; a blank end is 0.\r\nexport const MAX_CURLING_ROUND_POINTS = 4;\r\n\r\n// The most events one scoring write may carry: each event is a document created in the write's one\r\n// transaction, and a Firestore transaction commits at most 500 writes.\r\nexport const MAX_STAT_EVENTS_PER_WRITE = 200;\r\n\r\n// The most lines and fields one Correct a game call may set; a game holds far fewer.\r\nexport const MAX_GAME_STATS_CORRECTION_TARGETS = 200;\r\n\r\n// The most destination changes one rebuild call lists in its answer; the audit events record all.\r\nexport const MAX_STATS_REPAIR_LISTED_CHANGES = 500;\r\n\r\n// The most findings one stats check keeps on its report; every finding is still counted by kind.\r\nexport const MAX_STATS_VALIDATION_DISCREPANCIES = 500;\r\n\r\n// The most events one page of a completed game's finalized record holds.\r\nexport const STAT_HISTORY_PAGE_SIZE = 1000;\r\n\r\n// Points a football stat event adds to its team's score. FOOTBALL_BULK_EDIT carries its own `value`.\r\nexport const FOOTBALL_POINTS_BY_EVENT_TYPE = {\r\n [FOOTBALL_SIX_POINT_EVENT_TYPE]: 6,\r\n [FOOTBALL_TWO_POINT_EVENT_TYPE]: 2,\r\n [FOOTBALL_ONE_POINT_EVENT_TYPE]: 1,\r\n [FOOTBALL_BULK_EDIT_EVENT_TYPE]: 0,\r\n} as const satisfies Record<FootballStatEventType, number>;\r\n\r\n// A game write's answer — a scoring event, a bulk-entry form, absence, the possession arrow, a ghost\r\n// added from the game — when the request names a team the game does not hold.\r\nexport const TEAM_NOT_IN_GAME_MESSAGE = 'That team is not playing in this game.';\r\n\r\n// A game write's answer — a bulk-entry row, absence, a memo — when the request names a person the\r\n// game's roster does not hold.\r\nexport const NOT_ON_GAME_ROSTER_MESSAGE = \"That player is not on this game's roster.\";\r\n\r\n// What the scorekeeper reads beside an event a scoring write refused.\r\nexport const STAT_EVENT_REFUSAL_COPY = {\r\n eventTypeNotInSport: \"That stat does not belong to this game's sport.\",\r\n teamNotInGame: TEAM_NOT_IN_GAME_MESSAGE,\r\n playerNotRostered: \"That player is not on this game's roster for that team.\",\r\n assisterNotRostered: \"The assisting player is not on this game's roster for that team.\",\r\n assistNotAllowed: 'Only a 2- or 3-point basket can be assisted, and never by the player who scored it.',\r\n playerNotAllowed: \"That stat is the team's; it cannot name a player.\",\r\n roundNotNext: 'That round is not the next one to record.',\r\n roundsComplete: 'Every round is already recorded.',\r\n bulkValueInvalid: 'That entry is not a real result: stats are whole numbers and never go below zero.',\r\n bulkStale: 'The numbers changed while you were editing. Check the flagged values and save again.',\r\n eventIdConflict: 'A different stat was already saved under this one. Discard it and enter it again.',\r\n voidTargetNotSportEvent: 'There is no recorded stat there to undo.',\r\n correctionNotAccepted: 'Corrections are made from Fix stats, not from the scoring screen.',\r\n undoBelowZero: 'Undoing that play would leave a stat below zero, because a later entry already lowered it.',\r\n} as const satisfies Record<StatEventRefusalCode, string>;\r\n\r\n// The operation every correction the game copy appends is recorded under, and the reason it carries.\r\n// The copy carries each recorded result exactly: where a game's recorded lines differ from what its\r\n// recorded plays replay to, one correction per field closes the difference, and these name it.\r\nexport const STATS_MIGRATION_OPERATION_ID = 'migration';\r\nexport const STATS_MIGRATION_CORRECTION_REASON =\r\n 'The recorded result differs from what its recorded plays add up to; this correction keeps the recorded result.';\r\n\r\n// What an admin reads when Fix stats refuses a game repair.\r\nexport const GAME_REPAIR_REFUSAL_COPY = {\r\n eventUnreadable: \"One of this game's recorded stats can no longer be read. Fix the event in the console, then repair the game.\",\r\n sourcesDisagree:\r\n \"This game's record, its stored numbers, and its recorded stats all disagree, so nothing says what was applied. Fix the game in the console first.\",\r\n scoreAmbiguous:\r\n \"The team's score was edited in two places to different values. Enter the score you want as a correction instead.\",\r\n fieldNotCorrectable:\r\n \"That number cannot be corrected for this sport. Restore the game from its recorded stats, or reopen it and score it again.\",\r\n lineNotRostered: \"That player is not on this game's roster.\",\r\n teamNotInGame: \"That team is not playing in this game.\",\r\n gameTooLarge: 'This repair is too large to save at once.',\r\n} as const satisfies Record<GameRepairRefusal, string>;\r\n\r\n// What the caller reads when a stats path refuses a game whose numbers changed outside the app.\r\nexport const STATS_INTEGRITY_REFUSAL_COPY = {\r\n statsOutOfBand:\r\n \"This game's stored numbers no longer match the stats recorded for it. An admin must reconcile the game in Fix stats first.\",\r\n finalRecordMissing:\r\n \"This finalized game's record of its stats is missing. An admin must repair the game in Fix stats first.\",\r\n aggregateBelowZero:\r\n 'A league, career, or hall-of-fame total holds less than this game added to it. An admin must rebuild the totals in Fix stats first.',\r\n} as const satisfies Record<StatsIntegrityRefusal, string>;\r\n\r\n// What the finish control shows while a game may not be finalized, and what finalize refuses with.\r\nexport const FINALIZATION_NOT_READY_COPY = {\r\n roundsIncomplete: 'Every round must be recorded before the game can be finalized.',\r\n} as const satisfies Record<FinalizationNotReadyReason, string>;\r\n\r\n// The hall of fame's minimum-games filter: each choice keeps the careers with at least that many\r\n// games played. None is chosen until the viewer picks one, so the hall of fame opens on everyone.\r\nexport const HALL_OF_FAME_MINIMUM_GAMES_CHOICES = [25, 50, 100] as const;\r\nexport type HallOfFameMinimumGames = (typeof HALL_OF_FAME_MINIMUM_GAMES_CHOICES)[number];\r\n"]}
|
|
1
|
+
{"version":3,"file":"sports.js","sourceRoot":"","sources":["../../src/constants/sports.ts"],"names":[],"mappings":"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","sourcesContent":["// Sport rule values that are persisted or validated on both sides of the boundary. What a sport\n// DOES with them — applying an event, recomputing a score — belongs to its adapter (SPORT-003).\n\nimport {\n BASKETBALL_ASSIST_EVENT_TYPE,\n BASKETBALL_BULK_EDIT_EVENT_TYPE,\n BASKETBALL_ONE_POINT_EVENT_TYPE,\n BASKETBALL_REBOUND_EVENT_TYPE,\n BASKETBALL_THREE_POINT_EVENT_TYPE,\n BASKETBALL_TIMEOUT_EVENT_TYPE,\n BASKETBALL_TWO_POINT_EVENT_TYPE,\n FOOTBALL_BULK_EDIT_EVENT_TYPE,\n FOOTBALL_ONE_POINT_EVENT_TYPE,\n FOOTBALL_SIX_POINT_EVENT_TYPE,\n FOOTBALL_TWO_POINT_EVENT_TYPE,\n} from '../types/sports.js';\nimport type { BasketballPlayerStatKey, BasketballStatEventType, FootballStatEventType } from '../types/sports.js';\nimport type {\n FinalizationNotReadyReason,\n GameRepairRefusal,\n StatEventRefusalCode,\n StatsIntegrityRefusal,\n} from '../types/stats.js';\n\n// Points a basketball stat event adds to its team's score. BULK_EDIT carries its own `value`.\nexport const BASKETBALL_POINTS_BY_EVENT_TYPE = {\n [BASKETBALL_ONE_POINT_EVENT_TYPE]: 1,\n [BASKETBALL_TWO_POINT_EVENT_TYPE]: 2,\n [BASKETBALL_THREE_POINT_EVENT_TYPE]: 3,\n [BASKETBALL_REBOUND_EVENT_TYPE]: 0,\n [BASKETBALL_ASSIST_EVENT_TYPE]: 0,\n [BASKETBALL_TIMEOUT_EVENT_TYPE]: 0,\n [BASKETBALL_BULK_EDIT_EVENT_TYPE]: 0,\n} as const satisfies Record<BasketballStatEventType, number>;\n\n// Basketball fantasy points (FP): each player counter times its weight. Every weight is a multiple\n// of one half, so FP summed across games equals FP of the summed counters exactly.\nexport const BASKETBALL_FANTASY_POINT_WEIGHTS = {\n points: 1,\n rebounds: 1.5,\n assists: 2,\n} as const satisfies Record<BasketballPlayerStatKey, number>;\n\n// A curling game is this many rounds; `roundScores` has exactly this many slots.\nexport const CURLING_ROUND_COUNT = 14;\n\n// A scored curling round is worth 1..MAX; a blank end is 0.\nexport const MAX_CURLING_ROUND_POINTS = 4;\n\n// The most events one scoring write may carry: each event is a document created in the write's one\n// transaction, and a Firestore transaction commits at most 500 writes.\nexport const MAX_STAT_EVENTS_PER_WRITE = 200;\n\n// The most lines and fields one Correct a game call may set; a game holds far fewer.\nexport const MAX_GAME_STATS_CORRECTION_TARGETS = 200;\n\n// The most destination changes one rebuild call lists in its answer; the audit events record all.\nexport const MAX_STATS_REPAIR_LISTED_CHANGES = 500;\n\n// The most findings one stats check keeps on its report; every finding is still counted by kind.\nexport const MAX_STATS_VALIDATION_DISCREPANCIES = 500;\n\n// The most events one page of a completed game's finalized record holds.\nexport const STAT_HISTORY_PAGE_SIZE = 1000;\n\n// Points a football stat event adds to its team's score. FOOTBALL_BULK_EDIT carries its own `value`.\nexport const FOOTBALL_POINTS_BY_EVENT_TYPE = {\n [FOOTBALL_SIX_POINT_EVENT_TYPE]: 6,\n [FOOTBALL_TWO_POINT_EVENT_TYPE]: 2,\n [FOOTBALL_ONE_POINT_EVENT_TYPE]: 1,\n [FOOTBALL_BULK_EDIT_EVENT_TYPE]: 0,\n} as const satisfies Record<FootballStatEventType, number>;\n\n// A game write's answer — a scoring event, a bulk-entry form, absence, the possession arrow, a ghost\n// added from the game — when the request names a team the game does not hold.\nexport const TEAM_NOT_IN_GAME_MESSAGE = 'That team is not playing in this game.';\n\n// A game write's answer — a bulk-entry row, absence, a memo — when the request names a person the\n// game's roster does not hold.\nexport const NOT_ON_GAME_ROSTER_MESSAGE = \"That player is not on this game's roster.\";\n\n// What the scorekeeper reads beside an event a scoring write refused.\nexport const STAT_EVENT_REFUSAL_COPY = {\n eventTypeNotInSport: \"That stat does not belong to this game's sport.\",\n teamNotInGame: TEAM_NOT_IN_GAME_MESSAGE,\n playerNotRostered: \"That player is not on this game's roster for that team.\",\n assisterNotRostered: \"The assisting player is not on this game's roster for that team.\",\n assistNotAllowed: 'Only a 2- or 3-point basket can be assisted, and never by the player who scored it.',\n playerNotAllowed: \"That stat is the team's; it cannot name a player.\",\n roundNotNext: 'That round is not the next one to record.',\n roundsComplete: 'Every round is already recorded.',\n bulkValueInvalid: 'That entry is not a real result: stats are whole numbers and never go below zero.',\n bulkStale: 'The numbers changed while you were editing. Check the flagged values and save again.',\n eventIdConflict: 'A different stat was already saved under this one. Discard it and enter it again.',\n voidTargetNotSportEvent: 'There is no recorded stat there to undo.',\n correctionNotAccepted: 'Corrections are made from Fix stats, not from the scoring screen.',\n undoBelowZero: 'Undoing that play would leave a stat below zero, because a later entry already lowered it.',\n} as const satisfies Record<StatEventRefusalCode, string>;\n\n// The operation every correction the game copy appends is recorded under, and the reason it carries.\n// The copy carries each recorded result exactly: where a game's recorded lines differ from what its\n// recorded plays replay to, one correction per field closes the difference, and these name it.\nexport const STATS_MIGRATION_OPERATION_ID = 'migration';\nexport const STATS_MIGRATION_CORRECTION_REASON =\n 'The recorded result differs from what its recorded plays add up to; this correction keeps the recorded result.';\n\n// What an admin reads when Fix stats refuses a game repair.\nexport const GAME_REPAIR_REFUSAL_COPY = {\n eventUnreadable: \"One of this game's recorded stats can no longer be read. Fix the event in the console, then repair the game.\",\n sourcesDisagree:\n \"This game's record, its stored numbers, and its recorded stats all disagree, so nothing says what was applied. Fix the game in the console first.\",\n scoreAmbiguous:\n \"The team's score was edited in two places to different values. Enter the score you want as a correction instead.\",\n fieldNotCorrectable:\n \"That number cannot be corrected for this sport. Restore the game from its recorded stats, or reopen it and score it again.\",\n lineNotRostered: \"That player is not on this game's roster.\",\n teamNotInGame: \"That team is not playing in this game.\",\n gameTooLarge: 'This repair is too large to save at once.',\n} as const satisfies Record<GameRepairRefusal, string>;\n\n// What the caller reads when a stats path refuses a game whose numbers changed outside the app.\nexport const STATS_INTEGRITY_REFUSAL_COPY = {\n statsOutOfBand:\n \"This game's stored numbers no longer match the stats recorded for it. An admin must reconcile the game in Fix stats first.\",\n finalRecordMissing:\n \"This finalized game's record of its stats is missing. An admin must repair the game in Fix stats first.\",\n aggregateBelowZero:\n 'A league, career, or hall-of-fame total holds less than this game added to it. An admin must rebuild the totals in Fix stats first.',\n} as const satisfies Record<StatsIntegrityRefusal, string>;\n\n// What the finish control shows while a game may not be finalized, and what finalize refuses with.\nexport const FINALIZATION_NOT_READY_COPY = {\n roundsIncomplete: 'Every round must be recorded before the game can be finalized.',\n} as const satisfies Record<FinalizationNotReadyReason, string>;\n\n// The hall of fame's minimum-games filter: each choice keeps the careers with at least that many\n// games played. None is chosen until the viewer picks one, so the hall of fame opens on everyone.\nexport const HALL_OF_FAME_MINIMUM_GAMES_CHOICES = [25, 50, 100] as const;\nexport type HallOfFameMinimumGames = (typeof HALL_OF_FAME_MINIMUM_GAMES_CHOICES)[number];\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-keys.js","sourceRoot":"","sources":["../../src/constants/storage-keys.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,mGAAmG;AACnG,mGAAmG;AAKnG;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC;AAEzC,wFAAwF;AACxF,MAAM,CAAC,MAAM,0BAA0B,GAAG,yBAAyB,CAAC;AAEpE,yEAAyE;AACzE,MAAM,CAAC,MAAM,2BAA2B,GAAG,gCAAgC,CAAC;AAE5E;;;GAGG;AACH,MAAM,CAAC,MAAM,qCAAqC,GAAG,oCAAoC,CAAC;AAE1F;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAErD;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,mCAAmC,CAAC;AAE3E,uGAAuG;AACvG,MAAM,CAAC,MAAM,mCAAmC,GAAG,kCAAkC,CAAC;AAEtF,kFAAkF;AAClF,MAAM,CAAC,MAAM,oCAAoC,GAAG,yCAAyC,CAAC;AAE9F,yGAAyG;AACzG,MAAM,CAAC,MAAM,mCAAmC,GAAG,2BAA2B,CAAC;AAE/E;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,SAA2B,EAAE,QAAkB;IACtF,OAAO,GAAG,mCAAmC,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC;AAC3E,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,MAAM,6BAA6B,GAAG,kCAAkC,CAAC;AAEhF,iGAAiG;AACjG,MAAM,CAAC,MAAM,6BAA6B,GAAG,qBAAqB,CAAC;AAEnE;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW,EAAE,MAAc;IAC7D,OAAO,GAAG,6BAA6B,IAAI,GAAG,IAAI,MAAM,EAAE,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,yBAAyB,CAAC","sourcesContent":["// Browser-storage keys, each declared once with the same-tab event its writer dispatches: a\
|
|
1
|
+
{"version":3,"file":"storage-keys.js","sourceRoot":"","sources":["../../src/constants/storage-keys.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,mGAAmG;AACnG,mGAAmG;AAKnG;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC;AAEzC,wFAAwF;AACxF,MAAM,CAAC,MAAM,0BAA0B,GAAG,yBAAyB,CAAC;AAEpE,yEAAyE;AACzE,MAAM,CAAC,MAAM,2BAA2B,GAAG,gCAAgC,CAAC;AAE5E;;;GAGG;AACH,MAAM,CAAC,MAAM,qCAAqC,GAAG,oCAAoC,CAAC;AAE1F;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAErD;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,mCAAmC,CAAC;AAE3E,uGAAuG;AACvG,MAAM,CAAC,MAAM,mCAAmC,GAAG,kCAAkC,CAAC;AAEtF,kFAAkF;AAClF,MAAM,CAAC,MAAM,oCAAoC,GAAG,yCAAyC,CAAC;AAE9F,yGAAyG;AACzG,MAAM,CAAC,MAAM,mCAAmC,GAAG,2BAA2B,CAAC;AAE/E;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,SAA2B,EAAE,QAAkB;IACtF,OAAO,GAAG,mCAAmC,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC;AAC3E,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,MAAM,6BAA6B,GAAG,kCAAkC,CAAC;AAEhF,iGAAiG;AACjG,MAAM,CAAC,MAAM,6BAA6B,GAAG,qBAAqB,CAAC;AAEnE;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW,EAAE,MAAc;IAC7D,OAAO,GAAG,6BAA6B,IAAI,GAAG,IAAI,MAAM,EAAE,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,yBAAyB,CAAC","sourcesContent":["// Browser-storage keys, each declared once with the same-tab event its writer dispatches: a\n// localStorage write fires the native `storage` event in every other tab but never in the tab that\n// wrote it. Every value is persisted on viewers' devices, so changing one forgets what they saved.\n\nimport type { ColumnCatalogKey } from '../sports/column-catalog.js';\nimport type { SportKey } from '../types/sports.js';\n\n/**\n * localStorage key holding the device's theme. It is `next-themes`' default key, the one viewers'\n * saved themes are stored under.\n */\nexport const THEME_STORAGE_KEY = 'theme';\n\n/** localStorage key: `'true'` when the viewer has turned motion down on this device. */\nexport const REDUCED_MOTION_STORAGE_KEY = 'q-sports-reduced-motion';\n\n/** Same-tab event dispatched when REDUCED_MOTION_STORAGE_KEY changes. */\nexport const REDUCED_MOTION_CHANGE_EVENT = 'q-sports-reduced-motion-change';\n\n/**\n * localStorage key holding the differences between this device's settings and the account's that\n * the viewer chose to keep, so the compare prompt does not ask about them again while they hold.\n */\nexport const VIEWER_SETTINGS_DISMISSAL_STORAGE_KEY = 'q-sports-viewer-settings-dismissed';\n\n/**\n * localStorage key holding the `_appConfig/app` version this device last loaded. Written only once\n * a load has confirmed it, so a release that never landed is retried next session.\n */\nexport const LS_VERSION_KEY = 'q-sports-app-version';\n\n/**\n * sessionStorage key naming the version the version gate last reloaded for. It is what tells the\n * load after that reload apart from a mismatch still to act on, so a stuck release cannot hold a\n * tab in a reload loop; a new tab starts without it and tries again.\n */\nexport const SS_RELOAD_ATTEMPTED_KEY = 'q-sports-version-reload-attempted';\n\n/** localStorage key: `'true'` while the admin sidebar is collapsed to its icon rail on this device. */\nexport const ADMIN_SIDEBAR_COLLAPSED_STORAGE_KEY = 'q-sports-admin-sidebar-collapsed';\n\n/** Same-tab event dispatched when ADMIN_SIDEBAR_COLLAPSED_STORAGE_KEY changes. */\nexport const ADMIN_SIDEBAR_COLLAPSED_CHANGE_EVENT = 'q-sports-admin-sidebar-collapsed-change';\n\n/** The prefix every stats table View-state key starts with; `statsTableViewStorageKey` adds the rest. */\nexport const STATS_TABLE_VIEW_STORAGE_KEY_PREFIX = 'q-sports-stats-table-view';\n\n/**\n * localStorage key holding one stats table's View state on this device — its preset or Custom layout,\n * its sort, and its switches — for one table type of one sport: `{prefix}:{tableType}:{sportKey}`.\n */\nexport function statsTableViewStorageKey(tableType: ColumnCatalogKey, sportKey: SportKey): string {\n return `${STATS_TABLE_VIEW_STORAGE_KEY_PREFIX}:${tableType}:${sportKey}`;\n}\n\n/** Same-tab event dispatched when any stats table View-state key changes. */\nexport const STATS_TABLE_VIEW_CHANGE_EVENT = 'q-sports-stats-table-view-change';\n\n/** The prefix every scorer's stat-queue key starts with; `statQueueStorageKey` adds the rest. */\nexport const STAT_QUEUE_STORAGE_KEY_PREFIX = 'q-sports-stat-queue';\n\n/**\n * localStorage key holding one scorer's unsent and refused stat events for one game on this device —\n * `{prefix}:{uid}:{gameId}` — so a reload loses nothing, and another account signed in on the same\n * browser never sends or sees them.\n */\nexport function statQueueStorageKey(uid: string, gameId: string): string {\n return `${STAT_QUEUE_STORAGE_KEY_PREFIX}:${uid}:${gameId}`;\n}\n\n/**\n * localStorage key, and the first-party cookie's name, holding this browser's analytics consent:\n * `'granted'` or `'denied'`; absent until the visitor chooses.\n */\nexport const COOKIE_CONSENT_STORAGE_KEY = 'q-sports-cookie-consent';\n"]}
|
|
@@ -141,6 +141,7 @@ export declare const NotificationArchiveAllJobSchema: z.ZodObject<{
|
|
|
141
141
|
}>;
|
|
142
142
|
revision: z.ZodNumber;
|
|
143
143
|
archived: z.ZodNumber;
|
|
144
|
+
notArchived: z.ZodOptional<z.ZodNumber>;
|
|
144
145
|
error: z.ZodNullable<z.ZodString>;
|
|
145
146
|
attemptCount: z.ZodNumber;
|
|
146
147
|
nextAttemptAt: z.ZodNumber;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-notifications.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/admin-notifications.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAIvE,eAAO,MAAM,2BAA2B;;;EAAuC,CAAC;AAIhF,eAAO,MAAM,2CAA2C;;;kBAE7C,CAAC;AACZ,MAAM,MAAM,qCAAqC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2CAA2C,CAAC,CAAC;AAEhH,eAAO,MAAM,iDAAiD;;;kBAEnD,CAAC;AACZ,MAAM,MAAM,2CAA2C,GAAG,CAAC,CAAC,KAAK,CAC/D,OAAO,iDAAiD,CACzD,CAAC;AAEF,eAAO,MAAM,mCAAmC;;;;;;;;;CAGgB,CAAC;AAEjE,MAAM,MAAM,+BAA+B,GAAG;KAC3C,CAAC,IAAI,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,mCAAmC,CAAC,CAAC,CAAC,CAAC,CAAC;CACvF,CAAC;AAEF,0DAA0D;AAC1D,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,qBAAqB,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAEnG;AAQD,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;iBAWmD,CAAC;AAC9F,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAIpF,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAazC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAEtF,eAAO,MAAM,iCAAiC;;;;iBAK5C,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAS5F,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BnC,CAAC;AACL,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAM9E,eAAO,MAAM,+BAA+B
|
|
1
|
+
{"version":3,"file":"admin-notifications.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/admin-notifications.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAIvE,eAAO,MAAM,2BAA2B;;;EAAuC,CAAC;AAIhF,eAAO,MAAM,2CAA2C;;;kBAE7C,CAAC;AACZ,MAAM,MAAM,qCAAqC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2CAA2C,CAAC,CAAC;AAEhH,eAAO,MAAM,iDAAiD;;;kBAEnD,CAAC;AACZ,MAAM,MAAM,2CAA2C,GAAG,CAAC,CAAC,KAAK,CAC/D,OAAO,iDAAiD,CACzD,CAAC;AAEF,eAAO,MAAM,mCAAmC;;;;;;;;;CAGgB,CAAC;AAEjE,MAAM,MAAM,+BAA+B,GAAG;KAC3C,CAAC,IAAI,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,mCAAmC,CAAC,CAAC,CAAC,CAAC,CAAC;CACvF,CAAC;AAEF,0DAA0D;AAC1D,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,qBAAqB,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAEnG;AAQD,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;iBAWmD,CAAC;AAC9F,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAIpF,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAazC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAEtF,eAAO,MAAM,iCAAiC;;;;iBAK5C,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAS5F,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BnC,CAAC;AACL,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAM9E,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;iBAuB1C,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC"}
|
|
@@ -119,6 +119,10 @@ export const NotificationArchiveAllJobSchema = z.object({
|
|
|
119
119
|
// Moves on every claim, so an overlapping run that claimed an older revision cannot settle the job.
|
|
120
120
|
revision: countSchema,
|
|
121
121
|
archived: countSchema,
|
|
122
|
+
// The cards the COMPLETING drain could not archive — each failed on its own and is still in the
|
|
123
|
+
// list. Set (never summed) when the job completes, because that drain walked the whole active set
|
|
124
|
+
// once. Optional, never defaulted: absent until a job completes with cards left behind, read as 0.
|
|
125
|
+
notArchived: countSchema.optional(),
|
|
122
126
|
error: z.string().nullable(),
|
|
123
127
|
attemptCount: countSchema,
|
|
124
128
|
nextAttemptAt: epochMsSchema,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-notifications.js","sourceRoot":"","sources":["../../src/doc-schemas/admin-notifications.ts"],"names":[],"mappings":"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","sourcesContent":["// The admin notification documents: the shared cards, their archived history, the delivery ledger\n// the owning callables write occurrences into, and the archive-all jobs. Every one is written only by\n// Cloud Functions.\n//\n// notification-core owns the generic card shape, so the card schema is composed from its\n// `NotificationDocSchema` and narrowed to Q-Sports' one shared category and its notification types.\n// The history, ledger, and job documents are written by notification-core's server helpers and by\n// the functions around them; their schemas are declared here because the package exports no schema\n// for them. A card, a history entry, and a ledger row each hold ids only, never a name (ARCH-103).\n//\n// `expireAt` is the one Firestore `Timestamp` any of them holds: a native-TTL policy honours only a\n// real Timestamp, and nothing reads the field for display or order (ARCH-105).\n\nimport { z } from 'zod';\nimport { NotificationDocSchema } from '@ttt-productions/notification-core';\nimport {\n ADMIN_NOTIFICATION_CATEGORY,\n ADMIN_NOTIFICATION_TYPE_KEYS,\n NOTIFICATION_ARCHIVE_ALL_JOB_STATE_KEYS,\n NOTIFICATION_DELIVERY_PAYLOAD_VERSION,\n NOTIFICATION_DELIVERY_SKIP_REASON_KEYS,\n NOTIFICATION_DELIVERY_STATE_KEYS,\n NOTIFICATION_MATERIALIZATION_CLASS_KEYS,\n SHARED_NOTIFICATION_AUDIENCE_SCOPE,\n} from '../types/notifications.js';\nimport type { AdminNotificationType } from '../types/notifications.js';\nimport { countSchema, epochMsSchema, leagueIdSchema, teamIdSchema, userIdSchema } from './atoms.js';\nimport { FirestoreTimestampSchema } from './firestore-primitives.js';\n\nexport const adminNotificationTypeSchema = z.enum(ADMIN_NOTIFICATION_TYPE_KEYS);\n\n// What each type's card and ledger row name, by id. The card's title, link, and every name it shows\n// are derived from these at read time.\nexport const LeagueTeamCreatedNotificationMetadataSchema = z\n .object({ leagueId: leagueIdSchema, teamId: teamIdSchema })\n .strict();\nexport type LeagueTeamCreatedNotificationMetadata = z.infer<typeof LeagueTeamCreatedNotificationMetadataSchema>;\n\nexport const LeagueFreeAgentSignedUpNotificationMetadataSchema = z\n .object({ leagueId: leagueIdSchema, userId: userIdSchema })\n .strict();\nexport type LeagueFreeAgentSignedUpNotificationMetadata = z.infer<\n typeof LeagueFreeAgentSignedUpNotificationMetadataSchema\n>;\n\nexport const ADMIN_NOTIFICATION_METADATA_SCHEMAS = {\n leagueTeamCreated: LeagueTeamCreatedNotificationMetadataSchema,\n leagueFreeAgentSignedUp: LeagueFreeAgentSignedUpNotificationMetadataSchema,\n} as const satisfies Record<AdminNotificationType, z.ZodTypeAny>;\n\nexport type AdminNotificationMetadataByType = {\n [T in AdminNotificationType]: z.infer<(typeof ADMIN_NOTIFICATION_METADATA_SCHEMAS)[T]>;\n};\n\n/** Whether `metadata` is the metadata `type` declares. */\nexport function isAdminNotificationMetadata(type: AdminNotificationType, metadata: unknown): boolean {\n return ADMIN_NOTIFICATION_METADATA_SCHEMAS[type].safeParse(metadata).success;\n}\n\nconst METADATA_MISMATCH = { message: \"The metadata is not the notification type's.\", path: ['metadata'] };\n\n// activeAdminNotifications/{notificationId} — one shared card, as notification-core stores it. The id\n// is notification-core's, hashed from the type and the aggregation key, and is not a field: a reader\n// is handed it beside the document. `seenAt` is the package's field: a shared card has no seen state,\n// so no admin marks it and it stays 0.\nexport const ActiveAdminNotificationSchema = NotificationDocSchema.omit({ id: true })\n .extend({\n type: adminNotificationTypeSchema,\n category: z.literal(ADMIN_NOTIFICATION_CATEGORY),\n targetUserId: z.null(),\n count: countSchema,\n latestActorIds: z.array(userIdSchema),\n seenAt: epochMsSchema,\n createdAt: epochMsSchema,\n updatedAt: epochMsSchema,\n })\n .refine((card) => isAdminNotificationMetadata(card.type, card.metadata), METADATA_MISMATCH);\nexport type ActiveAdminNotification = z.infer<typeof ActiveAdminNotificationSchema>;\n\n// adminNotificationHistory/{historyId} — an archived card: the card as it stood when archived, kept\n// whole under `archivedSnapshot`, with who archived it and the archive's replay facts.\nexport const AdminNotificationHistorySchema = z.object({\n archiveOccurrenceId: z.string().min(1),\n requestId: z.string().min(1),\n // The archive's replay key: the card and the generation the archiving admin saw.\n payloadHash: z.string().min(1),\n activeId: z.string().min(1),\n observedActivityGeneration: z.string().min(1),\n category: z.literal(ADMIN_NOTIFICATION_CATEGORY),\n audienceScope: z.literal(SHARED_NOTIFICATION_AUDIENCE_SCOPE),\n archivedSnapshot: ActiveAdminNotificationSchema,\n archivedAt: epochMsSchema,\n expireAt: FirestoreTimestampSchema,\n handledBy: userIdSchema,\n});\nexport type AdminNotificationHistory = z.infer<typeof AdminNotificationHistorySchema>;\n\nexport const NotificationDeliveryPayloadSchema = z.object({\n // Who did what the occurrence records; null for an occurrence with no acting account.\n actorId: userIdSchema.nullable(),\n metadata: z.record(z.string(), z.unknown()),\n occurrenceAt: epochMsSchema,\n});\nexport type NotificationDeliveryPayload = z.infer<typeof NotificationDeliveryPayloadSchema>;\n\n// notificationDeliveries/{deliveryId} — one occurrence: the queue row the worker materializes and the\n// record that it happened, in one document, so the occurrence and its delivery cannot come apart.\n// Written in the owning callable's own transaction. A queued or dead-lettered row never expires:\n// notification-core sets `expireAt` only when the row materializes or is skipped, and an admin's\n// replay of a dead-lettered row sets it back to null. A row is skipped only when it names a recipient\n// who may no longer receive, which no Q-Sports row does; the skip's fields are declared because the\n// package writes them.\nexport const NotificationDeliverySchema = z\n .object({\n deliveryId: z.string().min(1),\n state: z.enum(NOTIFICATION_DELIVERY_STATE_KEYS),\n notificationType: adminNotificationTypeSchema,\n eventId: z.string().min(1),\n // Every Q-Sports notification is shared, so no row names a recipient.\n recipientUid: z.null(),\n aggregationKey: z.string().min(1),\n strategy: z.literal('increment'),\n payload: NotificationDeliveryPayloadSchema,\n payloadVersion: z.literal(NOTIFICATION_DELIVERY_PAYLOAD_VERSION),\n materializationClass: z.enum(NOTIFICATION_MATERIALIZATION_CLASS_KEYS),\n createdAt: epochMsSchema,\n attemptCount: countSchema,\n nextAttemptAt: epochMsSchema,\n lastError: z.string().nullable(),\n materializedAt: epochMsSchema.nullable(),\n deadLetteredAt: epochMsSchema.nullable(),\n skipReason: z.enum(NOTIFICATION_DELIVERY_SKIP_REASON_KEYS).optional(),\n skippedAt: epochMsSchema.optional(),\n expireAt: FirestoreTimestampSchema.nullable().optional(),\n })\n .refine((row) => isAdminNotificationMetadata(row.notificationType, row.payload.metadata), {\n message: METADATA_MISMATCH.message,\n path: ['payload', 'metadata'],\n });\nexport type NotificationDelivery = z.infer<typeof NotificationDeliverySchema>;\n\n// notificationArchiveAllJobs/{jobId} — one admin's \"archive all\": the server drains every active card\n// in pages until none is left, whether or not that admin's browser is still open. Backend-only: the\n// admin learns its state through the status callable. A completed job expires; one that is still\n// running, stopped short, or failed never does.\nexport const NotificationArchiveAllJobSchema = z.object({\n jobId: z.string().min(1),\n // The admin who asked. Each card the job archives is recorded as archived by them; the event the\n // request wrote when the job was created carries the request's origin (BACKEND-211).\n userId: userIdSchema,\n category: z.literal(ADMIN_NOTIFICATION_CATEGORY),\n state: z.enum(NOTIFICATION_ARCHIVE_ALL_JOB_STATE_KEYS),\n // Moves on every claim, so an overlapping run that claimed an older revision cannot settle the job.\n revision: countSchema,\n archived: countSchema,\n error: z.string().nullable(),\n attemptCount: countSchema,\n nextAttemptAt: epochMsSchema,\n deadLettered: z.boolean(),\n createdAt: epochMsSchema,\n updatedAt: epochMsSchema,\n completedAt: epochMsSchema.nullable(),\n deadLetteredAt: epochMsSchema.nullable(),\n expireAt: FirestoreTimestampSchema.optional(),\n});\nexport type NotificationArchiveAllJob = z.infer<typeof NotificationArchiveAllJobSchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"admin-notifications.js","sourceRoot":"","sources":["../../src/doc-schemas/admin-notifications.ts"],"names":[],"mappings":"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","sourcesContent":["// The admin notification documents: the shared cards, their archived history, the delivery ledger\n// the owning callables write occurrences into, and the archive-all jobs. Every one is written only by\n// Cloud Functions.\n//\n// notification-core owns the generic card shape, so the card schema is composed from its\n// `NotificationDocSchema` and narrowed to Q-Sports' one shared category and its notification types.\n// The history, ledger, and job documents are written by notification-core's server helpers and by\n// the functions around them; their schemas are declared here because the package exports no schema\n// for them. A card, a history entry, and a ledger row each hold ids only, never a name (ARCH-103).\n//\n// `expireAt` is the one Firestore `Timestamp` any of them holds: a native-TTL policy honours only a\n// real Timestamp, and nothing reads the field for display or order (ARCH-105).\n\nimport { z } from 'zod';\nimport { NotificationDocSchema } from '@ttt-productions/notification-core';\nimport {\n ADMIN_NOTIFICATION_CATEGORY,\n ADMIN_NOTIFICATION_TYPE_KEYS,\n NOTIFICATION_ARCHIVE_ALL_JOB_STATE_KEYS,\n NOTIFICATION_DELIVERY_PAYLOAD_VERSION,\n NOTIFICATION_DELIVERY_SKIP_REASON_KEYS,\n NOTIFICATION_DELIVERY_STATE_KEYS,\n NOTIFICATION_MATERIALIZATION_CLASS_KEYS,\n SHARED_NOTIFICATION_AUDIENCE_SCOPE,\n} from '../types/notifications.js';\nimport type { AdminNotificationType } from '../types/notifications.js';\nimport { countSchema, epochMsSchema, leagueIdSchema, teamIdSchema, userIdSchema } from './atoms.js';\nimport { FirestoreTimestampSchema } from './firestore-primitives.js';\n\nexport const adminNotificationTypeSchema = z.enum(ADMIN_NOTIFICATION_TYPE_KEYS);\n\n// What each type's card and ledger row name, by id. The card's title, link, and every name it shows\n// are derived from these at read time.\nexport const LeagueTeamCreatedNotificationMetadataSchema = z\n .object({ leagueId: leagueIdSchema, teamId: teamIdSchema })\n .strict();\nexport type LeagueTeamCreatedNotificationMetadata = z.infer<typeof LeagueTeamCreatedNotificationMetadataSchema>;\n\nexport const LeagueFreeAgentSignedUpNotificationMetadataSchema = z\n .object({ leagueId: leagueIdSchema, userId: userIdSchema })\n .strict();\nexport type LeagueFreeAgentSignedUpNotificationMetadata = z.infer<\n typeof LeagueFreeAgentSignedUpNotificationMetadataSchema\n>;\n\nexport const ADMIN_NOTIFICATION_METADATA_SCHEMAS = {\n leagueTeamCreated: LeagueTeamCreatedNotificationMetadataSchema,\n leagueFreeAgentSignedUp: LeagueFreeAgentSignedUpNotificationMetadataSchema,\n} as const satisfies Record<AdminNotificationType, z.ZodTypeAny>;\n\nexport type AdminNotificationMetadataByType = {\n [T in AdminNotificationType]: z.infer<(typeof ADMIN_NOTIFICATION_METADATA_SCHEMAS)[T]>;\n};\n\n/** Whether `metadata` is the metadata `type` declares. */\nexport function isAdminNotificationMetadata(type: AdminNotificationType, metadata: unknown): boolean {\n return ADMIN_NOTIFICATION_METADATA_SCHEMAS[type].safeParse(metadata).success;\n}\n\nconst METADATA_MISMATCH = { message: \"The metadata is not the notification type's.\", path: ['metadata'] };\n\n// activeAdminNotifications/{notificationId} — one shared card, as notification-core stores it. The id\n// is notification-core's, hashed from the type and the aggregation key, and is not a field: a reader\n// is handed it beside the document. `seenAt` is the package's field: a shared card has no seen state,\n// so no admin marks it and it stays 0.\nexport const ActiveAdminNotificationSchema = NotificationDocSchema.omit({ id: true })\n .extend({\n type: adminNotificationTypeSchema,\n category: z.literal(ADMIN_NOTIFICATION_CATEGORY),\n targetUserId: z.null(),\n count: countSchema,\n latestActorIds: z.array(userIdSchema),\n seenAt: epochMsSchema,\n createdAt: epochMsSchema,\n updatedAt: epochMsSchema,\n })\n .refine((card) => isAdminNotificationMetadata(card.type, card.metadata), METADATA_MISMATCH);\nexport type ActiveAdminNotification = z.infer<typeof ActiveAdminNotificationSchema>;\n\n// adminNotificationHistory/{historyId} — an archived card: the card as it stood when archived, kept\n// whole under `archivedSnapshot`, with who archived it and the archive's replay facts.\nexport const AdminNotificationHistorySchema = z.object({\n archiveOccurrenceId: z.string().min(1),\n requestId: z.string().min(1),\n // The archive's replay key: the card and the generation the archiving admin saw.\n payloadHash: z.string().min(1),\n activeId: z.string().min(1),\n observedActivityGeneration: z.string().min(1),\n category: z.literal(ADMIN_NOTIFICATION_CATEGORY),\n audienceScope: z.literal(SHARED_NOTIFICATION_AUDIENCE_SCOPE),\n archivedSnapshot: ActiveAdminNotificationSchema,\n archivedAt: epochMsSchema,\n expireAt: FirestoreTimestampSchema,\n handledBy: userIdSchema,\n});\nexport type AdminNotificationHistory = z.infer<typeof AdminNotificationHistorySchema>;\n\nexport const NotificationDeliveryPayloadSchema = z.object({\n // Who did what the occurrence records; null for an occurrence with no acting account.\n actorId: userIdSchema.nullable(),\n metadata: z.record(z.string(), z.unknown()),\n occurrenceAt: epochMsSchema,\n});\nexport type NotificationDeliveryPayload = z.infer<typeof NotificationDeliveryPayloadSchema>;\n\n// notificationDeliveries/{deliveryId} — one occurrence: the queue row the worker materializes and the\n// record that it happened, in one document, so the occurrence and its delivery cannot come apart.\n// Written in the owning callable's own transaction. A queued or dead-lettered row never expires:\n// notification-core sets `expireAt` only when the row materializes or is skipped, and an admin's\n// replay of a dead-lettered row sets it back to null. A row is skipped only when it names a recipient\n// who may no longer receive, which no Q-Sports row does; the skip's fields are declared because the\n// package writes them.\nexport const NotificationDeliverySchema = z\n .object({\n deliveryId: z.string().min(1),\n state: z.enum(NOTIFICATION_DELIVERY_STATE_KEYS),\n notificationType: adminNotificationTypeSchema,\n eventId: z.string().min(1),\n // Every Q-Sports notification is shared, so no row names a recipient.\n recipientUid: z.null(),\n aggregationKey: z.string().min(1),\n strategy: z.literal('increment'),\n payload: NotificationDeliveryPayloadSchema,\n payloadVersion: z.literal(NOTIFICATION_DELIVERY_PAYLOAD_VERSION),\n materializationClass: z.enum(NOTIFICATION_MATERIALIZATION_CLASS_KEYS),\n createdAt: epochMsSchema,\n attemptCount: countSchema,\n nextAttemptAt: epochMsSchema,\n lastError: z.string().nullable(),\n materializedAt: epochMsSchema.nullable(),\n deadLetteredAt: epochMsSchema.nullable(),\n skipReason: z.enum(NOTIFICATION_DELIVERY_SKIP_REASON_KEYS).optional(),\n skippedAt: epochMsSchema.optional(),\n expireAt: FirestoreTimestampSchema.nullable().optional(),\n })\n .refine((row) => isAdminNotificationMetadata(row.notificationType, row.payload.metadata), {\n message: METADATA_MISMATCH.message,\n path: ['payload', 'metadata'],\n });\nexport type NotificationDelivery = z.infer<typeof NotificationDeliverySchema>;\n\n// notificationArchiveAllJobs/{jobId} — one admin's \"archive all\": the server drains every active card\n// in pages until none is left, whether or not that admin's browser is still open. Backend-only: the\n// admin learns its state through the status callable. A completed job expires; one that is still\n// running, stopped short, or failed never does.\nexport const NotificationArchiveAllJobSchema = z.object({\n jobId: z.string().min(1),\n // The admin who asked. Each card the job archives is recorded as archived by them; the event the\n // request wrote when the job was created carries the request's origin (BACKEND-211).\n userId: userIdSchema,\n category: z.literal(ADMIN_NOTIFICATION_CATEGORY),\n state: z.enum(NOTIFICATION_ARCHIVE_ALL_JOB_STATE_KEYS),\n // Moves on every claim, so an overlapping run that claimed an older revision cannot settle the job.\n revision: countSchema,\n archived: countSchema,\n // The cards the COMPLETING drain could not archive — each failed on its own and is still in the\n // list. Set (never summed) when the job completes, because that drain walked the whole active set\n // once. Optional, never defaulted: absent until a job completes with cards left behind, read as 0.\n notArchived: countSchema.optional(),\n error: z.string().nullable(),\n attemptCount: countSchema,\n nextAttemptAt: epochMsSchema,\n deadLettered: z.boolean(),\n createdAt: epochMsSchema,\n updatedAt: epochMsSchema,\n completedAt: epochMsSchema.nullable(),\n deadLetteredAt: epochMsSchema.nullable(),\n expireAt: FirestoreTimestampSchema.optional(),\n});\nexport type NotificationArchiveAllJob = z.infer<typeof NotificationArchiveAllJobSchema>;\n"]}
|
|
@@ -251,8 +251,10 @@ export declare const statsBeaconActionSchema: z.ZodEnum<{
|
|
|
251
251
|
link: "link";
|
|
252
252
|
}>;
|
|
253
253
|
export declare const statsDiscrepancyKindSchema: z.ZodEnum<{
|
|
254
|
+
gameUnreadable: "gameUnreadable";
|
|
254
255
|
invalidEvent: "invalidEvent";
|
|
255
256
|
eventSequenceMismatch: "eventSequenceMismatch";
|
|
257
|
+
eventSequenceGap: "eventSequenceGap";
|
|
256
258
|
rollupMismatch: "rollupMismatch";
|
|
257
259
|
scoreMirrorMismatch: "scoreMirrorMismatch";
|
|
258
260
|
unrosteredStatLine: "unrosteredStatLine";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atoms.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/atoms.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"atoms.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/atoms.ts"],"names":[],"mappings":"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"}
|
|
@@ -82,6 +82,7 @@ export declare const auditEventTypeSchema: z.ZodEnum<{
|
|
|
82
82
|
"adminNotification.archiveAllRequested": "adminNotification.archiveAllRequested";
|
|
83
83
|
"system.manualIntervention": "system.manualIntervention";
|
|
84
84
|
"migrationAction.pageRun": "migrationAction.pageRun";
|
|
85
|
+
"migrationAction.writesCommitted": "migrationAction.writesCommitted";
|
|
85
86
|
"migrationAction.controlRecorded": "migrationAction.controlRecorded";
|
|
86
87
|
"migrationAction.checkpointRecorded": "migrationAction.checkpointRecorded";
|
|
87
88
|
"migrationConsole.cutoverRecorded": "migrationConsole.cutoverRecorded";
|
|
@@ -195,6 +196,7 @@ export declare const AuditEventSchema: z.ZodObject<{
|
|
|
195
196
|
"adminNotification.archiveAllRequested": "adminNotification.archiveAllRequested";
|
|
196
197
|
"system.manualIntervention": "system.manualIntervention";
|
|
197
198
|
"migrationAction.pageRun": "migrationAction.pageRun";
|
|
199
|
+
"migrationAction.writesCommitted": "migrationAction.writesCommitted";
|
|
198
200
|
"migrationAction.controlRecorded": "migrationAction.controlRecorded";
|
|
199
201
|
"migrationAction.checkpointRecorded": "migrationAction.checkpointRecorded";
|
|
200
202
|
"migrationConsole.cutoverRecorded": "migrationConsole.cutoverRecorded";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-event.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/audit-event.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,oBAAoB
|
|
1
|
+
{"version":3,"file":"audit-event.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/audit-event.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAgC,CAAC;AAElE,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;iCAY3B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;iBAG5B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAe3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalogs.js","sourceRoot":"","sources":["../../src/doc-schemas/catalogs.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,sDAAsD;AAEtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClG,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,oGAAoG;AACpG,kCAAkC;AAClC,MAAM,CAAC,MAAM,aAAa,GAAG,uBAAuB,CAAC;AAErD,8EAA8E;AAC9E,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC,uBAAuB,CAAC,CAAC;AAExE,mGAAmG;AACnG,qGAAqG;AACrG,sGAAsG;AACtG,EAAE;AACF,gGAAgG;AAChG,kGAAkG;AAClG,gFAAgF;AAChF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,YAAY,CAAC;IAClD,IAAI,EAAE,eAAe;IACrB,cAAc,EAAE,eAAe,CAAC,QAAQ,EAAE;IAC1C,WAAW,EAAE,WAAW;IACxB,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC","sourcesContent":["// The award catalog. Each award is its own document, keeping the id granted awards already\
|
|
1
|
+
{"version":3,"file":"catalogs.js","sourceRoot":"","sources":["../../src/doc-schemas/catalogs.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,sDAAsD;AAEtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClG,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,oGAAoG;AACpG,kCAAkC;AAClC,MAAM,CAAC,MAAM,aAAa,GAAG,uBAAuB,CAAC;AAErD,8EAA8E;AAC9E,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC,uBAAuB,CAAC,CAAC;AAExE,mGAAmG;AACnG,qGAAqG;AACrG,sGAAsG;AACtG,EAAE;AACF,gGAAgG;AAChG,kGAAkG;AAClG,gFAAgF;AAChF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,YAAY,CAAC;IAClD,IAAI,EAAE,eAAe;IACrB,cAAc,EAAE,eAAe,CAAC,QAAQ,EAAE;IAC1C,WAAW,EAAE,WAAW;IACxB,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC","sourcesContent":["// The award catalog. Each award is its own document, keeping the id granted awards already\n// reference. The venue catalog is ./game-location.ts.\n\nimport { z } from 'zod';\nimport { AWARD_NAME_INPUT_FORMAT } from '../input-formats/index.js';\nimport { countSchema, documentIdSegmentSchema, epochMsSchema, textFieldSchema } from './atoms.js';\nimport { pictureIdSchema } from './gallery.js';\n\n// An award's id, which every grant names and so never changes: an award created by its badge upload\n// takes that upload's staging id.\nexport const awardIdSchema = documentIdSegmentSchema;\n\n// An award's name, as the catalog stores it and the creating upload sends it.\nexport const awardNameSchema = textFieldSchema(AWARD_NAME_INPUT_FORMAT);\n\n// `awardDefinitions/{awardId}` — one award in the catalog. It is created by the publication of its\n// first badge, so an award created that way always has one; an award with no badge yet gets one from\n// the next badge upload for it. A badge is replaced only by a newer upload, never removed on its own.\n//\n// `holderCount` is how many accounts hold the award now. Every grant and revoke moves it in the\n// transaction that writes the grant, so a deletion — refused while anyone holds the award — and a\n// concurrent grant conflict on this document instead of racing past each other.\nexport const AwardDefinitionSchema = z.strictObject({\n name: awardNameSchema,\n badgePictureId: pictureIdSchema.optional(),\n holderCount: countSchema,\n createdAt: epochMsSchema,\n updatedAt: epochMsSchema,\n});\nexport type AwardDefinition = z.infer<typeof AwardDefinitionSchema>;\n"]}
|
|
@@ -20,6 +20,7 @@ export declare const GalleryPictureSchema: z.ZodObject<{
|
|
|
20
20
|
}>;
|
|
21
21
|
ownerId: z.ZodString;
|
|
22
22
|
position: z.ZodString;
|
|
23
|
+
sourceIndex: z.ZodOptional<z.ZodNumber>;
|
|
23
24
|
createdAt: z.ZodNumber;
|
|
24
25
|
}, z.core.$strip>;
|
|
25
26
|
export type GalleryPicture = z.infer<typeof GalleryPictureSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gallery.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/gallery.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,sBAAsB;;;;;;EAAkC,CAAC;AACtE,eAAO,MAAM,sBAAsB;;;;EAAkC,CAAC;AAGtE,eAAO,MAAM,eAAe,aAAkB,CAAC;AAE/C,eAAO,MAAM,oBAAoB
|
|
1
|
+
{"version":3,"file":"gallery.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/gallery.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,sBAAsB;;;;;;EAAkC,CAAC;AACtE,eAAO,MAAM,sBAAsB;;;;EAAkC,CAAC;AAGtE,eAAO,MAAM,eAAe,aAAkB,CAAC;AAE/C,eAAO,MAAM,oBAAoB;;;;;;;;;;iBAW/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,oBAAoB;;;;iBAW7B,CAAC;AACL,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
|
|
@@ -19,6 +19,9 @@ export const GalleryPictureSchema = z.object({
|
|
|
19
19
|
// A fractional sort key: a move rewrites only the moved picture's key, strictly between its new
|
|
20
20
|
// neighbours, and a gallery's first page is read ordered by it.
|
|
21
21
|
position: z.string().min(1),
|
|
22
|
+
// Set only on a picture the migration carried from V1: its position in the V1 source list, which
|
|
23
|
+
// places a later-finishing carried picture among its carried neighbours in V1's order.
|
|
24
|
+
sourceIndex: countSchema.optional(),
|
|
22
25
|
createdAt: epochMsSchema,
|
|
23
26
|
});
|
|
24
27
|
export const GallerySummarySchema = z
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gallery.js","sourceRoot":"","sources":["../../src/doc-schemas/gallery.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,iGAAiG;AACjG,gGAAgG;AAChG,4FAA4F;AAC5F,gGAAgG;AAChG,+FAA+F;AAE/F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;AACtE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;AAEtE,6EAA6E;AAC7E,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC;AAE/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,SAAS,EAAE,sBAAsB;IACjC,sFAAsF;IACtF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,gGAAgG;IAChG,gEAAgE;IAChE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC;KAClC,MAAM,CAAC;IACN,+EAA+E;IAC/E,KAAK,EAAE,WAAW;IAClB,0EAA0E;IAC1E,iBAAiB,EAAE,eAAe,CAAC,QAAQ,EAAE;IAC7C,SAAS,EAAE,aAAa;CACzB,CAAC;KACD,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,KAAK,SAAS,CAAC,EAAE;IACtF,OAAO,EAAE,uEAAuE;IAChF,IAAI,EAAE,CAAC,mBAAmB,CAAC;CAC5B,CAAC,CAAC","sourcesContent":["// Picture galleries — the league's, each team's, and the landing page's.\n//\n// Each picture in a gallery is its own `galleryPictures/{pictureId}` document, publicly readable\n// and written only by the picture core. The owner document carries its gallery's summary as its\n// optional `pictures` field: a card or a header reads the featured picture off the owner it\n// already holds, and `count` tells a display how many pictures there are without a count query.\n// An absent `pictures` field is an empty gallery, so no copy action or create core writes one.\n\nimport { z } from 'zod';\nimport { GALLERY_OWNER_KIND_KEYS, PICTURE_OWNER_KIND_KEYS } from '../types/picture-owners.js';\nimport { countSchema, epochMsSchema, stagingIdSchema } from './atoms.js';\n\nexport const pictureOwnerKindSchema = z.enum(PICTURE_OWNER_KIND_KEYS);\nexport const galleryOwnerKindSchema = z.enum(GALLERY_OWNER_KIND_KEYS);\n\n// A picture id is its upload's staging id; every stored size lives under it.\nexport const pictureIdSchema = stagingIdSchema;\n\nexport const GalleryPictureSchema = z.object({\n ownerKind: galleryOwnerKindSchema,\n // The league or team id; the landing page's gallery uses `SPECIAL_DOCS.LANDING_PAGE`.\n ownerId: z.string().min(1),\n // A fractional sort key: a move rewrites only the moved picture's key, strictly between its new\n // neighbours, and a gallery's first page is read ordered by it.\n position: z.string().min(1),\n createdAt: epochMsSchema,\n});\nexport type GalleryPicture = z.infer<typeof GalleryPictureSchema>;\n\nexport const GallerySummarySchema = z\n .object({\n // Exact: every gallery change rewrites the summary inside its own transaction.\n count: countSchema,\n // Always one of the owner's pictures, so no reader needs a fallback rule.\n featuredPictureId: pictureIdSchema.optional(),\n updatedAt: epochMsSchema,\n })\n .refine((summary) => (summary.count > 0) === (summary.featuredPictureId !== undefined), {\n message: 'featuredPictureId is present exactly when the gallery holds a picture',\n path: ['featuredPictureId'],\n });\nexport type GallerySummary = z.infer<typeof GallerySummarySchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"gallery.js","sourceRoot":"","sources":["../../src/doc-schemas/gallery.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,iGAAiG;AACjG,gGAAgG;AAChG,4FAA4F;AAC5F,gGAAgG;AAChG,+FAA+F;AAE/F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;AACtE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;AAEtE,6EAA6E;AAC7E,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC;AAE/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,SAAS,EAAE,sBAAsB;IACjC,sFAAsF;IACtF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,gGAAgG;IAChG,gEAAgE;IAChE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,iGAAiG;IACjG,uFAAuF;IACvF,WAAW,EAAE,WAAW,CAAC,QAAQ,EAAE;IACnC,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC;KAClC,MAAM,CAAC;IACN,+EAA+E;IAC/E,KAAK,EAAE,WAAW;IAClB,0EAA0E;IAC1E,iBAAiB,EAAE,eAAe,CAAC,QAAQ,EAAE;IAC7C,SAAS,EAAE,aAAa;CACzB,CAAC;KACD,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,KAAK,SAAS,CAAC,EAAE;IACtF,OAAO,EAAE,uEAAuE;IAChF,IAAI,EAAE,CAAC,mBAAmB,CAAC;CAC5B,CAAC,CAAC","sourcesContent":["// Picture galleries — the league's, each team's, and the landing page's.\n//\n// Each picture in a gallery is its own `galleryPictures/{pictureId}` document, publicly readable\n// and written only by the picture core. The owner document carries its gallery's summary as its\n// optional `pictures` field: a card or a header reads the featured picture off the owner it\n// already holds, and `count` tells a display how many pictures there are without a count query.\n// An absent `pictures` field is an empty gallery, so no copy action or create core writes one.\n\nimport { z } from 'zod';\nimport { GALLERY_OWNER_KIND_KEYS, PICTURE_OWNER_KIND_KEYS } from '../types/picture-owners.js';\nimport { countSchema, epochMsSchema, stagingIdSchema } from './atoms.js';\n\nexport const pictureOwnerKindSchema = z.enum(PICTURE_OWNER_KIND_KEYS);\nexport const galleryOwnerKindSchema = z.enum(GALLERY_OWNER_KIND_KEYS);\n\n// A picture id is its upload's staging id; every stored size lives under it.\nexport const pictureIdSchema = stagingIdSchema;\n\nexport const GalleryPictureSchema = z.object({\n ownerKind: galleryOwnerKindSchema,\n // The league or team id; the landing page's gallery uses `SPECIAL_DOCS.LANDING_PAGE`.\n ownerId: z.string().min(1),\n // A fractional sort key: a move rewrites only the moved picture's key, strictly between its new\n // neighbours, and a gallery's first page is read ordered by it.\n position: z.string().min(1),\n // Set only on a picture the migration carried from V1: its position in the V1 source list, which\n // places a later-finishing carried picture among its carried neighbours in V1's order.\n sourceIndex: countSchema.optional(),\n createdAt: epochMsSchema,\n});\nexport type GalleryPicture = z.infer<typeof GalleryPictureSchema>;\n\nexport const GallerySummarySchema = z\n .object({\n // Exact: every gallery change rewrites the summary inside its own transaction.\n count: countSchema,\n // Always one of the owner's pictures, so no reader needs a fallback rule.\n featuredPictureId: pictureIdSchema.optional(),\n updatedAt: epochMsSchema,\n })\n .refine((summary) => (summary.count > 0) === (summary.featuredPictureId !== undefined), {\n message: 'featuredPictureId is present exactly when the gallery holds a picture',\n path: ['featuredPictureId'],\n });\nexport type GallerySummary = z.infer<typeof GallerySummarySchema>;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game-location.js","sourceRoot":"","sources":["../../src/doc-schemas/game-location.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,iGAAiG;AACjG,oBAAoB;AAEpB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAE5D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,6CAA6C;IAC7C,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACjC,sDAAsD;IACtD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAClC,8FAA8F;IAC9F,6CAA6C;IAC7C,SAAS,EAAE,eAAe,CAAC,QAAQ,EAAE;IACrC,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC","sourcesContent":["// `gameLocations/{gameLocationId}` — one venue games are played at. Games name it by id\
|
|
1
|
+
{"version":3,"file":"game-location.js","sourceRoot":"","sources":["../../src/doc-schemas/game-location.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,iGAAiG;AACjG,oBAAoB;AAEpB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAE5D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,6CAA6C;IAC7C,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACjC,sDAAsD;IACtD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAClC,8FAA8F;IAC9F,6CAA6C;IAC7C,SAAS,EAAE,eAAe,CAAC,QAAQ,EAAE;IACrC,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC","sourcesContent":["// `gameLocations/{gameLocationId}` — one venue games are played at. Games name it by id\n// (`gameLocationId`) beside their own free-text label, so a game still reads correctly after its\n// venue is deleted.\n\nimport { z } from 'zod';\nimport { documentIdSegmentSchema, epochMsSchema } from './atoms.js';\nimport { pictureIdSchema } from './gallery.js';\n\nexport const gameLocationIdSchema = documentIdSegmentSchema;\n\nexport const GameLocationSchema = z.object({\n name: z.string().min(1),\n streetAddress: z.string(),\n // Courts, sheets, or rooms within the venue.\n subLocations: z.array(z.string()),\n // Directions for players; absent when there are none.\n memo: z.string().min(1).optional(),\n // The venue's picture. Only the picture pipeline writes it (ARCH-001); the location callables\n // write the fields above and never this one.\n pictureId: pictureIdSchema.optional(),\n createdAt: epochMsSchema,\n updatedAt: epochMsSchema,\n});\nexport type GameLocation = z.infer<typeof GameLocationSchema>;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game-stats.js","sourceRoot":"","sources":["../../src/doc-schemas/game-stats.ts"],"names":[],"mappings":"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","sourcesContent":["// The game tier of the stats model: the stat event documents, and the rollup the game document\r\n// carries (SPORT-001, SPORT-101, SPORT-102).\r\n//\r\n// Each stat event is its own document, `sportGames/{gameId}/gameStatEvents/{eventId}`, and the\r\n// event documents are the source of truth: at every commit the game's `stats` equals their replay,\r\n// in `sequence` order, from the sport's empty stats. The store is append-only — an undo appends a\r\n// `STAT_VOID` and a correction a `STAT_CORRECTION`; no event is ever edited.\r\n//\r\n// An event names people by id; names resolve from `publicUsers` at read time (ARCH-103, SPORT-104).\r\n// `displayNameSnapshot` and `assistedByDisplayNameSnapshot` are carried only by copied events, as\r\n// the audit record of the name the stat was entered under — never read as identity.\r\n\r\nimport { z } from 'zod';\r\nimport { CURLING_ROUND_COUNT, MAX_CURLING_ROUND_POINTS } from '../constants/sports.js';\r\nimport { buildGameRosterPlayerId } from '../ids/compound-ids.js';\r\nimport { buildStatCorrectionId, buildStatVoidId } from '../ids/stat-event-ids.js';\r\nimport {\r\n BASKETBALL_ASSISTABLE_SHOT_EVENT_TYPE_KEYS,\r\n BASKETBALL_BULK_EDIT_EVENT_TYPE,\r\n BASKETBALL_ONE_POINT_EVENT_TYPE,\r\n BASKETBALL_PLAYER_STAT_KEYS,\r\n BASKETBALL_PLAYER_TALLY_EVENT_TYPE_KEYS,\r\n BASKETBALL_TEAM_STAT_KEYS,\r\n BASKETBALL_TIMEOUT_EVENT_TYPE,\r\n CURLING_ROUND_BLANK_EVENT_TYPE,\r\n CURLING_ROUND_SCORE_EVENT_TYPE,\r\n CURLING_TEAM_STAT_KEYS,\r\n FOOTBALL_BULK_EDIT_EVENT_TYPE,\r\n FOOTBALL_SCORE_EVENT_TYPE_KEYS,\r\n FOOTBALL_TEAM_STAT_KEYS,\r\n} from '../types/sports.js';\r\nimport type {\r\n BasketballStatEventType,\r\n CurlingStatEventType,\r\n FootballStatEventType,\r\n StatCounterKey,\r\n} from '../types/sports.js';\r\nimport {\r\n STAT_CORRECTION_EVENT_TYPE,\r\n STAT_CORRECTION_SOURCE_KEYS,\r\n STAT_EVENT_AUTHORITY_KEYS,\r\n STAT_VOID_EVENT_TYPE,\r\n} from '../types/stats.js';\r\nimport { CAPTAIN_TEAM_ROLES } from '../types/unions.js';\r\nimport {\r\n basketballBulkStatKeySchema,\r\n countSchema,\r\n epochMsSchema,\r\n gameRosterPlayerIdSchema,\r\n repairReasonSchema,\r\n statCounterKeySchema,\r\n statEventIdSchema,\r\n statsOperationIdSchema,\r\n teamIdSchema,\r\n userIdSchema,\r\n} from './atoms.js';\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Lines — one per team of the game, one per roster entry holding a non-zero player line\r\n// ---------------------------------------------------------------------------------------------\r\n\r\n// A line's counters: one field per key of the sport's declared stat-key set (SPORT-007), so a key\r\n// added to the set is a field of every line built from it.\r\nfunction counterShape<K extends StatCounterKey>(keys: readonly K[]): Record<K, typeof countSchema> {\r\n return Object.fromEntries(keys.map((key) => [key, countSchema])) as Record<K, typeof countSchema>;\r\n}\r\n\r\nexport const BasketballTeamStatsSchema = z.strictObject(counterShape(BASKETBALL_TEAM_STAT_KEYS));\r\nexport type BasketballTeamStats = z.infer<typeof BasketballTeamStatsSchema>;\r\n\r\n// `fantasyPoints` is `basketballFantasyPoints` of the line's own counters, on every basketball\r\n// player line — this game line and the totals lines built from it — stored so every table and\r\n// aggregate reads it rather than deriving it. FP is linear in the counters, so a totals line's FP\r\n// equals the sum of its games' FP.\r\nexport const BasketballPlayerStatsSchema = z.strictObject({\r\n ...counterShape(BASKETBALL_PLAYER_STAT_KEYS),\r\n fantasyPoints: z.number().nonnegative(),\r\n});\r\nexport type BasketballPlayerStats = z.infer<typeof BasketballPlayerStatsSchema>;\r\n\r\n// `roundScores[n]` is end n + 1: `null` until the end is recorded, `0` on both teams for a blank end.\r\n// `score` is the sum of the recorded ends.\r\nexport const CurlingTeamStatsSchema = z.strictObject({\r\n ...counterShape(CURLING_TEAM_STAT_KEYS),\r\n roundScores: z\r\n .array(z.number().int().min(0).max(MAX_CURLING_ROUND_POINTS).nullable())\r\n .length(CURLING_ROUND_COUNT),\r\n});\r\nexport type CurlingTeamStats = z.infer<typeof CurlingTeamStatsSchema>;\r\n\r\nexport const FootballTeamStatsSchema = z.strictObject(counterShape(FOOTBALL_TEAM_STAT_KEYS));\r\nexport type FootballTeamStats = z.infer<typeof FootballTeamStatsSchema>;\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// The payload — exactly two keys for every sport (SPORT-001)\r\n// ---------------------------------------------------------------------------------------------\r\n\r\n// The one declaration of the game `stats` payload. Each sport's is built through it from that\r\n// sport's game lines in `SPORT_LINE_SCHEMAS`, as `SPORT_GAME_STATS_SCHEMAS`. `playerStats` is keyed\r\n// by roster entry, never by person, so a person on both teams of a game holds a line on each side. A\r\n// sport with no player lines passes `z.never()`, so its map stays empty.\r\nexport function gameStatsSchema<TeamLine extends z.ZodType, PlayerLine extends z.ZodType>(\r\n teamLine: TeamLine,\r\n playerLine: PlayerLine,\r\n) {\r\n return z.strictObject({\r\n teamStats: z.record(teamIdSchema, teamLine),\r\n playerStats: z.record(gameRosterPlayerIdSchema, playerLine),\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Events\r\n// ---------------------------------------------------------------------------------------------\r\n\r\n// Every event: its id, its place in the replay, and when it was entered. The recorder facts are\r\n// derived by the writing core, never taken from the payload (ARCH-106); a copied event has none.\r\nconst statEventBase = {\r\n eventId: statEventIdSchema,\r\n sequence: z.number().int().positive(),\r\n recordedAt: epochMsSchema,\r\n acceptedAt: epochMsSchema.optional(),\r\n recordedByUserId: userIdSchema.optional(),\r\n recordedByAuthority: z.enum(STAT_EVENT_AUTHORITY_KEYS).optional(),\r\n // Only for the two team roles: the team whose authority the event was recorded under.\r\n recordedByTeamId: teamIdSchema.optional(),\r\n};\r\n\r\n// A player-attributed event names the roster entry `{teamId}_{playerUserId}` whose line it changes.\r\nconst playerEventFields = {\r\n teamId: teamIdSchema,\r\n playerUserId: userIdSchema,\r\n displayNameSnapshot: z.string().optional(),\r\n};\r\n\r\n// Basketball\r\n\r\nexport const BasketballOnePointEventSchema = z.strictObject({\r\n ...statEventBase,\r\n ...playerEventFields,\r\n type: z.literal(BASKETBALL_ONE_POINT_EVENT_TYPE),\r\n});\r\n\r\n// An assisted shot names its assister on the same event, which credits both players.\r\nexport const BasketballAssistableShotEventSchema = z\r\n .strictObject({\r\n ...statEventBase,\r\n ...playerEventFields,\r\n type: z.enum(BASKETBALL_ASSISTABLE_SHOT_EVENT_TYPE_KEYS),\r\n assistedByUserId: userIdSchema.optional(),\r\n assistedByDisplayNameSnapshot: z.string().optional(),\r\n })\r\n .refine(\r\n (event) => event.assistedByDisplayNameSnapshot === undefined || event.assistedByUserId !== undefined,\r\n 'An assister snapshot needs the assister.',\r\n );\r\n\r\nexport const BasketballPlayerTallyEventSchema = z.strictObject({\r\n ...statEventBase,\r\n ...playerEventFields,\r\n type: z.enum(BASKETBALL_PLAYER_TALLY_EVENT_TYPE_KEYS),\r\n});\r\n\r\nexport const BasketballTimeoutEventSchema = z.strictObject({\r\n ...statEventBase,\r\n teamId: teamIdSchema,\r\n type: z.literal(BASKETBALL_TIMEOUT_EVENT_TYPE),\r\n});\r\n\r\n// A scorer's edit: `value` is the signed change to `stat`, entered against `previousValue`, the\r\n// value the form showed. A copied bulk edit has no `previousValue`; nothing validates one again.\r\nexport const BasketballBulkEditEventSchema = z.strictObject({\r\n ...statEventBase,\r\n ...playerEventFields,\r\n type: z.literal(BASKETBALL_BULK_EDIT_EVENT_TYPE),\r\n stat: basketballBulkStatKeySchema,\r\n value: z.number().int(),\r\n previousValue: countSchema.optional(),\r\n});\r\n\r\n// Curling — an event names the end it records; it names no player.\r\n\r\nconst curlingRoundNumberSchema = z.number().int().min(1).max(CURLING_ROUND_COUNT);\r\n\r\nexport const CurlingRoundScoreEventSchema = z.strictObject({\r\n ...statEventBase,\r\n type: z.literal(CURLING_ROUND_SCORE_EVENT_TYPE),\r\n teamId: teamIdSchema,\r\n roundNumber: curlingRoundNumberSchema,\r\n points: z.number().int().min(1).max(MAX_CURLING_ROUND_POINTS),\r\n});\r\n\r\nexport const CurlingBlankEndEventSchema = z.strictObject({\r\n ...statEventBase,\r\n type: z.literal(CURLING_ROUND_BLANK_EVENT_TYPE),\r\n roundNumber: curlingRoundNumberSchema,\r\n});\r\n\r\n// Football — team-attributed only.\r\n\r\nexport const FootballScoreEventSchema = z.strictObject({\r\n ...statEventBase,\r\n type: z.enum(FOOTBALL_SCORE_EVENT_TYPE_KEYS),\r\n teamId: teamIdSchema,\r\n});\r\n\r\nexport const FootballBulkEditEventSchema = z.strictObject({\r\n ...statEventBase,\r\n type: z.literal(FOOTBALL_BULK_EDIT_EVENT_TYPE),\r\n teamId: teamIdSchema,\r\n value: z.number().int(),\r\n previousValue: countSchema,\r\n});\r\n\r\n// The store-level events, members of every sport's union.\r\n\r\n// Undoes exactly the event it targets. Its id is derived from the target, so a target has at most\r\n// one void and a second undo of the same event is the same document.\r\nexport const StatVoidEventSchema = z\r\n .strictObject({\r\n ...statEventBase,\r\n type: z.literal(STAT_VOID_EVENT_TYPE),\r\n targetEventId: statEventIdSchema,\r\n })\r\n .refine((event) => event.eventId === buildStatVoidId(event.targetEventId), {\r\n message: 'A void is stored at the id its target derives.',\r\n path: ['eventId'],\r\n });\r\n\r\n// Adds `value` to one correctable field of one line — the player line `{teamId}_{playerUserId}`\r\n// when it names a player, the team line of `teamId` when it does not. It never cascades: a player\r\n// correction does not move the team's score.\r\nexport const StatCorrectionEventSchema = z\r\n .strictObject({\r\n ...statEventBase,\r\n type: z.literal(STAT_CORRECTION_EVENT_TYPE),\r\n teamId: teamIdSchema,\r\n playerUserId: userIdSchema.optional(),\r\n stat: statCounterKeySchema,\r\n value: z.number().int(),\r\n correctionSource: z.enum(STAT_CORRECTION_SOURCE_KEYS),\r\n operationId: statsOperationIdSchema,\r\n reason: repairReasonSchema,\r\n // The ghost a link re-keyed this correction's player line from. The id was derived from the\r\n // ghost's line when the correction was written, and a document id never changes.\r\n rekeyedFromGhostUserId: userIdSchema.optional(),\r\n })\r\n .refine(\r\n (event) =>\r\n event.eventId ===\r\n buildStatCorrectionId(\r\n event.operationId,\r\n event.playerUserId === undefined\r\n ? event.teamId\r\n : buildGameRosterPlayerId(event.teamId, event.rekeyedFromGhostUserId ?? event.playerUserId),\r\n event.stat,\r\n ),\r\n { message: 'A correction is stored at the id its operation, line, and field derive.', path: ['eventId'] },\r\n );\r\n\r\n// Recorder facts are all present or all absent, and a team is named exactly when the authority is a\r\n// team role.\r\nfunction recorderFactsAgree(event: {\r\n acceptedAt?: number;\r\n recordedByUserId?: string;\r\n recordedByAuthority?: (typeof STAT_EVENT_AUTHORITY_KEYS)[number];\r\n recordedByTeamId?: string;\r\n}): boolean {\r\n const facts = [event.acceptedAt, event.recordedByUserId, event.recordedByAuthority];\r\n const present = facts.filter((fact) => fact !== undefined).length;\r\n if (present !== 0 && present !== facts.length) return false;\r\n const teamAuthority = (CAPTAIN_TEAM_ROLES as readonly string[]).includes(event.recordedByAuthority ?? '');\r\n return teamAuthority === (event.recordedByTeamId !== undefined);\r\n}\r\n\r\n// A name snapshot is the audit record a copied event keeps of the name its stat was entered under.\r\n// Only the writing core stamps recorder facts, and it writes ids only, so an event carrying both a\r\n// snapshot and a recorder fact is refused (ARCH-103, SPORT-104).\r\nfunction snapshotsOnlyOnCopiedEvents(event: {\r\n acceptedAt?: number;\r\n recordedByUserId?: string;\r\n recordedByAuthority?: string;\r\n recordedByTeamId?: string;\r\n displayNameSnapshot?: string;\r\n assistedByDisplayNameSnapshot?: string;\r\n}): boolean {\r\n const snapshot = event.displayNameSnapshot !== undefined || event.assistedByDisplayNameSnapshot !== undefined;\r\n const recorded = [event.acceptedAt, event.recordedByUserId, event.recordedByAuthority, event.recordedByTeamId].some(\r\n (fact) => fact !== undefined,\r\n );\r\n return !(snapshot && recorded);\r\n}\r\n\r\n// Event types are disjoint across sports, so `type` alone discriminates the whole union.\r\nexport const GameStatEventSchema = z\r\n .discriminatedUnion('type', [\r\n BasketballOnePointEventSchema,\r\n BasketballAssistableShotEventSchema,\r\n BasketballPlayerTallyEventSchema,\r\n BasketballTimeoutEventSchema,\r\n BasketballBulkEditEventSchema,\r\n CurlingRoundScoreEventSchema,\r\n CurlingBlankEndEventSchema,\r\n FootballScoreEventSchema,\r\n FootballBulkEditEventSchema,\r\n StatVoidEventSchema,\r\n StatCorrectionEventSchema,\r\n ])\r\n .refine(recorderFactsAgree, 'Recorder facts are all present, or all absent, with a team only for a team role.')\r\n .refine(snapshotsOnlyOnCopiedEvents, 'A name snapshot belongs to a copied event, which carries no recorder facts.');\r\nexport type GameStatEvent = z.infer<typeof GameStatEventSchema>;\r\nexport type GameStatEventType = GameStatEvent['type'];\r\n\r\nexport type BasketballStatEvent = Extract<GameStatEvent, { type: BasketballStatEventType }>;\r\nexport type CurlingRoundScoreEvent = z.infer<typeof CurlingRoundScoreEventSchema>;\r\nexport type CurlingBlankEndEvent = z.infer<typeof CurlingBlankEndEventSchema>;\r\nexport type CurlingStatEvent = Extract<GameStatEvent, { type: CurlingStatEventType }>;\r\nexport type FootballStatEvent = Extract<GameStatEvent, { type: FootballStatEventType }>;\r\nexport type StatVoidEvent = z.infer<typeof StatVoidEventSchema>;\r\nexport type StatCorrectionEvent = z.infer<typeof StatCorrectionEventSchema>;\r\n"]}
|
|
1
|
+
{"version":3,"file":"game-stats.js","sourceRoot":"","sources":["../../src/doc-schemas/game-stats.ts"],"names":[],"mappings":"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","sourcesContent":["// The game tier of the stats model: the stat event documents, and the rollup the game document\n// carries (SPORT-001, SPORT-101, SPORT-102).\n//\n// Each stat event is its own document, `sportGames/{gameId}/gameStatEvents/{eventId}`, and the\n// event documents are the source of truth: at every commit the game's `stats` equals their replay,\n// in `sequence` order, from the sport's empty stats. The store is append-only — an undo appends a\n// `STAT_VOID` and a correction a `STAT_CORRECTION`; no event is ever edited.\n//\n// An event names people by id; names resolve from `publicUsers` at read time (ARCH-103, SPORT-104).\n// `displayNameSnapshot` and `assistedByDisplayNameSnapshot` are carried only by copied events, as\n// the audit record of the name the stat was entered under — never read as identity.\n\nimport { z } from 'zod';\nimport { CURLING_ROUND_COUNT, MAX_CURLING_ROUND_POINTS } from '../constants/sports.js';\nimport { buildGameRosterPlayerId } from '../ids/compound-ids.js';\nimport { buildStatCorrectionId, buildStatVoidId } from '../ids/stat-event-ids.js';\nimport {\n BASKETBALL_ASSISTABLE_SHOT_EVENT_TYPE_KEYS,\n BASKETBALL_BULK_EDIT_EVENT_TYPE,\n BASKETBALL_ONE_POINT_EVENT_TYPE,\n BASKETBALL_PLAYER_STAT_KEYS,\n BASKETBALL_PLAYER_TALLY_EVENT_TYPE_KEYS,\n BASKETBALL_TEAM_STAT_KEYS,\n BASKETBALL_TIMEOUT_EVENT_TYPE,\n CURLING_ROUND_BLANK_EVENT_TYPE,\n CURLING_ROUND_SCORE_EVENT_TYPE,\n CURLING_TEAM_STAT_KEYS,\n FOOTBALL_BULK_EDIT_EVENT_TYPE,\n FOOTBALL_SCORE_EVENT_TYPE_KEYS,\n FOOTBALL_TEAM_STAT_KEYS,\n} from '../types/sports.js';\nimport type {\n BasketballStatEventType,\n CurlingStatEventType,\n FootballStatEventType,\n StatCounterKey,\n} from '../types/sports.js';\nimport {\n STAT_CORRECTION_EVENT_TYPE,\n STAT_CORRECTION_SOURCE_KEYS,\n STAT_EVENT_AUTHORITY_KEYS,\n STAT_VOID_EVENT_TYPE,\n} from '../types/stats.js';\nimport { CAPTAIN_TEAM_ROLES } from '../types/unions.js';\nimport {\n basketballBulkStatKeySchema,\n countSchema,\n epochMsSchema,\n gameRosterPlayerIdSchema,\n repairReasonSchema,\n statCounterKeySchema,\n statEventIdSchema,\n statsOperationIdSchema,\n teamIdSchema,\n userIdSchema,\n} from './atoms.js';\n\n// ---------------------------------------------------------------------------------------------\n// Lines — one per team of the game, one per roster entry holding a non-zero player line\n// ---------------------------------------------------------------------------------------------\n\n// A line's counters: one field per key of the sport's declared stat-key set (SPORT-007), so a key\n// added to the set is a field of every line built from it.\nfunction counterShape<K extends StatCounterKey>(keys: readonly K[]): Record<K, typeof countSchema> {\n return Object.fromEntries(keys.map((key) => [key, countSchema])) as Record<K, typeof countSchema>;\n}\n\nexport const BasketballTeamStatsSchema = z.strictObject(counterShape(BASKETBALL_TEAM_STAT_KEYS));\nexport type BasketballTeamStats = z.infer<typeof BasketballTeamStatsSchema>;\n\n// `fantasyPoints` is `basketballFantasyPoints` of the line's own counters, on every basketball\n// player line — this game line and the totals lines built from it — stored so every table and\n// aggregate reads it rather than deriving it. FP is linear in the counters, so a totals line's FP\n// equals the sum of its games' FP.\nexport const BasketballPlayerStatsSchema = z.strictObject({\n ...counterShape(BASKETBALL_PLAYER_STAT_KEYS),\n fantasyPoints: z.number().nonnegative(),\n});\nexport type BasketballPlayerStats = z.infer<typeof BasketballPlayerStatsSchema>;\n\n// `roundScores[n]` is end n + 1: `null` until the end is recorded, `0` on both teams for a blank end.\n// `score` is the sum of the recorded ends.\nexport const CurlingTeamStatsSchema = z.strictObject({\n ...counterShape(CURLING_TEAM_STAT_KEYS),\n roundScores: z\n .array(z.number().int().min(0).max(MAX_CURLING_ROUND_POINTS).nullable())\n .length(CURLING_ROUND_COUNT),\n});\nexport type CurlingTeamStats = z.infer<typeof CurlingTeamStatsSchema>;\n\nexport const FootballTeamStatsSchema = z.strictObject(counterShape(FOOTBALL_TEAM_STAT_KEYS));\nexport type FootballTeamStats = z.infer<typeof FootballTeamStatsSchema>;\n\n// ---------------------------------------------------------------------------------------------\n// The payload — exactly two keys for every sport (SPORT-001)\n// ---------------------------------------------------------------------------------------------\n\n// The one declaration of the game `stats` payload. Each sport's is built through it from that\n// sport's game lines in `SPORT_LINE_SCHEMAS`, as `SPORT_GAME_STATS_SCHEMAS`. `playerStats` is keyed\n// by roster entry, never by person, so a person on both teams of a game holds a line on each side. A\n// sport with no player lines passes `z.never()`, so its map stays empty.\nexport function gameStatsSchema<TeamLine extends z.ZodType, PlayerLine extends z.ZodType>(\n teamLine: TeamLine,\n playerLine: PlayerLine,\n) {\n return z.strictObject({\n teamStats: z.record(teamIdSchema, teamLine),\n playerStats: z.record(gameRosterPlayerIdSchema, playerLine),\n });\n}\n\n// ---------------------------------------------------------------------------------------------\n// Events\n// ---------------------------------------------------------------------------------------------\n\n// Every event: its id, its place in the replay, and when it was entered. The recorder facts are\n// derived by the writing core, never taken from the payload (ARCH-106); a copied event has none.\nconst statEventBase = {\n eventId: statEventIdSchema,\n sequence: z.number().int().positive(),\n recordedAt: epochMsSchema,\n acceptedAt: epochMsSchema.optional(),\n recordedByUserId: userIdSchema.optional(),\n recordedByAuthority: z.enum(STAT_EVENT_AUTHORITY_KEYS).optional(),\n // Only for the two team roles: the team whose authority the event was recorded under.\n recordedByTeamId: teamIdSchema.optional(),\n};\n\n// A player-attributed event names the roster entry `{teamId}_{playerUserId}` whose line it changes.\nconst playerEventFields = {\n teamId: teamIdSchema,\n playerUserId: userIdSchema,\n displayNameSnapshot: z.string().optional(),\n};\n\n// Basketball\n\nexport const BasketballOnePointEventSchema = z.strictObject({\n ...statEventBase,\n ...playerEventFields,\n type: z.literal(BASKETBALL_ONE_POINT_EVENT_TYPE),\n});\n\n// An assisted shot names its assister on the same event, which credits both players.\nexport const BasketballAssistableShotEventSchema = z\n .strictObject({\n ...statEventBase,\n ...playerEventFields,\n type: z.enum(BASKETBALL_ASSISTABLE_SHOT_EVENT_TYPE_KEYS),\n assistedByUserId: userIdSchema.optional(),\n assistedByDisplayNameSnapshot: z.string().optional(),\n })\n .refine(\n (event) => event.assistedByDisplayNameSnapshot === undefined || event.assistedByUserId !== undefined,\n 'An assister snapshot needs the assister.',\n );\n\nexport const BasketballPlayerTallyEventSchema = z.strictObject({\n ...statEventBase,\n ...playerEventFields,\n type: z.enum(BASKETBALL_PLAYER_TALLY_EVENT_TYPE_KEYS),\n});\n\nexport const BasketballTimeoutEventSchema = z.strictObject({\n ...statEventBase,\n teamId: teamIdSchema,\n type: z.literal(BASKETBALL_TIMEOUT_EVENT_TYPE),\n});\n\n// A scorer's edit: `value` is the signed change to `stat`, entered against `previousValue`, the\n// value the form showed. A copied bulk edit has no `previousValue`; nothing validates one again.\nexport const BasketballBulkEditEventSchema = z.strictObject({\n ...statEventBase,\n ...playerEventFields,\n type: z.literal(BASKETBALL_BULK_EDIT_EVENT_TYPE),\n stat: basketballBulkStatKeySchema,\n value: z.number().int(),\n previousValue: countSchema.optional(),\n});\n\n// Curling — an event names the end it records; it names no player.\n\nconst curlingRoundNumberSchema = z.number().int().min(1).max(CURLING_ROUND_COUNT);\n\nexport const CurlingRoundScoreEventSchema = z.strictObject({\n ...statEventBase,\n type: z.literal(CURLING_ROUND_SCORE_EVENT_TYPE),\n teamId: teamIdSchema,\n roundNumber: curlingRoundNumberSchema,\n points: z.number().int().min(1).max(MAX_CURLING_ROUND_POINTS),\n});\n\nexport const CurlingBlankEndEventSchema = z.strictObject({\n ...statEventBase,\n type: z.literal(CURLING_ROUND_BLANK_EVENT_TYPE),\n roundNumber: curlingRoundNumberSchema,\n});\n\n// Football — team-attributed only.\n\nexport const FootballScoreEventSchema = z.strictObject({\n ...statEventBase,\n type: z.enum(FOOTBALL_SCORE_EVENT_TYPE_KEYS),\n teamId: teamIdSchema,\n});\n\nexport const FootballBulkEditEventSchema = z.strictObject({\n ...statEventBase,\n type: z.literal(FOOTBALL_BULK_EDIT_EVENT_TYPE),\n teamId: teamIdSchema,\n value: z.number().int(),\n previousValue: countSchema,\n});\n\n// The store-level events, members of every sport's union.\n\n// Undoes exactly the event it targets. Its id is derived from the target, so a target has at most\n// one void and a second undo of the same event is the same document.\nexport const StatVoidEventSchema = z\n .strictObject({\n ...statEventBase,\n type: z.literal(STAT_VOID_EVENT_TYPE),\n targetEventId: statEventIdSchema,\n })\n .refine((event) => event.eventId === buildStatVoidId(event.targetEventId), {\n message: 'A void is stored at the id its target derives.',\n path: ['eventId'],\n });\n\n// Adds `value` to one correctable field of one line — the player line `{teamId}_{playerUserId}`\n// when it names a player, the team line of `teamId` when it does not. It never cascades: a player\n// correction does not move the team's score.\nexport const StatCorrectionEventSchema = z\n .strictObject({\n ...statEventBase,\n type: z.literal(STAT_CORRECTION_EVENT_TYPE),\n teamId: teamIdSchema,\n playerUserId: userIdSchema.optional(),\n stat: statCounterKeySchema,\n value: z.number().int(),\n correctionSource: z.enum(STAT_CORRECTION_SOURCE_KEYS),\n operationId: statsOperationIdSchema,\n reason: repairReasonSchema,\n // The ghost a link re-keyed this correction's player line from. The id was derived from the\n // ghost's line when the correction was written, and a document id never changes.\n rekeyedFromGhostUserId: userIdSchema.optional(),\n })\n .refine(\n (event) =>\n event.eventId ===\n buildStatCorrectionId(\n event.operationId,\n event.playerUserId === undefined\n ? event.teamId\n : buildGameRosterPlayerId(event.teamId, event.rekeyedFromGhostUserId ?? event.playerUserId),\n event.stat,\n ),\n { message: 'A correction is stored at the id its operation, line, and field derive.', path: ['eventId'] },\n );\n\n// Recorder facts are all present or all absent, and a team is named exactly when the authority is a\n// team role.\nfunction recorderFactsAgree(event: {\n acceptedAt?: number;\n recordedByUserId?: string;\n recordedByAuthority?: (typeof STAT_EVENT_AUTHORITY_KEYS)[number];\n recordedByTeamId?: string;\n}): boolean {\n const facts = [event.acceptedAt, event.recordedByUserId, event.recordedByAuthority];\n const present = facts.filter((fact) => fact !== undefined).length;\n if (present !== 0 && present !== facts.length) return false;\n const teamAuthority = (CAPTAIN_TEAM_ROLES as readonly string[]).includes(event.recordedByAuthority ?? '');\n return teamAuthority === (event.recordedByTeamId !== undefined);\n}\n\n// A name snapshot is the audit record a copied event keeps of the name its stat was entered under.\n// Only the writing core stamps recorder facts, and it writes ids only, so an event carrying both a\n// snapshot and a recorder fact is refused (ARCH-103, SPORT-104).\nfunction snapshotsOnlyOnCopiedEvents(event: {\n acceptedAt?: number;\n recordedByUserId?: string;\n recordedByAuthority?: string;\n recordedByTeamId?: string;\n displayNameSnapshot?: string;\n assistedByDisplayNameSnapshot?: string;\n}): boolean {\n const snapshot = event.displayNameSnapshot !== undefined || event.assistedByDisplayNameSnapshot !== undefined;\n const recorded = [event.acceptedAt, event.recordedByUserId, event.recordedByAuthority, event.recordedByTeamId].some(\n (fact) => fact !== undefined,\n );\n return !(snapshot && recorded);\n}\n\n// Event types are disjoint across sports, so `type` alone discriminates the whole union.\nexport const GameStatEventSchema = z\n .discriminatedUnion('type', [\n BasketballOnePointEventSchema,\n BasketballAssistableShotEventSchema,\n BasketballPlayerTallyEventSchema,\n BasketballTimeoutEventSchema,\n BasketballBulkEditEventSchema,\n CurlingRoundScoreEventSchema,\n CurlingBlankEndEventSchema,\n FootballScoreEventSchema,\n FootballBulkEditEventSchema,\n StatVoidEventSchema,\n StatCorrectionEventSchema,\n ])\n .refine(recorderFactsAgree, 'Recorder facts are all present, or all absent, with a team only for a team role.')\n .refine(snapshotsOnlyOnCopiedEvents, 'A name snapshot belongs to a copied event, which carries no recorder facts.');\nexport type GameStatEvent = z.infer<typeof GameStatEventSchema>;\nexport type GameStatEventType = GameStatEvent['type'];\n\nexport type BasketballStatEvent = Extract<GameStatEvent, { type: BasketballStatEventType }>;\nexport type CurlingRoundScoreEvent = z.infer<typeof CurlingRoundScoreEventSchema>;\nexport type CurlingBlankEndEvent = z.infer<typeof CurlingBlankEndEventSchema>;\nexport type CurlingStatEvent = Extract<GameStatEvent, { type: CurlingStatEventType }>;\nexport type FootballStatEvent = Extract<GameStatEvent, { type: FootballStatEventType }>;\nexport type StatVoidEvent = z.infer<typeof StatVoidEventSchema>;\nexport type StatCorrectionEvent = z.infer<typeof StatCorrectionEventSchema>;\n"]}
|