@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.
Files changed (178) hide show
  1. package/dist/constants/business.d.ts +12 -0
  2. package/dist/constants/business.d.ts.map +1 -1
  3. package/dist/constants/business.js +24 -0
  4. package/dist/constants/business.js.map +1 -1
  5. package/dist/constants/media.d.ts +1 -0
  6. package/dist/constants/media.d.ts.map +1 -1
  7. package/dist/constants/media.js +5 -0
  8. package/dist/constants/media.js.map +1 -1
  9. package/dist/constants/sports.js.map +1 -1
  10. package/dist/constants/storage-keys.js.map +1 -1
  11. package/dist/doc-schemas/admin-notifications.d.ts +1 -0
  12. package/dist/doc-schemas/admin-notifications.d.ts.map +1 -1
  13. package/dist/doc-schemas/admin-notifications.js +4 -0
  14. package/dist/doc-schemas/admin-notifications.js.map +1 -1
  15. package/dist/doc-schemas/atoms.d.ts +2 -0
  16. package/dist/doc-schemas/atoms.d.ts.map +1 -1
  17. package/dist/doc-schemas/audit-event.d.ts +2 -0
  18. package/dist/doc-schemas/audit-event.d.ts.map +1 -1
  19. package/dist/doc-schemas/catalogs.js.map +1 -1
  20. package/dist/doc-schemas/gallery.d.ts +1 -0
  21. package/dist/doc-schemas/gallery.d.ts.map +1 -1
  22. package/dist/doc-schemas/gallery.js +3 -0
  23. package/dist/doc-schemas/gallery.js.map +1 -1
  24. package/dist/doc-schemas/game-location.js.map +1 -1
  25. package/dist/doc-schemas/game-stats.js.map +1 -1
  26. package/dist/doc-schemas/league-team.js.map +1 -1
  27. package/dist/doc-schemas/migration-console.d.ts +2 -0
  28. package/dist/doc-schemas/migration-console.d.ts.map +1 -1
  29. package/dist/doc-schemas/migration-console.js +5 -0
  30. package/dist/doc-schemas/migration-console.js.map +1 -1
  31. package/dist/doc-schemas/pending-media.d.ts +1 -0
  32. package/dist/doc-schemas/pending-media.d.ts.map +1 -1
  33. package/dist/doc-schemas/pending-media.js +8 -0
  34. package/dist/doc-schemas/pending-media.js.map +1 -1
  35. package/dist/doc-schemas/registry.d.ts +12 -0
  36. package/dist/doc-schemas/registry.d.ts.map +1 -1
  37. package/dist/doc-schemas/registry.js.map +1 -1
  38. package/dist/doc-schemas/sport-game.js.map +1 -1
  39. package/dist/doc-schemas/stats-operation.d.ts.map +1 -1
  40. package/dist/doc-schemas/stats-operation.js +6 -11
  41. package/dist/doc-schemas/stats-operation.js.map +1 -1
  42. package/dist/doc-schemas/system.d.ts +7 -0
  43. package/dist/doc-schemas/system.d.ts.map +1 -1
  44. package/dist/doc-schemas/system.js +4 -1
  45. package/dist/doc-schemas/system.js.map +1 -1
  46. package/dist/doc-schemas/user-profile.d.ts +1 -0
  47. package/dist/doc-schemas/user-profile.d.ts.map +1 -1
  48. package/dist/doc-schemas/user-profile.js +5 -0
  49. package/dist/doc-schemas/user-profile.js.map +1 -1
  50. package/dist/doc-schemas/waiver-template.d.ts +1 -0
  51. package/dist/doc-schemas/waiver-template.d.ts.map +1 -1
  52. package/dist/doc-schemas/waiver-template.js +10 -1
  53. package/dist/doc-schemas/waiver-template.js.map +1 -1
  54. package/dist/doc-schemas/waivers-and-hardware.d.ts +1 -0
  55. package/dist/doc-schemas/waivers-and-hardware.d.ts.map +1 -1
  56. package/dist/doc-schemas/waivers-and-hardware.js +17 -9
  57. package/dist/doc-schemas/waivers-and-hardware.js.map +1 -1
  58. package/dist/ids/index.js.map +1 -1
  59. package/dist/ids/minted-ids.d.ts +1 -0
  60. package/dist/ids/minted-ids.d.ts.map +1 -1
  61. package/dist/ids/minted-ids.js +6 -0
  62. package/dist/ids/minted-ids.js.map +1 -1
  63. package/dist/ids/stats-operation-ids.js.map +1 -1
  64. package/dist/index.js.map +1 -1
  65. package/dist/input-formats/index.d.ts +2 -2
  66. package/dist/input-formats/index.d.ts.map +1 -1
  67. package/dist/input-formats/index.js +2 -2
  68. package/dist/input-formats/index.js.map +1 -1
  69. package/dist/media/file-origins.js.map +1 -1
  70. package/dist/notifications/archive-all.d.ts +2 -0
  71. package/dist/notifications/archive-all.d.ts.map +1 -0
  72. package/dist/notifications/archive-all.js +6 -0
  73. package/dist/notifications/archive-all.js.map +1 -0
  74. package/dist/notifications/index.d.ts +1 -0
  75. package/dist/notifications/index.d.ts.map +1 -1
  76. package/dist/notifications/index.js +1 -0
  77. package/dist/notifications/index.js.map +1 -1
  78. package/dist/paths/collection-refs.js.map +1 -1
  79. package/dist/paths/collections.js.map +1 -1
  80. package/dist/paths/path-builders.js.map +1 -1
  81. package/dist/paths/utils.js.map +1 -1
  82. package/dist/schemas/account-settings.js.map +1 -1
  83. package/dist/schemas/admin-notifications.d.ts +1 -0
  84. package/dist/schemas/admin-notifications.d.ts.map +1 -1
  85. package/dist/schemas/admin-notifications.js +4 -2
  86. package/dist/schemas/admin-notifications.js.map +1 -1
  87. package/dist/schemas/app-config.d.ts +2 -2
  88. package/dist/schemas/app-config.d.ts.map +1 -1
  89. package/dist/schemas/app-config.js +9 -5
  90. package/dist/schemas/app-config.js.map +1 -1
  91. package/dist/schemas/atoms.js.map +1 -1
  92. package/dist/schemas/awards.d.ts +16 -4
  93. package/dist/schemas/awards.d.ts.map +1 -1
  94. package/dist/schemas/awards.js +10 -6
  95. package/dist/schemas/awards.js.map +1 -1
  96. package/dist/schemas/game-locations.d.ts +4 -4
  97. package/dist/schemas/game-locations.d.ts.map +1 -1
  98. package/dist/schemas/game-locations.js +11 -3
  99. package/dist/schemas/game-locations.js.map +1 -1
  100. package/dist/schemas/hardware-loan-contracts.js.map +1 -1
  101. package/dist/schemas/migration-console.d.ts +1 -0
  102. package/dist/schemas/migration-console.d.ts.map +1 -1
  103. package/dist/schemas/pictures.d.ts +3 -0
  104. package/dist/schemas/pictures.d.ts.map +1 -1
  105. package/dist/schemas/schedules.js.map +1 -1
  106. package/dist/schemas/scoring.js.map +1 -1
  107. package/dist/schemas/stats.d.ts +2 -0
  108. package/dist/schemas/stats.d.ts.map +1 -1
  109. package/dist/schemas/stats.js.map +1 -1
  110. package/dist/schemas/team-joining.js.map +1 -1
  111. package/dist/schemas/teams.d.ts +3 -2
  112. package/dist/schemas/teams.d.ts.map +1 -1
  113. package/dist/schemas/teams.js +19 -9
  114. package/dist/schemas/teams.js.map +1 -1
  115. package/dist/schemas/uploads.js.map +1 -1
  116. package/dist/schemas/users.d.ts +7 -3
  117. package/dist/schemas/users.d.ts.map +1 -1
  118. package/dist/schemas/users.js +10 -3
  119. package/dist/schemas/users.js.map +1 -1
  120. package/dist/schemas/waiver-templates.d.ts +1 -0
  121. package/dist/schemas/waiver-templates.d.ts.map +1 -1
  122. package/dist/schemas/waiver-templates.js +4 -1
  123. package/dist/schemas/waiver-templates.js.map +1 -1
  124. package/dist/sports/basketball-scoring.js.map +1 -1
  125. package/dist/sports/basketball.js.map +1 -1
  126. package/dist/sports/bulk-entry.js.map +1 -1
  127. package/dist/sports/contribution.js.map +1 -1
  128. package/dist/sports/curling-scoring.js.map +1 -1
  129. package/dist/sports/finalized-record.js.map +1 -1
  130. package/dist/sports/football-scoring.js.map +1 -1
  131. package/dist/sports/index.d.ts +1 -0
  132. package/dist/sports/index.d.ts.map +1 -1
  133. package/dist/sports/index.js +1 -0
  134. package/dist/sports/index.js.map +1 -1
  135. package/dist/sports/ledger-continuity.d.ts +13 -0
  136. package/dist/sports/ledger-continuity.d.ts.map +1 -0
  137. package/dist/sports/ledger-continuity.js +19 -0
  138. package/dist/sports/ledger-continuity.js.map +1 -0
  139. package/dist/sports/rankings.js.map +1 -1
  140. package/dist/sports/rollup-check.js.map +1 -1
  141. package/dist/sports/scoring.js.map +1 -1
  142. package/dist/sports/store-driver.js.map +1 -1
  143. package/dist/types/audit.d.ts +1 -1
  144. package/dist/types/audit.d.ts.map +1 -1
  145. package/dist/types/audit.js +5 -2
  146. package/dist/types/audit.js.map +1 -1
  147. package/dist/types/documents.js.map +1 -1
  148. package/dist/types/notifications.js.map +1 -1
  149. package/dist/types/picture-owners.js.map +1 -1
  150. package/dist/types/sports.js.map +1 -1
  151. package/dist/types/stats.js.map +1 -1
  152. package/dist/types/unions.d.ts +4 -2
  153. package/dist/types/unions.d.ts.map +1 -1
  154. package/dist/types/unions.js +6 -0
  155. package/dist/types/unions.js.map +1 -1
  156. package/dist/upload-variables/index.d.ts +3 -0
  157. package/dist/upload-variables/index.d.ts.map +1 -0
  158. package/dist/upload-variables/index.js +3 -0
  159. package/dist/upload-variables/index.js.map +1 -0
  160. package/dist/upload-variables/on-progress.d.ts +4 -0
  161. package/dist/upload-variables/on-progress.d.ts.map +1 -0
  162. package/dist/upload-variables/on-progress.js +10 -0
  163. package/dist/upload-variables/on-progress.js.map +1 -0
  164. package/dist/upload-variables/picture-upload-variables.d.ts +32 -0
  165. package/dist/upload-variables/picture-upload-variables.d.ts.map +1 -0
  166. package/dist/upload-variables/picture-upload-variables.js +21 -0
  167. package/dist/upload-variables/picture-upload-variables.js.map +1 -0
  168. package/dist/utils/account-status.js.map +1 -1
  169. package/dist/utils/app-config.d.ts +17 -3
  170. package/dist/utils/app-config.d.ts.map +1 -1
  171. package/dist/utils/app-config.js +21 -14
  172. package/dist/utils/app-config.js.map +1 -1
  173. package/dist/utils/app-routes.js.map +1 -1
  174. package/dist/utils/index.js.map +1 -1
  175. package/dist/utils/league-calendar.js.map +1 -1
  176. package/dist/utils/league-mode.js.map +1 -1
  177. package/dist/utils/team-member-actions.js.map +1 -1
  178. package/package.json +94 -90
@@ -1 +1 @@
1
- {"version":3,"file":"teams.js","sourceRoot":"","sources":["../../src/schemas/teams.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for teams and team membership. The acting user is always `request.auth.uid` —\r\n// never an input field (ARCH-106). The entry, never a field of the payload, decides the authority\r\n// (BACKEND-004); an admin entry's schema adds only what its authority needs.\r\n\r\nimport { z } from 'zod';\r\nimport {\r\n leagueJoinWarningActedOnSchema,\r\n leagueJoinWarningFindingSchema,\r\n} from '../utils/league-join-warning.js';\r\nimport { membershipRosterSyncStatusSchema } from '../doc-schemas/atoms.js';\r\nimport { isGhostUserId } from '../ids/minted-ids.js';\r\nimport { GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS } from '../types/stats.js';\r\nimport { MEMBER_ASSIGNABLE_TEAM_ROLES } from '../types/unions.js';\r\nimport {\r\n contactPhoneSchema,\r\n countSchema,\r\n displayNameSchema,\r\n gameIdSchema,\r\n leagueIdSchema,\r\n repairReasonSchema,\r\n teamIconSchema,\r\n teamIdSchema,\r\n teamNameSchema,\r\n teamRoleSchema,\r\n teamTypeSchema,\r\n userIdSchema,\r\n} from './atoms.js';\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Team creation — `createLeagueTeam` (the creator becomes captain) and `adminCreateLeagueTeam`\r\n// (an admin creates the team with a newly minted ghost captain). Both write the team's contact\r\n// phone; `teamType` is read only in a Competitive/Recreational league, which requires it.\r\n// ---------------------------------------------------------------------------------------------\r\n\r\nconst teamCreationFields = {\r\n leagueId: leagueIdSchema,\r\n name: teamNameSchema,\r\n icon: teamIconSchema,\r\n teamType: teamTypeSchema.optional(),\r\n contactPhone: contactPhoneSchema,\r\n};\r\n\r\nexport const CreateLeagueTeamInputSchema = z.object(teamCreationFields).strict();\r\nexport type CreateLeagueTeamInput = z.infer<typeof CreateLeagueTeamInputSchema>;\r\n\r\nexport const AdminCreateLeagueTeamInputSchema = z\r\n .object({ ...teamCreationFields, captainDisplayName: displayNameSchema })\r\n .strict();\r\nexport type AdminCreateLeagueTeamInput = z.infer<typeof AdminCreateLeagueTeamInputSchema>;\r\n\r\nexport const CreateLeagueTeamResultSchema = z\r\n .object({ leagueId: leagueIdSchema, teamId: teamIdSchema, captainUserId: userIdSchema })\r\n .strict();\r\nexport type CreateLeagueTeamResult = z.infer<typeof CreateLeagueTeamResultSchema>;\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Ghost add — one core behind two doors. The team page door (`createTeamGhostPlayer` /\r\n// `adminCreateTeamGhostPlayer`) needs authority over the team; the game page door\r\n// (`createGameGhostPlayer` / `adminCreateGameGhostPlayer`) needs scoring authority over the game\r\n// and adds to one of its two teams. The ghost id is always minted by the server.\r\n// ---------------------------------------------------------------------------------------------\r\n\r\nexport const CreateTeamGhostPlayerInputSchema = z\r\n .object({ teamId: teamIdSchema, displayName: displayNameSchema })\r\n .strict();\r\nexport type CreateTeamGhostPlayerInput = z.infer<typeof CreateTeamGhostPlayerInputSchema>;\r\n\r\nexport const CreateGameGhostPlayerInputSchema = z\r\n .object({ gameId: gameIdSchema, teamId: teamIdSchema, displayName: displayNameSchema })\r\n .strict();\r\nexport type CreateGameGhostPlayerInput = z.infer<typeof CreateGameGhostPlayerInputSchema>;\r\n\r\n// `rosterSyncStatus` is where the new membership's roster work stood when the call returned: the\r\n// membership is committed either way, and `pending` finishes in the background.\r\nexport const CreateGhostPlayerResultSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n teamId: teamIdSchema,\r\n ghostUserId: userIdSchema,\r\n rosterSyncStatus: membershipRosterSyncStatusSchema,\r\n })\r\n .strict();\r\nexport type CreateGhostPlayerResult = z.infer<typeof CreateGhostPlayerResultSchema>;\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// The join warning — `getLeagueJoinWarning` (the person, or a captain or co-captain of the target\r\n// team) and `adminGetLeagueJoinWarning` (an admin, about anyone).\r\n// ---------------------------------------------------------------------------------------------\r\n\r\n// `targetTeamId` is the team the door acts for; a free-agent signup and a team being created have\r\n// none. `actedOn` is the item the door answers, which the warning leaves out.\r\nexport const GetLeagueJoinWarningInputSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n userId: userIdSchema,\r\n targetTeamId: teamIdSchema.optional(),\r\n actedOn: leagueJoinWarningActedOnSchema.optional(),\r\n })\r\n .strict();\r\nexport type GetLeagueJoinWarningInput = z.infer<typeof GetLeagueJoinWarningInputSchema>;\r\n\r\nexport const GetLeagueJoinWarningResultSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n userId: userIdSchema,\r\n findings: z.array(leagueJoinWarningFindingSchema),\r\n })\r\n .strict();\r\nexport type GetLeagueJoinWarningResult = z.infer<typeof GetLeagueJoinWarningResultSchema>;\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Roster reconciliation recovery — an admin puts a team's failed roster obligations back to work.\r\n// ---------------------------------------------------------------------------------------------\r\n\r\nexport const AdminRetryLeagueTeamRosterSyncInputSchema = z.object({ teamId: teamIdSchema }).strict();\r\nexport type AdminRetryLeagueTeamRosterSyncInput = z.infer<typeof AdminRetryLeagueTeamRosterSyncInputSchema>;\r\n\r\nexport const AdminRetryLeagueTeamRosterSyncResultSchema = z\r\n .object({\r\n teamId: teamIdSchema,\r\n // Failed obligations put back to pending.\r\n retried: countSchema,\r\n // Of those and any already pending, how many the call itself finished.\r\n reconciled: countSchema,\r\n // Failed obligations left as they are because they fail their schema, by document id; a\r\n // damaged document's id is reported as stored, so it is not held to the membership id format.\r\n damagedTeamMembershipIds: z.array(z.string().min(1)),\r\n })\r\n .strict();\r\nexport type AdminRetryLeagueTeamRosterSyncResult = z.infer<typeof AdminRetryLeagueTeamRosterSyncResultSchema>;\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Linking a ghost to a real account — `linkGhostPlayerToUser` in a league that is not closed, and\r\n// `adminLinkClosedLeagueGhostPlayer` in a closed one. Both are admin-only, act on one team, and take\r\n// a reason, because a link rewrites completed records (BACKEND-212). The ghost and the account are\r\n// ids the core checks itself, so a ghost id named as the account, or a real id named as the ghost,\r\n// is refused with a failure record rather than at the parse. Every name the link records is read\r\n// server-side, never sent.\r\n// ---------------------------------------------------------------------------------------------\r\n\r\nexport const LinkGhostPlayerInputSchema = z\r\n .object({\r\n teamId: teamIdSchema,\r\n ghostUserId: userIdSchema,\r\n userId: userIdSchema,\r\n reason: repairReasonSchema,\r\n })\r\n .strict();\r\nexport type LinkGhostPlayerInput = z.infer<typeof LinkGhostPlayerInputSchema>;\r\n\r\n// `complete` is false when the call ran out of time part-way: the link stays under way, and the same\r\n// call by the same account continues it. `membershipOutcome` is present once it is complete.\r\n// `publicUserDeleted` is false when something else still names the ghost.\r\nexport const LinkGhostPlayerResultSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n teamId: teamIdSchema,\r\n ghostUserId: userIdSchema,\r\n userId: userIdSchema,\r\n complete: z.boolean(),\r\n gamesMoved: countSchema,\r\n membershipOutcome: z.enum(GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS).optional(),\r\n publicUserDeleted: z.boolean(),\r\n })\r\n .strict();\r\nexport type LinkGhostPlayerResult = z.infer<typeof LinkGhostPlayerResultSchema>;\r\n\r\nexport const AdminLinkClosedLeagueGhostPlayerInputSchema = LinkGhostPlayerInputSchema;\r\nexport type AdminLinkClosedLeagueGhostPlayerInput = LinkGhostPlayerInput;\r\nexport const AdminLinkClosedLeagueGhostPlayerResultSchema = LinkGhostPlayerResultSchema;\r\nexport type AdminLinkClosedLeagueGhostPlayerResult = LinkGhostPlayerResult;\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Managing a team's members. A role change and a removal each have a member entry — the team's\r\n// captain or a co-captain, read from their membership — and an admin entry; changing the captain,\r\n// renaming the team, changing its type, setting its contact phone, and deleting it are admin-only.\r\n// Every target is named by id and read server-side; nothing here names who is acting (ARCH-106).\r\n// ---------------------------------------------------------------------------------------------\r\n\r\n/** A ghost id, refused for any other id, so a removal input cannot name a real account. */\r\nexport const ghostUserIdSchema = userIdSchema.refine(isGhostUserId, 'Not a ghost player.');\r\n\r\n// `updateTeamMembershipRole` (the captain) / `adminUpdateTeamMembershipRole`: promote a player to\r\n// co-captain, or demote a co-captain to player.\r\nexport const UpdateTeamMembershipRoleInputSchema = z\r\n .object({ teamId: teamIdSchema, userId: userIdSchema, role: z.enum(MEMBER_ASSIGNABLE_TEAM_ROLES) })\r\n .strict();\r\nexport type UpdateTeamMembershipRoleInput = z.infer<typeof UpdateTeamMembershipRoleInputSchema>;\r\n\r\n// `changed` is false when the member already held the role: nothing was written or recorded.\r\nexport const UpdateTeamMembershipRoleResultSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n teamId: teamIdSchema,\r\n userId: userIdSchema,\r\n role: teamRoleSchema,\r\n changed: z.boolean(),\r\n })\r\n .strict();\r\nexport type UpdateTeamMembershipRoleResult = z.infer<typeof UpdateTeamMembershipRoleResultSchema>;\r\n\r\n// `deleteTeamMembership` (the captain or a co-captain) / `adminDeleteTeamMembership`: remove a real\r\n// player from the team. A ghost is removed through its own action, below.\r\nexport const DeleteTeamMembershipInputSchema = z\r\n .object({\r\n teamId: teamIdSchema,\r\n userId: userIdSchema.refine((userId) => !isGhostUserId(userId), 'A ghost player is removed as a ghost player.'),\r\n })\r\n .strict();\r\nexport type DeleteTeamMembershipInput = z.infer<typeof DeleteTeamMembershipInputSchema>;\r\n\r\n// `deleted` is false when the person held no membership on the team: nothing was written. The\r\n// membership is gone either way; `rosterSyncStatus` is where its roster work stood on return.\r\nexport const DeleteTeamMembershipResultSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n teamId: teamIdSchema,\r\n userId: userIdSchema,\r\n deleted: z.boolean(),\r\n rosterSyncStatus: membershipRosterSyncStatusSchema,\r\n })\r\n .strict();\r\nexport type DeleteTeamMembershipResult = z.infer<typeof DeleteTeamMembershipResultSchema>;\r\n\r\n// `deleteTeamGhostPlayer` (the captain or a co-captain) / `adminDeleteTeamGhostPlayer`: remove a ghost\r\n// that has never played, completely. A never-played ghost holds no stat, so its removal is not a\r\n// repair and takes no reason; its audit event still records who removed what (BACKEND-212).\r\nexport const DeleteTeamGhostPlayerInputSchema = z\r\n .object({ teamId: teamIdSchema, ghostUserId: ghostUserIdSchema })\r\n .strict();\r\nexport type DeleteTeamGhostPlayerInput = z.infer<typeof DeleteTeamGhostPlayerInputSchema>;\r\n\r\n// `complete` is false when the call ran out of time part-way: the ghost's games stay held and the\r\n// same call finishes the removal. `publicUserDeleted` is false when something else still names the\r\n// ghost, so its name stays until that reference goes.\r\nexport const DeleteTeamGhostPlayerResultSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n teamId: teamIdSchema,\r\n ghostUserId: userIdSchema,\r\n complete: z.boolean(),\r\n finishedGameEntriesRemoved: countSchema,\r\n publicUserDeleted: z.boolean(),\r\n })\r\n .strict();\r\nexport type DeleteTeamGhostPlayerResult = z.infer<typeof DeleteTeamGhostPlayerResultSchema>;\r\n\r\n// `adminUpdateLeagueTeamCaptain`: make a member of the team its captain. Every other captain the team\r\n// holds becomes a player.\r\nexport const AdminUpdateLeagueTeamCaptainInputSchema = z\r\n .object({ teamId: teamIdSchema, captainUserId: userIdSchema })\r\n .strict();\r\nexport type AdminUpdateLeagueTeamCaptainInput = z.infer<typeof AdminUpdateLeagueTeamCaptainInputSchema>;\r\n\r\nexport const AdminUpdateLeagueTeamCaptainResultSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n teamId: teamIdSchema,\r\n captainUserId: userIdSchema,\r\n demotedUserIds: z.array(userIdSchema),\r\n changed: z.boolean(),\r\n })\r\n .strict();\r\nexport type AdminUpdateLeagueTeamCaptainResult = z.infer<typeof AdminUpdateLeagueTeamCaptainResultSchema>;\r\n\r\n// `adminUpdateLeagueTeamName`: rename a team. The name lives on the team alone; nothing copies it.\r\nexport const AdminUpdateLeagueTeamNameInputSchema = z\r\n .object({ teamId: teamIdSchema, name: teamNameSchema })\r\n .strict();\r\nexport type AdminUpdateLeagueTeamNameInput = z.infer<typeof AdminUpdateLeagueTeamNameInputSchema>;\r\n\r\n// `adminUpdateLeagueTeamType`: change a team's type in a league that sorts its teams by type.\r\nexport const AdminUpdateLeagueTeamTypeInputSchema = z\r\n .object({ teamId: teamIdSchema, teamType: teamTypeSchema })\r\n .strict();\r\nexport type AdminUpdateLeagueTeamTypeInput = z.infer<typeof AdminUpdateLeagueTeamTypeInputSchema>;\r\n\r\n// The answer to either edit: `changed` is false when the team already held the value.\r\nexport const AdminUpdateLeagueTeamResultSchema = z\r\n .object({ leagueId: leagueIdSchema, teamId: teamIdSchema, changed: z.boolean() })\r\n .strict();\r\nexport type AdminUpdateLeagueTeamResult = z.infer<typeof AdminUpdateLeagueTeamResultSchema>;\r\n\r\n// `adminUpdateLeagueTeamContact`: set the team's contact phone on its admin-only contact document.\r\nexport const AdminUpdateLeagueTeamContactInputSchema = z\r\n .object({ teamId: teamIdSchema, contactPhone: contactPhoneSchema })\r\n .strict();\r\nexport type AdminUpdateLeagueTeamContactInput = z.infer<typeof AdminUpdateLeagueTeamContactInputSchema>;\r\n\r\nexport const AdminUpdateLeagueTeamContactResultSchema = AdminUpdateLeagueTeamResultSchema;\r\nexport type AdminUpdateLeagueTeamContactResult = AdminUpdateLeagueTeamResult;\r\n\r\n// `adminDeleteLeagueTeam`: delete a team that has never played, with everything that is only its.\r\n// A never-played team holds no stat, so its deletion is not a repair and takes no reason; its audit\r\n// event still records who deleted what (BACKEND-212).\r\nexport const AdminDeleteLeagueTeamInputSchema = z.object({ teamId: teamIdSchema }).strict();\r\nexport type AdminDeleteLeagueTeamInput = z.infer<typeof AdminDeleteLeagueTeamInputSchema>;\r\n\r\n// `complete` is false when the call ran out of time part-way: what is left stays, the team still\r\n// stands, and the same call finishes the deletion. `remainingGameCount` is the team's games still to\r\n// delete when it stopped.\r\nexport const AdminDeleteLeagueTeamResultSchema = z\r\n .object({\r\n teamId: teamIdSchema,\r\n complete: z.boolean(),\r\n remainingGameCount: countSchema,\r\n })\r\n .strict();\r\nexport type AdminDeleteLeagueTeamResult = z.infer<typeof AdminDeleteLeagueTeamResultSchema>;\r\n"]}
1
+ {"version":3,"file":"teams.js","sourceRoot":"","sources":["../../src/schemas/teams.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for teams and team membership. The acting user is always `request.auth.uid` —\n// never an input field (ARCH-106). The entry, never a field of the payload, decides the authority\n// (BACKEND-004); an admin entry's schema adds only what its authority needs.\n\nimport { z } from 'zod';\nimport {\n leagueJoinWarningActedOnSchema,\n leagueJoinWarningFindingSchema,\n} from '../utils/league-join-warning.js';\nimport { documentIdSegmentSchema, membershipRosterSyncStatusSchema } from '../doc-schemas/atoms.js';\nimport { buildGhostUserIdForRequest, isGhostUserId } from '../ids/minted-ids.js';\nimport { isDocumentIdSegment } from '../paths/utils.js';\nimport { GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS } from '../types/stats.js';\nimport { MEMBER_ASSIGNABLE_TEAM_ROLES } from '../types/unions.js';\nimport {\n contactPhoneSchema,\n countSchema,\n displayNameSchema,\n gameIdSchema,\n leagueIdSchema,\n teamIconSchema,\n teamIdSchema,\n teamNameSchema,\n teamRoleSchema,\n teamTypeSchema,\n userIdSchema,\n} from './atoms.js';\n\n// ---------------------------------------------------------------------------------------------\n// Team creation — `createLeagueTeam` (the creator becomes captain) and `adminCreateLeagueTeam`\n// (an admin creates the team with a newly minted ghost captain). Both write the team's contact\n// phone; `teamType` is read only in a Competitive/Recreational league, which requires it.\n// ---------------------------------------------------------------------------------------------\n\nconst teamCreationFields = {\n leagueId: leagueIdSchema,\n name: teamNameSchema,\n icon: teamIconSchema,\n teamType: teamTypeSchema.optional(),\n contactPhone: contactPhoneSchema,\n};\n\nexport const CreateLeagueTeamInputSchema = z.object(teamCreationFields).strict();\nexport type CreateLeagueTeamInput = z.infer<typeof CreateLeagueTeamInputSchema>;\n\nexport const AdminCreateLeagueTeamInputSchema = z\n .object({ ...teamCreationFields, captainDisplayName: displayNameSchema })\n .strict();\nexport type AdminCreateLeagueTeamInput = z.infer<typeof AdminCreateLeagueTeamInputSchema>;\n\nexport const CreateLeagueTeamResultSchema = z\n .object({ leagueId: leagueIdSchema, teamId: teamIdSchema, captainUserId: userIdSchema })\n .strict();\nexport type CreateLeagueTeamResult = z.infer<typeof CreateLeagueTeamResultSchema>;\n\n// ---------------------------------------------------------------------------------------------\n// Ghost add — one core behind two doors. The team page door (`createTeamGhostPlayer` /\n// `adminCreateTeamGhostPlayer`) needs authority over the team; the game page door\n// (`createGameGhostPlayer` / `adminCreateGameGhostPlayer`) needs scoring authority over the game\n// and adds to one of its two teams. The ghost id is derived by the server from the add's\n// `requestId`, which the client mints once when the add starts and re-sends on every retry, so a\n// retry after an unknown outcome is recognised as the same add (`buildGhostUserIdForRequest`).\n// ---------------------------------------------------------------------------------------------\n\n// One document-id segment (ARCH-106), short enough that the ghost id derived from it is one too.\nexport const ghostCreateRequestIdSchema = documentIdSegmentSchema.refine(\n (requestId) => isDocumentIdSegment(buildGhostUserIdForRequest(requestId)),\n 'Not a ghost add request id.',\n);\n\nexport const CreateTeamGhostPlayerInputSchema = z\n .object({ teamId: teamIdSchema, displayName: displayNameSchema, requestId: ghostCreateRequestIdSchema })\n .strict();\nexport type CreateTeamGhostPlayerInput = z.infer<typeof CreateTeamGhostPlayerInputSchema>;\n\nexport const CreateGameGhostPlayerInputSchema = z\n .object({\n gameId: gameIdSchema,\n teamId: teamIdSchema,\n displayName: displayNameSchema,\n requestId: ghostCreateRequestIdSchema,\n })\n .strict();\nexport type CreateGameGhostPlayerInput = z.infer<typeof CreateGameGhostPlayerInputSchema>;\n\n// `rosterSyncStatus` is where the new membership's roster work stood when the call returned: the\n// membership is committed either way, and `pending` finishes in the background.\nexport const CreateGhostPlayerResultSchema = z\n .object({\n leagueId: leagueIdSchema,\n teamId: teamIdSchema,\n ghostUserId: userIdSchema,\n rosterSyncStatus: membershipRosterSyncStatusSchema,\n })\n .strict();\nexport type CreateGhostPlayerResult = z.infer<typeof CreateGhostPlayerResultSchema>;\n\n// ---------------------------------------------------------------------------------------------\n// The join warning — `getLeagueJoinWarning` (the person, or a captain or co-captain of the target\n// team) and `adminGetLeagueJoinWarning` (an admin, about anyone).\n// ---------------------------------------------------------------------------------------------\n\n// `targetTeamId` is the team the door acts for; a free-agent signup and a team being created have\n// none. `actedOn` is the item the door answers, which the warning leaves out.\nexport const GetLeagueJoinWarningInputSchema = z\n .object({\n leagueId: leagueIdSchema,\n userId: userIdSchema,\n targetTeamId: teamIdSchema.optional(),\n actedOn: leagueJoinWarningActedOnSchema.optional(),\n })\n .strict();\nexport type GetLeagueJoinWarningInput = z.infer<typeof GetLeagueJoinWarningInputSchema>;\n\nexport const GetLeagueJoinWarningResultSchema = z\n .object({\n leagueId: leagueIdSchema,\n userId: userIdSchema,\n findings: z.array(leagueJoinWarningFindingSchema),\n })\n .strict();\nexport type GetLeagueJoinWarningResult = z.infer<typeof GetLeagueJoinWarningResultSchema>;\n\n// ---------------------------------------------------------------------------------------------\n// Roster reconciliation recovery — an admin puts a team's failed roster obligations back to work.\n// ---------------------------------------------------------------------------------------------\n\nexport const AdminRetryLeagueTeamRosterSyncInputSchema = z.object({ teamId: teamIdSchema }).strict();\nexport type AdminRetryLeagueTeamRosterSyncInput = z.infer<typeof AdminRetryLeagueTeamRosterSyncInputSchema>;\n\nexport const AdminRetryLeagueTeamRosterSyncResultSchema = z\n .object({\n teamId: teamIdSchema,\n // Failed obligations put back to pending.\n retried: countSchema,\n // Of those and any already pending, how many the call itself finished.\n reconciled: countSchema,\n // Failed obligations left as they are because they fail their schema, by document id; a\n // damaged document's id is reported as stored, so it is not held to the membership id format.\n damagedTeamMembershipIds: z.array(z.string().min(1)),\n })\n .strict();\nexport type AdminRetryLeagueTeamRosterSyncResult = z.infer<typeof AdminRetryLeagueTeamRosterSyncResultSchema>;\n\n// ---------------------------------------------------------------------------------------------\n// Linking a ghost to a real account — `linkGhostPlayerToUser` in a league that is not closed, and\n// `adminLinkClosedLeagueGhostPlayer` in a closed one. Both are admin-only and act on one team. A link\n// takes no reason: the admin chooses the account and confirms, and the link's audit event records\n// who linked which ghost to whom and what moved (BACKEND-212). The ghost and the account are\n// ids the core checks itself, so a ghost id named as the account, or a real id named as the ghost,\n// is refused with a failure record rather than at the parse. Every name the link records is read\n// server-side, never sent.\n// ---------------------------------------------------------------------------------------------\n\nexport const LinkGhostPlayerInputSchema = z\n .object({\n teamId: teamIdSchema,\n ghostUserId: userIdSchema,\n userId: userIdSchema,\n })\n .strict();\nexport type LinkGhostPlayerInput = z.infer<typeof LinkGhostPlayerInputSchema>;\n\n// `complete` is false when the call ran out of time part-way: the link stays under way, and the same\n// call by the same account continues it. `membershipOutcome` is present once it is complete.\n// `publicUserDeleted` is false when something else still names the ghost.\nexport const LinkGhostPlayerResultSchema = z\n .object({\n leagueId: leagueIdSchema,\n teamId: teamIdSchema,\n ghostUserId: userIdSchema,\n userId: userIdSchema,\n complete: z.boolean(),\n gamesMoved: countSchema,\n membershipOutcome: z.enum(GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS).optional(),\n publicUserDeleted: z.boolean(),\n })\n .strict();\nexport type LinkGhostPlayerResult = z.infer<typeof LinkGhostPlayerResultSchema>;\n\nexport const AdminLinkClosedLeagueGhostPlayerInputSchema = LinkGhostPlayerInputSchema;\nexport type AdminLinkClosedLeagueGhostPlayerInput = LinkGhostPlayerInput;\nexport const AdminLinkClosedLeagueGhostPlayerResultSchema = LinkGhostPlayerResultSchema;\nexport type AdminLinkClosedLeagueGhostPlayerResult = LinkGhostPlayerResult;\n\n// ---------------------------------------------------------------------------------------------\n// Managing a team's members. A role change and a removal each have a member entry — the team's\n// captain or a co-captain, read from their membership — and an admin entry; changing the captain,\n// renaming the team, changing its type, setting its contact phone, and deleting it are admin-only.\n// Every target is named by id and read server-side; nothing here names who is acting (ARCH-106).\n// ---------------------------------------------------------------------------------------------\n\n/** A ghost id, refused for any other id, so a removal input cannot name a real account. */\nexport const ghostUserIdSchema = userIdSchema.refine(isGhostUserId, 'Not a ghost player.');\n\n// `updateTeamMembershipRole` (the captain) / `adminUpdateTeamMembershipRole`: promote a player to\n// co-captain, or demote a co-captain to player.\nexport const UpdateTeamMembershipRoleInputSchema = z\n .object({ teamId: teamIdSchema, userId: userIdSchema, role: z.enum(MEMBER_ASSIGNABLE_TEAM_ROLES) })\n .strict();\nexport type UpdateTeamMembershipRoleInput = z.infer<typeof UpdateTeamMembershipRoleInputSchema>;\n\n// `changed` is false when the member already held the role: nothing was written or recorded.\nexport const UpdateTeamMembershipRoleResultSchema = z\n .object({\n leagueId: leagueIdSchema,\n teamId: teamIdSchema,\n userId: userIdSchema,\n role: teamRoleSchema,\n changed: z.boolean(),\n })\n .strict();\nexport type UpdateTeamMembershipRoleResult = z.infer<typeof UpdateTeamMembershipRoleResultSchema>;\n\n// `deleteTeamMembership` (the captain or a co-captain) / `adminDeleteTeamMembership`: remove a real\n// player from the team. A ghost is removed through its own action, below.\nexport const DeleteTeamMembershipInputSchema = z\n .object({\n teamId: teamIdSchema,\n userId: userIdSchema.refine((userId) => !isGhostUserId(userId), 'A ghost player is removed as a ghost player.'),\n })\n .strict();\nexport type DeleteTeamMembershipInput = z.infer<typeof DeleteTeamMembershipInputSchema>;\n\n// `deleted` is false when the person held no membership on the team: nothing was written. The\n// membership is gone either way; `rosterSyncStatus` is where its roster work stood on return.\nexport const DeleteTeamMembershipResultSchema = z\n .object({\n leagueId: leagueIdSchema,\n teamId: teamIdSchema,\n userId: userIdSchema,\n deleted: z.boolean(),\n rosterSyncStatus: membershipRosterSyncStatusSchema,\n })\n .strict();\nexport type DeleteTeamMembershipResult = z.infer<typeof DeleteTeamMembershipResultSchema>;\n\n// `deleteTeamGhostPlayer` (the captain or a co-captain) / `adminDeleteTeamGhostPlayer`: remove a ghost\n// that has never played, completely. A never-played ghost holds no stat, so its removal is not a\n// repair and takes no reason; its audit event still records who removed what (BACKEND-212).\nexport const DeleteTeamGhostPlayerInputSchema = z\n .object({ teamId: teamIdSchema, ghostUserId: ghostUserIdSchema })\n .strict();\nexport type DeleteTeamGhostPlayerInput = z.infer<typeof DeleteTeamGhostPlayerInputSchema>;\n\n// `complete` is false when the call ran out of time part-way: the ghost's games stay held and the\n// same call finishes the removal. `publicUserDeleted` is false when something else still names the\n// ghost, so its name stays until that reference goes.\nexport const DeleteTeamGhostPlayerResultSchema = z\n .object({\n leagueId: leagueIdSchema,\n teamId: teamIdSchema,\n ghostUserId: userIdSchema,\n complete: z.boolean(),\n finishedGameEntriesRemoved: countSchema,\n publicUserDeleted: z.boolean(),\n })\n .strict();\nexport type DeleteTeamGhostPlayerResult = z.infer<typeof DeleteTeamGhostPlayerResultSchema>;\n\n// `adminUpdateLeagueTeamCaptain`: make a member of the team its captain. Every other captain the team\n// holds becomes a player.\nexport const AdminUpdateLeagueTeamCaptainInputSchema = z\n .object({ teamId: teamIdSchema, captainUserId: userIdSchema })\n .strict();\nexport type AdminUpdateLeagueTeamCaptainInput = z.infer<typeof AdminUpdateLeagueTeamCaptainInputSchema>;\n\nexport const AdminUpdateLeagueTeamCaptainResultSchema = z\n .object({\n leagueId: leagueIdSchema,\n teamId: teamIdSchema,\n captainUserId: userIdSchema,\n demotedUserIds: z.array(userIdSchema),\n changed: z.boolean(),\n })\n .strict();\nexport type AdminUpdateLeagueTeamCaptainResult = z.infer<typeof AdminUpdateLeagueTeamCaptainResultSchema>;\n\n// `adminUpdateLeagueTeamName`: rename a team. The name lives on the team alone; nothing copies it.\nexport const AdminUpdateLeagueTeamNameInputSchema = z\n .object({ teamId: teamIdSchema, name: teamNameSchema })\n .strict();\nexport type AdminUpdateLeagueTeamNameInput = z.infer<typeof AdminUpdateLeagueTeamNameInputSchema>;\n\n// `adminUpdateLeagueTeamType`: change a team's type in a league that sorts its teams by type.\nexport const AdminUpdateLeagueTeamTypeInputSchema = z\n .object({ teamId: teamIdSchema, teamType: teamTypeSchema })\n .strict();\nexport type AdminUpdateLeagueTeamTypeInput = z.infer<typeof AdminUpdateLeagueTeamTypeInputSchema>;\n\n// The answer to either edit: `changed` is false when the team already held the value.\nexport const AdminUpdateLeagueTeamResultSchema = z\n .object({ leagueId: leagueIdSchema, teamId: teamIdSchema, changed: z.boolean() })\n .strict();\nexport type AdminUpdateLeagueTeamResult = z.infer<typeof AdminUpdateLeagueTeamResultSchema>;\n\n// `adminUpdateLeagueTeamContact`: set the team's contact phone on its admin-only contact document.\nexport const AdminUpdateLeagueTeamContactInputSchema = z\n .object({ teamId: teamIdSchema, contactPhone: contactPhoneSchema })\n .strict();\nexport type AdminUpdateLeagueTeamContactInput = z.infer<typeof AdminUpdateLeagueTeamContactInputSchema>;\n\nexport const AdminUpdateLeagueTeamContactResultSchema = AdminUpdateLeagueTeamResultSchema;\nexport type AdminUpdateLeagueTeamContactResult = AdminUpdateLeagueTeamResult;\n\n// `adminDeleteLeagueTeam`: delete a team that has never played, with everything that is only its.\n// A never-played team holds no stat, so its deletion is not a repair and takes no reason; its audit\n// event still records who deleted what (BACKEND-212).\nexport const AdminDeleteLeagueTeamInputSchema = z.object({ teamId: teamIdSchema }).strict();\nexport type AdminDeleteLeagueTeamInput = z.infer<typeof AdminDeleteLeagueTeamInputSchema>;\n\n// `complete` is false when the call ran out of time part-way: what is left stays, the team still\n// stands, and the same call finishes the deletion. `remainingGameCount` is the team's games still to\n// delete when it stopped.\nexport const AdminDeleteLeagueTeamResultSchema = z\n .object({\n teamId: teamIdSchema,\n complete: z.boolean(),\n remainingGameCount: countSchema,\n })\n .strict();\nexport type AdminDeleteLeagueTeamResult = z.infer<typeof AdminDeleteLeagueTeamResultSchema>;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"uploads.js","sourceRoot":"","sources":["../../src/schemas/uploads.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for accepting a picture upload.\r\n//\r\n// A client stages its bytes at its own staging path and hands that path, the origin, and the origin's\r\n// target to `adminStartUpload`. Nothing about any path is negotiable: the target names the owner by\r\n// id, and every path the picture is later written to is derived on the server.\r\n\r\nimport { z } from 'zod';\r\nimport { ClientMediaClaimSchema } from '@ttt-productions/media-schemas';\r\nimport { MAX_STAGING_UPLOAD_PATH_LENGTH } from '../constants/media.js';\r\nimport { leagueIdSchema, stagingIdSchema, teamIdSchema } from '../doc-schemas/atoms.js';\r\nimport { awardIdSchema, awardNameSchema } from '../doc-schemas/catalogs.js';\r\nimport { gameLocationIdSchema } from '../doc-schemas/game-location.js';\r\nimport { pictureOriginSchema } from '../doc-schemas/pending-media.js';\r\nimport type { PictureOwnerRef } from '../doc-schemas/pending-media.js';\r\nimport type { PictureOrigin } from '../media/file-origins.js';\r\nimport { SPECIAL_DOCS } from '../paths/collections.js';\r\nimport { AWARD_DEFINITION_OWNER_KIND } from '../types/picture-owners.js';\r\nimport type { PictureOwnerKind } from '../types/picture-owners.js';\r\n\r\nexport const stagingUploadPathSchema = z.string().min(1).max(MAX_STAGING_UPLOAD_PATH_LENGTH);\r\n\r\n// Each picture origin's target: which owner the picture is for, by id.\r\nexport const LeaguePictureTargetInfoSchema = z.object({ leagueId: leagueIdSchema }).strict();\r\nexport const TeamPictureTargetInfoSchema = z.object({ teamId: teamIdSchema }).strict();\r\n// There is one landing page, so its target names nothing.\r\nexport const LandingPictureTargetInfoSchema = z.object({}).strict();\r\nexport const LocationPictureTargetInfoSchema = z.object({ gameLocationId: gameLocationIdSchema }).strict();\r\n// A badge either replaces an existing award's (`awardId`) or creates the award it is the first badge\r\n// of (`newAwardName`), whose id is the upload's staging id.\r\nexport const ExistingAwardBadgeTargetInfoSchema = z.object({ awardId: awardIdSchema }).strict();\r\nexport const NewAwardBadgeTargetInfoSchema = z.object({ newAwardName: awardNameSchema }).strict();\r\nexport const AwardBadgeTargetInfoSchema = z.union([ExistingAwardBadgeTargetInfoSchema, NewAwardBadgeTargetInfoSchema]);\r\n\r\ninterface PictureTarget<TSchema extends z.ZodTypeAny> {\r\n readonly schema: TSchema;\r\n /** The kind of document a picture of this origin belongs to. */\r\n readonly ownerKind: PictureOwnerKind;\r\n /** The owner's id. A target naming an owner that does not exist yet takes the upload's staging id. */\r\n readonly ownerId: (target: z.infer<TSchema>, stagingId: string | undefined) => string;\r\n}\r\n\r\nfunction pictureTarget<TSchema extends z.ZodTypeAny>(\r\n schema: TSchema,\r\n ownerKind: PictureOwnerKind,\r\n ownerId: (target: z.infer<TSchema>, stagingId: string | undefined) => string,\r\n): PictureTarget<TSchema> {\r\n return { schema, ownerKind, ownerId };\r\n}\r\n\r\nexport const PICTURE_TARGETS = {\r\n 'league-picture': pictureTarget(LeaguePictureTargetInfoSchema, 'sportLeague', (target) => target.leagueId),\r\n 'team-picture': pictureTarget(TeamPictureTargetInfoSchema, 'leagueTeam', (target) => target.teamId),\r\n 'landing-picture': pictureTarget(LandingPictureTargetInfoSchema, 'landingPage', () => SPECIAL_DOCS.LANDING_PAGE),\r\n 'location-picture': pictureTarget(\r\n LocationPictureTargetInfoSchema,\r\n 'gameLocation',\r\n (target) => target.gameLocationId,\r\n ),\r\n 'award-badge': pictureTarget(AwardBadgeTargetInfoSchema, AWARD_DEFINITION_OWNER_KIND, (target, stagingId) => {\r\n if ('awardId' in target) return target.awardId;\r\n if (stagingId === undefined) throw new Error(\"A new award's id is its badge upload's staging id, which was not given.\");\r\n return stagingId;\r\n }),\r\n} as const satisfies Record<PictureOrigin, PictureTarget<z.ZodTypeAny>>;\r\n\r\nexport type PictureTargetInfo = {\r\n [O in PictureOrigin]: z.infer<(typeof PICTURE_TARGETS)[O]['schema']>;\r\n}[PictureOrigin];\r\n\r\n/**\r\n * Parse a picture upload's target with its origin's schema and normalize it to the owner the\r\n * picture belongs to — the form an upload row stores. A badge creating its award names the award by\r\n * the upload's `stagingId`. Throws the schema's error on a target that does not fit the origin.\r\n */\r\nexport function parseTargetInfo(fileOrigin: PictureOrigin, targetInfo: unknown, stagingId?: string): PictureOwnerRef {\r\n const target = PICTURE_TARGETS[fileOrigin] as PictureTarget<z.ZodTypeAny>;\r\n return { kind: target.ownerKind, id: target.ownerId(target.schema.parse(targetInfo), stagingId) };\r\n}\r\n\r\n/** The name of the award a badge upload creates, or `undefined` for every other upload. */\r\nexport function newAwardNameOf(fileOrigin: PictureOrigin, targetInfo: unknown): string | undefined {\r\n if (PICTURE_TARGETS[fileOrigin].ownerKind !== AWARD_DEFINITION_OWNER_KIND) return undefined;\r\n const target = AwardBadgeTargetInfoSchema.parse(targetInfo);\r\n return 'newAwardName' in target ? target.newAwardName : undefined;\r\n}\r\n\r\nexport const AdminStartUploadInputSchema = z\r\n .object({\r\n fileOrigin: pictureOriginSchema,\r\n // The full staging path the client uploaded to. Only its last segment, the staging id, is\r\n // taken from it; the server rebuilds the rest and refuses anything not exactly equal.\r\n storagePath: stagingUploadPathSchema,\r\n // Checked against the origin's own target schema below, so a target that does not fit its\r\n // origin is refused with the rest of a malformed payload.\r\n targetInfo: z.unknown(),\r\n // What the admin actually did — chose a file in the picker, an advisory claim. Untrusted\r\n // context kept on the row for the processing pipeline; the byte inspection alone decides what\r\n // the file is, and a request without it is inspected all the same.\r\n clientMediaClaim: ClientMediaClaimSchema.optional(),\r\n })\r\n .strict()\r\n .superRefine((input, context) => {\r\n const target = PICTURE_TARGETS[input.fileOrigin] as PictureTarget<z.ZodTypeAny>;\r\n const parsed = target.schema.safeParse(input.targetInfo);\r\n if (!parsed.success) {\r\n context.addIssue({\r\n code: 'custom',\r\n path: ['targetInfo'],\r\n message: `The target does not fit a ${input.fileOrigin} upload: ${parsed.error.issues[0]?.message ?? 'invalid'}`,\r\n });\r\n }\r\n });\r\nexport type AdminStartUploadInput = z.infer<typeof AdminStartUploadInputSchema>;\r\n\r\nexport const AdminStartUploadResultSchema = z\r\n .object({\r\n // The upload's row, which the uploading control follows to its end. It is also the picture's id.\r\n pendingMediaId: stagingIdSchema,\r\n // A badge's award: the existing one it replaces, or the one its publication will create.\r\n awardId: awardIdSchema.optional(),\r\n })\r\n .strict();\r\nexport type AdminStartUploadResult = z.infer<typeof AdminStartUploadResultSchema>;\r\n"]}
1
+ {"version":3,"file":"uploads.js","sourceRoot":"","sources":["../../src/schemas/uploads.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for accepting a picture upload.\n//\n// A client stages its bytes at its own staging path and hands that path, the origin, and the origin's\n// target to `adminStartUpload`. Nothing about any path is negotiable: the target names the owner by\n// id, and every path the picture is later written to is derived on the server.\n\nimport { z } from 'zod';\nimport { ClientMediaClaimSchema } from '@ttt-productions/media-schemas';\nimport { MAX_STAGING_UPLOAD_PATH_LENGTH } from '../constants/media.js';\nimport { leagueIdSchema, stagingIdSchema, teamIdSchema } from '../doc-schemas/atoms.js';\nimport { awardIdSchema, awardNameSchema } from '../doc-schemas/catalogs.js';\nimport { gameLocationIdSchema } from '../doc-schemas/game-location.js';\nimport { pictureOriginSchema } from '../doc-schemas/pending-media.js';\nimport type { PictureOwnerRef } from '../doc-schemas/pending-media.js';\nimport type { PictureOrigin } from '../media/file-origins.js';\nimport { SPECIAL_DOCS } from '../paths/collections.js';\nimport { AWARD_DEFINITION_OWNER_KIND } from '../types/picture-owners.js';\nimport type { PictureOwnerKind } from '../types/picture-owners.js';\n\nexport const stagingUploadPathSchema = z.string().min(1).max(MAX_STAGING_UPLOAD_PATH_LENGTH);\n\n// Each picture origin's target: which owner the picture is for, by id.\nexport const LeaguePictureTargetInfoSchema = z.object({ leagueId: leagueIdSchema }).strict();\nexport const TeamPictureTargetInfoSchema = z.object({ teamId: teamIdSchema }).strict();\n// There is one landing page, so its target names nothing.\nexport const LandingPictureTargetInfoSchema = z.object({}).strict();\nexport const LocationPictureTargetInfoSchema = z.object({ gameLocationId: gameLocationIdSchema }).strict();\n// A badge either replaces an existing award's (`awardId`) or creates the award it is the first badge\n// of (`newAwardName`), whose id is the upload's staging id.\nexport const ExistingAwardBadgeTargetInfoSchema = z.object({ awardId: awardIdSchema }).strict();\nexport const NewAwardBadgeTargetInfoSchema = z.object({ newAwardName: awardNameSchema }).strict();\nexport const AwardBadgeTargetInfoSchema = z.union([ExistingAwardBadgeTargetInfoSchema, NewAwardBadgeTargetInfoSchema]);\n\ninterface PictureTarget<TSchema extends z.ZodTypeAny> {\n readonly schema: TSchema;\n /** The kind of document a picture of this origin belongs to. */\n readonly ownerKind: PictureOwnerKind;\n /** The owner's id. A target naming an owner that does not exist yet takes the upload's staging id. */\n readonly ownerId: (target: z.infer<TSchema>, stagingId: string | undefined) => string;\n}\n\nfunction pictureTarget<TSchema extends z.ZodTypeAny>(\n schema: TSchema,\n ownerKind: PictureOwnerKind,\n ownerId: (target: z.infer<TSchema>, stagingId: string | undefined) => string,\n): PictureTarget<TSchema> {\n return { schema, ownerKind, ownerId };\n}\n\nexport const PICTURE_TARGETS = {\n 'league-picture': pictureTarget(LeaguePictureTargetInfoSchema, 'sportLeague', (target) => target.leagueId),\n 'team-picture': pictureTarget(TeamPictureTargetInfoSchema, 'leagueTeam', (target) => target.teamId),\n 'landing-picture': pictureTarget(LandingPictureTargetInfoSchema, 'landingPage', () => SPECIAL_DOCS.LANDING_PAGE),\n 'location-picture': pictureTarget(\n LocationPictureTargetInfoSchema,\n 'gameLocation',\n (target) => target.gameLocationId,\n ),\n 'award-badge': pictureTarget(AwardBadgeTargetInfoSchema, AWARD_DEFINITION_OWNER_KIND, (target, stagingId) => {\n if ('awardId' in target) return target.awardId;\n if (stagingId === undefined) throw new Error(\"A new award's id is its badge upload's staging id, which was not given.\");\n return stagingId;\n }),\n} as const satisfies Record<PictureOrigin, PictureTarget<z.ZodTypeAny>>;\n\nexport type PictureTargetInfo = {\n [O in PictureOrigin]: z.infer<(typeof PICTURE_TARGETS)[O]['schema']>;\n}[PictureOrigin];\n\n/**\n * Parse a picture upload's target with its origin's schema and normalize it to the owner the\n * picture belongs to — the form an upload row stores. A badge creating its award names the award by\n * the upload's `stagingId`. Throws the schema's error on a target that does not fit the origin.\n */\nexport function parseTargetInfo(fileOrigin: PictureOrigin, targetInfo: unknown, stagingId?: string): PictureOwnerRef {\n const target = PICTURE_TARGETS[fileOrigin] as PictureTarget<z.ZodTypeAny>;\n return { kind: target.ownerKind, id: target.ownerId(target.schema.parse(targetInfo), stagingId) };\n}\n\n/** The name of the award a badge upload creates, or `undefined` for every other upload. */\nexport function newAwardNameOf(fileOrigin: PictureOrigin, targetInfo: unknown): string | undefined {\n if (PICTURE_TARGETS[fileOrigin].ownerKind !== AWARD_DEFINITION_OWNER_KIND) return undefined;\n const target = AwardBadgeTargetInfoSchema.parse(targetInfo);\n return 'newAwardName' in target ? target.newAwardName : undefined;\n}\n\nexport const AdminStartUploadInputSchema = z\n .object({\n fileOrigin: pictureOriginSchema,\n // The full staging path the client uploaded to. Only its last segment, the staging id, is\n // taken from it; the server rebuilds the rest and refuses anything not exactly equal.\n storagePath: stagingUploadPathSchema,\n // Checked against the origin's own target schema below, so a target that does not fit its\n // origin is refused with the rest of a malformed payload.\n targetInfo: z.unknown(),\n // What the admin actually did — chose a file in the picker, an advisory claim. Untrusted\n // context kept on the row for the processing pipeline; the byte inspection alone decides what\n // the file is, and a request without it is inspected all the same.\n clientMediaClaim: ClientMediaClaimSchema.optional(),\n })\n .strict()\n .superRefine((input, context) => {\n const target = PICTURE_TARGETS[input.fileOrigin] as PictureTarget<z.ZodTypeAny>;\n const parsed = target.schema.safeParse(input.targetInfo);\n if (!parsed.success) {\n context.addIssue({\n code: 'custom',\n path: ['targetInfo'],\n message: `The target does not fit a ${input.fileOrigin} upload: ${parsed.error.issues[0]?.message ?? 'invalid'}`,\n });\n }\n });\nexport type AdminStartUploadInput = z.infer<typeof AdminStartUploadInputSchema>;\n\nexport const AdminStartUploadResultSchema = z\n .object({\n // The upload's row, which the uploading control follows to its end. It is also the picture's id.\n pendingMediaId: stagingIdSchema,\n // A badge's award: the existing one it replaces, or the one its publication will create.\n awardId: awardIdSchema.optional(),\n })\n .strict();\nexport type AdminStartUploadResult = z.infer<typeof AdminStartUploadResultSchema>;\n"]}
@@ -4,10 +4,13 @@ export declare const RegisterUserInputSchema: z.ZodObject<{
4
4
  acceptedTerms: z.ZodLiteral<true>;
5
5
  }, z.core.$strict>;
6
6
  export type RegisterUserInput = z.infer<typeof RegisterUserInputSchema>;
7
- export declare const RegisterUserResultSchema: z.ZodObject<{
7
+ export declare const RegisterUserResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
8
+ status: z.ZodLiteral<"registered">;
8
9
  userId: z.ZodString;
9
10
  displayName: z.ZodString;
10
- }, z.core.$strict>;
11
+ }, z.core.$strict>, z.ZodObject<{
12
+ status: z.ZodLiteral<"registrationExpired">;
13
+ }, z.core.$strict>], "status">;
11
14
  export type RegisterUserResult = z.infer<typeof RegisterUserResultSchema>;
12
15
  export declare const CheckDisplayNameAvailableInputSchema: z.ZodObject<{
13
16
  displayName: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
@@ -129,10 +132,11 @@ export type AdminUpdateUserStatusResult = z.infer<typeof AdminUpdateUserStatusRe
129
132
  export declare const ADMIN_STANDING_BAN_REFUSAL_REASON = "adminStandingTarget";
130
133
  export declare const CreateRegistrationStartInputSchema: z.ZodObject<{}, z.core.$strict>;
131
134
  export type CreateRegistrationStartInput = z.infer<typeof CreateRegistrationStartInputSchema>;
132
- export declare const REGISTRATION_START_OUTCOMES: readonly ["started", "alreadyStarted"];
135
+ export declare const REGISTRATION_START_OUTCOMES: readonly ["started", "alreadyStarted", "registrationExpired"];
133
136
  export type RegistrationStartOutcome = (typeof REGISTRATION_START_OUTCOMES)[number];
134
137
  export declare const CreateRegistrationStartResultSchema: z.ZodObject<{
135
138
  outcome: z.ZodEnum<{
139
+ registrationExpired: "registrationExpired";
136
140
  started: "started";
137
141
  alreadyStarted: "alreadyStarted";
138
142
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/schemas/users.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/schemas/users.ts"],"names":[],"mappings":"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"}
@@ -12,7 +12,13 @@ export const RegisterUserInputSchema = z
12
12
  acceptedTerms: z.literal(true),
13
13
  })
14
14
  .strict();
15
- export const RegisterUserResultSchema = z.object({ userId: userIdSchema, displayName: z.string() }).strict();
15
+ export const RegisterUserResultSchema = z.discriminatedUnion('status', [
16
+ // The account is registered (or already was — an idempotent replay).
17
+ z.object({ status: z.literal('registered'), userId: userIdSchema, displayName: z.string() }).strict(),
18
+ // The orphan-registration cleanup claimed this login for deletion, so the registration cannot
19
+ // finish on it; nothing is written and the person signs up again.
20
+ z.object({ status: z.literal('registrationExpired') }).strict(),
21
+ ]);
16
22
  // The register form's check before the login is created: is the name free? It runs before any
17
23
  // account exists, over the same name rule `registerUser` takes, and is a soft answer — the claim
18
24
  // itself is `registerUser`'s transaction, which refuses `already-exists` when two registrations
@@ -113,8 +119,9 @@ export const ADMIN_STANDING_BAN_REFUSAL_REASON = 'adminStandingTarget';
113
119
  // caller is `request.auth.uid` and the email comes from its token, so it takes no input.
114
120
  export const CreateRegistrationStartInputSchema = z.object({}).strict();
115
121
  // `started` wrote both records; `alreadyStarted` found the registration already started and wrote
116
- // nothing — a retry, or a resume after a later step failed.
117
- export const REGISTRATION_START_OUTCOMES = ['started', 'alreadyStarted'];
122
+ // nothing — a retry, or a resume after a later step failed; `registrationExpired` found the login
123
+ // claimed by the orphan-registration cleanup and wrote nothing — the person signs up again.
124
+ export const REGISTRATION_START_OUTCOMES = ['started', 'alreadyStarted', 'registrationExpired'];
118
125
  export const CreateRegistrationStartResultSchema = z
119
126
  .object({ outcome: z.enum(REGISTRATION_START_OUTCOMES) })
120
127
  .strict();
@@ -1 +1 @@
1
- {"version":3,"file":"users.js","sourceRoot":"","sources":["../../src/schemas/users.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for user accounts and the global role rosters.\r\n\r\nimport { z } from 'zod';\r\nimport { MAX_ADMIN_LIST_CHANGES } from '../constants/business.js';\r\nimport { userStatusSchema } from '../doc-schemas/atoms.js';\r\nimport { countSchema, displayNameSchema, repairReasonSchema, userIdSchema } from './atoms.js';\r\n\r\n// The signed-in caller finishes registration: profile, public identity, and the display-name\r\n// reservation are created for `request.auth.uid`. Email comes from the token, never the payload.\r\nexport const RegisterUserInputSchema = z\r\n .object({\r\n displayName: displayNameSchema,\r\n // The terms checkbox, re-checked server-side: only `true` registers.\r\n acceptedTerms: z.literal(true),\r\n })\r\n .strict();\r\nexport type RegisterUserInput = z.infer<typeof RegisterUserInputSchema>;\r\nexport const RegisterUserResultSchema = z.object({ userId: userIdSchema, displayName: z.string() }).strict();\r\nexport type RegisterUserResult = z.infer<typeof RegisterUserResultSchema>;\r\n\r\n// The register form's check before the login is created: is the name free? It runs before any\r\n// account exists, over the same name rule `registerUser` takes, and is a soft answer — the claim\r\n// itself is `registerUser`'s transaction, which refuses `already-exists` when two registrations\r\n// pass this check at once.\r\nexport const CheckDisplayNameAvailableInputSchema = z.object({ displayName: displayNameSchema }).strict();\r\nexport type CheckDisplayNameAvailableInput = z.infer<typeof CheckDisplayNameAvailableInputSchema>;\r\n// Why a name is not available. Uniqueness is the only rule a Q-Sports name is held to beyond its\r\n// input format.\r\nexport const DISPLAY_NAME_UNAVAILABLE_REASONS = ['taken'] as const;\r\nexport type DisplayNameUnavailableReason = (typeof DISPLAY_NAME_UNAVAILABLE_REASONS)[number];\r\nexport const CheckDisplayNameAvailableResultSchema = z\r\n .object({ available: z.boolean(), reason: z.enum(DISPLAY_NAME_UNAVAILABLE_REASONS).optional() })\r\n .strict();\r\nexport type CheckDisplayNameAvailableResult = z.infer<typeof CheckDisplayNameAvailableResultSchema>;\r\n\r\n/** The longest text an admin's account search takes: a name, a full email address, or a uid. */\r\nexport const MAX_USER_SEARCH_QUERY_LENGTH = 100;\r\n\r\n// Which read an admin's account search routes to: a full email address or a 28-character Firebase\r\n// Auth uid is an exact lookup (`lookupUserByEmailOrUid`), anything else a name search. Declared once:\r\n// the search box routes by it and the lookup callable re-derives the same answer, so a mis-routed\r\n// request never looks an email up as a uid or the other way round.\r\nexport const USER_LOOKUP_EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\nexport const USER_LOOKUP_UID_PATTERN = /^[A-Za-z0-9]{28}$/;\r\nexport type UserSearchKind = 'email' | 'uid' | 'name';\r\nexport function detectUserSearchKind(query: string): UserSearchKind {\r\n const trimmed = query.trim();\r\n if (USER_LOOKUP_EMAIL_PATTERN.test(trimmed)) return 'email';\r\n if (USER_LOOKUP_UID_PATTERN.test(trimmed)) return 'uid';\r\n return 'name';\r\n}\r\n\r\n// An admin finds one account by its exact email address or its uid. The answer carries the\r\n// owner-only email, so it is admin only.\r\nexport const LookupUserByEmailOrUidInputSchema = z\r\n .object({ query: z.string().trim().min(1).max(MAX_USER_SEARCH_QUERY_LENGTH) })\r\n .strict();\r\nexport type LookupUserByEmailOrUidInput = z.infer<typeof LookupUserByEmailOrUidInputSchema>;\r\nexport const LookedUpUserSchema = z\r\n .object({\r\n uid: userIdSchema,\r\n displayName: z.string(),\r\n email: z.string(),\r\n userStatus: userStatusSchema,\r\n // Present, and true, only for an account on the admin roster.\r\n isAdmin: z.literal(true).optional(),\r\n })\r\n .strict();\r\nexport type LookedUpUser = z.infer<typeof LookedUpUserSchema>;\r\n// The one exact match, or `null` when no account with a profile resolves.\r\nexport const LookupUserByEmailOrUidResultSchema = z.object({ user: LookedUpUserSchema.nullable() }).strict();\r\nexport type LookupUserByEmailOrUidResult = z.infer<typeof LookupUserByEmailOrUidResultSchema>;\r\n\r\n// An admin searches accounts by the start of their name, over public display identity. Ghosts are\r\n// not accounts and are left out; a banned account is found, with its status.\r\nexport const SearchPublicUsersInputSchema = z\r\n .object({ query: z.string().trim().min(1).max(MAX_USER_SEARCH_QUERY_LENGTH) })\r\n .strict();\r\nexport type SearchPublicUsersInput = z.infer<typeof SearchPublicUsersInputSchema>;\r\nexport const PublicUserSearchResultSchema = z\r\n .object({ uid: userIdSchema, displayName: z.string(), userStatus: userStatusSchema })\r\n .strict();\r\nexport type PublicUserSearchResult = z.infer<typeof PublicUserSearchResultSchema>;\r\nexport const SearchPublicUsersResultSchema = z.object({ users: z.array(PublicUserSearchResultSchema) }).strict();\r\nexport type SearchPublicUsersResult = z.infer<typeof SearchPublicUsersResultSchema>;\r\n\r\n// An admin renames a user. Self-service rename is not a Q-Sports feature.\r\nexport const UpdateDisplayNameInputSchema = z\r\n .object({ userId: userIdSchema, newDisplayName: displayNameSchema })\r\n .strict();\r\nexport type UpdateDisplayNameInput = z.infer<typeof UpdateDisplayNameInputSchema>;\r\nexport const UpdateDisplayNameResultSchema = z.object({ userId: userIdSchema, displayName: z.string() }).strict();\r\nexport type UpdateDisplayNameResult = z.infer<typeof UpdateDisplayNameResultSchema>;\r\n\r\n// An admin grants or revokes the two global roles on `_systemData/adminList`. Four named lists —\r\n// never a role/action discriminator (BACKEND-002).\r\nconst adminListChangeSchema = z.array(userIdSchema).max(MAX_ADMIN_LIST_CHANGES).optional();\r\nexport const UpdateAdminListInputSchema = z\r\n .object({\r\n addAdmins: adminListChangeSchema,\r\n removeAdmins: adminListChangeSchema,\r\n addReferees: adminListChangeSchema,\r\n removeReferees: adminListChangeSchema,\r\n })\r\n .strict();\r\nexport type UpdateAdminListInput = z.infer<typeof UpdateAdminListInputSchema>;\r\nexport const UpdateAdminListResultSchema = z\r\n .object({\r\n adminsGranted: countSchema,\r\n adminsRevoked: countSchema,\r\n refereesGranted: countSchema,\r\n refereesRevoked: countSchema,\r\n })\r\n .strict();\r\nexport type UpdateAdminListResult = z.infer<typeof UpdateAdminListResultSchema>;\r\n\r\n// An admin bans an account or lifts its ban. The reason is internal — recorded on the audit event,\r\n// never shown to the account (BACKEND-212). Banning or unbanning to the status the account already\r\n// holds changes nothing.\r\nexport const AdminUpdateUserStatusInputSchema = z\r\n .object({ userId: userIdSchema, userStatus: userStatusSchema, reason: repairReasonSchema })\r\n .strict();\r\nexport type AdminUpdateUserStatusInput = z.infer<typeof AdminUpdateUserStatusInputSchema>;\r\n\r\n// `changed` is whether the status moved.\r\nexport const AdminUpdateUserStatusResultSchema = z\r\n .object({\r\n userId: userIdSchema,\r\n userStatus: userStatusSchema,\r\n previousStatus: userStatusSchema,\r\n changed: z.boolean(),\r\n })\r\n .strict();\r\nexport type AdminUpdateUserStatusResult = z.infer<typeof AdminUpdateUserStatusResultSchema>;\r\n\r\n// The `details.reason` of the refusal to ban an account that holds admin standing (BACKEND-210), so\r\n// a client can tell it from every other refusal.\r\nexport const ADMIN_STANDING_BAN_REFUSAL_REASON = 'adminStandingTarget';\r\n\r\n// A signed-in login with no profile starts its registration, before `registerUser`: the record the\r\n// orphan-login cleanup finds it by, and the owner-only private record `registerUser` requires. The\r\n// caller is `request.auth.uid` and the email comes from its token, so it takes no input.\r\nexport const CreateRegistrationStartInputSchema = z.object({}).strict();\r\nexport type CreateRegistrationStartInput = z.infer<typeof CreateRegistrationStartInputSchema>;\r\n// `started` wrote both records; `alreadyStarted` found the registration already started and wrote\r\n// nothing — a retry, or a resume after a later step failed.\r\nexport const REGISTRATION_START_OUTCOMES = ['started', 'alreadyStarted'] as const;\r\nexport type RegistrationStartOutcome = (typeof REGISTRATION_START_OUTCOMES)[number];\r\nexport const CreateRegistrationStartResultSchema = z\r\n .object({ outcome: z.enum(REGISTRATION_START_OUTCOMES) })\r\n .strict();\r\nexport type CreateRegistrationStartResult = z.infer<typeof CreateRegistrationStartResultSchema>;\r\n"]}
1
+ {"version":3,"file":"users.js","sourceRoot":"","sources":["../../src/schemas/users.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for user accounts and the global role rosters.\n\nimport { z } from 'zod';\nimport { MAX_ADMIN_LIST_CHANGES } from '../constants/business.js';\nimport { userStatusSchema } from '../doc-schemas/atoms.js';\nimport { countSchema, displayNameSchema, repairReasonSchema, userIdSchema } from './atoms.js';\n\n// The signed-in caller finishes registration: profile, public identity, and the display-name\n// reservation are created for `request.auth.uid`. Email comes from the token, never the payload.\nexport const RegisterUserInputSchema = z\n .object({\n displayName: displayNameSchema,\n // The terms checkbox, re-checked server-side: only `true` registers.\n acceptedTerms: z.literal(true),\n })\n .strict();\nexport type RegisterUserInput = z.infer<typeof RegisterUserInputSchema>;\nexport const RegisterUserResultSchema = z.discriminatedUnion('status', [\n // The account is registered (or already was — an idempotent replay).\n z.object({ status: z.literal('registered'), userId: userIdSchema, displayName: z.string() }).strict(),\n // The orphan-registration cleanup claimed this login for deletion, so the registration cannot\n // finish on it; nothing is written and the person signs up again.\n z.object({ status: z.literal('registrationExpired') }).strict(),\n]);\nexport type RegisterUserResult = z.infer<typeof RegisterUserResultSchema>;\n\n// The register form's check before the login is created: is the name free? It runs before any\n// account exists, over the same name rule `registerUser` takes, and is a soft answer — the claim\n// itself is `registerUser`'s transaction, which refuses `already-exists` when two registrations\n// pass this check at once.\nexport const CheckDisplayNameAvailableInputSchema = z.object({ displayName: displayNameSchema }).strict();\nexport type CheckDisplayNameAvailableInput = z.infer<typeof CheckDisplayNameAvailableInputSchema>;\n// Why a name is not available. Uniqueness is the only rule a Q-Sports name is held to beyond its\n// input format.\nexport const DISPLAY_NAME_UNAVAILABLE_REASONS = ['taken'] as const;\nexport type DisplayNameUnavailableReason = (typeof DISPLAY_NAME_UNAVAILABLE_REASONS)[number];\nexport const CheckDisplayNameAvailableResultSchema = z\n .object({ available: z.boolean(), reason: z.enum(DISPLAY_NAME_UNAVAILABLE_REASONS).optional() })\n .strict();\nexport type CheckDisplayNameAvailableResult = z.infer<typeof CheckDisplayNameAvailableResultSchema>;\n\n/** The longest text an admin's account search takes: a name, a full email address, or a uid. */\nexport const MAX_USER_SEARCH_QUERY_LENGTH = 100;\n\n// Which read an admin's account search routes to: a full email address or a 28-character Firebase\n// Auth uid is an exact lookup (`lookupUserByEmailOrUid`), anything else a name search. Declared once:\n// the search box routes by it and the lookup callable re-derives the same answer, so a mis-routed\n// request never looks an email up as a uid or the other way round.\nexport const USER_LOOKUP_EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nexport const USER_LOOKUP_UID_PATTERN = /^[A-Za-z0-9]{28}$/;\nexport type UserSearchKind = 'email' | 'uid' | 'name';\nexport function detectUserSearchKind(query: string): UserSearchKind {\n const trimmed = query.trim();\n if (USER_LOOKUP_EMAIL_PATTERN.test(trimmed)) return 'email';\n if (USER_LOOKUP_UID_PATTERN.test(trimmed)) return 'uid';\n return 'name';\n}\n\n// An admin finds one account by its exact email address or its uid. The answer carries the\n// owner-only email, so it is admin only.\nexport const LookupUserByEmailOrUidInputSchema = z\n .object({ query: z.string().trim().min(1).max(MAX_USER_SEARCH_QUERY_LENGTH) })\n .strict();\nexport type LookupUserByEmailOrUidInput = z.infer<typeof LookupUserByEmailOrUidInputSchema>;\nexport const LookedUpUserSchema = z\n .object({\n uid: userIdSchema,\n displayName: z.string(),\n email: z.string(),\n userStatus: userStatusSchema,\n // Present, and true, only for an account on the admin roster.\n isAdmin: z.literal(true).optional(),\n })\n .strict();\nexport type LookedUpUser = z.infer<typeof LookedUpUserSchema>;\n// The one exact match, or `null` when no account with a profile resolves.\nexport const LookupUserByEmailOrUidResultSchema = z.object({ user: LookedUpUserSchema.nullable() }).strict();\nexport type LookupUserByEmailOrUidResult = z.infer<typeof LookupUserByEmailOrUidResultSchema>;\n\n// An admin searches accounts by the start of their name, over public display identity. Ghosts are\n// not accounts and are left out; a banned account is found, with its status.\nexport const SearchPublicUsersInputSchema = z\n .object({ query: z.string().trim().min(1).max(MAX_USER_SEARCH_QUERY_LENGTH) })\n .strict();\nexport type SearchPublicUsersInput = z.infer<typeof SearchPublicUsersInputSchema>;\nexport const PublicUserSearchResultSchema = z\n .object({ uid: userIdSchema, displayName: z.string(), userStatus: userStatusSchema })\n .strict();\nexport type PublicUserSearchResult = z.infer<typeof PublicUserSearchResultSchema>;\nexport const SearchPublicUsersResultSchema = z.object({ users: z.array(PublicUserSearchResultSchema) }).strict();\nexport type SearchPublicUsersResult = z.infer<typeof SearchPublicUsersResultSchema>;\n\n// An admin renames a user. Self-service rename is not a Q-Sports feature.\nexport const UpdateDisplayNameInputSchema = z\n .object({ userId: userIdSchema, newDisplayName: displayNameSchema })\n .strict();\nexport type UpdateDisplayNameInput = z.infer<typeof UpdateDisplayNameInputSchema>;\nexport const UpdateDisplayNameResultSchema = z.object({ userId: userIdSchema, displayName: z.string() }).strict();\nexport type UpdateDisplayNameResult = z.infer<typeof UpdateDisplayNameResultSchema>;\n\n// An admin grants or revokes the two global roles on `_systemData/adminList`. Four named lists —\n// never a role/action discriminator (BACKEND-002).\nconst adminListChangeSchema = z.array(userIdSchema).max(MAX_ADMIN_LIST_CHANGES).optional();\nexport const UpdateAdminListInputSchema = z\n .object({\n addAdmins: adminListChangeSchema,\n removeAdmins: adminListChangeSchema,\n addReferees: adminListChangeSchema,\n removeReferees: adminListChangeSchema,\n })\n .strict();\nexport type UpdateAdminListInput = z.infer<typeof UpdateAdminListInputSchema>;\nexport const UpdateAdminListResultSchema = z\n .object({\n adminsGranted: countSchema,\n adminsRevoked: countSchema,\n refereesGranted: countSchema,\n refereesRevoked: countSchema,\n })\n .strict();\nexport type UpdateAdminListResult = z.infer<typeof UpdateAdminListResultSchema>;\n\n// An admin bans an account or lifts its ban. The reason is internal — recorded on the audit event,\n// never shown to the account (BACKEND-212). Banning or unbanning to the status the account already\n// holds changes nothing.\nexport const AdminUpdateUserStatusInputSchema = z\n .object({ userId: userIdSchema, userStatus: userStatusSchema, reason: repairReasonSchema })\n .strict();\nexport type AdminUpdateUserStatusInput = z.infer<typeof AdminUpdateUserStatusInputSchema>;\n\n// `changed` is whether the status moved.\nexport const AdminUpdateUserStatusResultSchema = z\n .object({\n userId: userIdSchema,\n userStatus: userStatusSchema,\n previousStatus: userStatusSchema,\n changed: z.boolean(),\n })\n .strict();\nexport type AdminUpdateUserStatusResult = z.infer<typeof AdminUpdateUserStatusResultSchema>;\n\n// The `details.reason` of the refusal to ban an account that holds admin standing (BACKEND-210), so\n// a client can tell it from every other refusal.\nexport const ADMIN_STANDING_BAN_REFUSAL_REASON = 'adminStandingTarget';\n\n// A signed-in login with no profile starts its registration, before `registerUser`: the record the\n// orphan-login cleanup finds it by, and the owner-only private record `registerUser` requires. The\n// caller is `request.auth.uid` and the email comes from its token, so it takes no input.\nexport const CreateRegistrationStartInputSchema = z.object({}).strict();\nexport type CreateRegistrationStartInput = z.infer<typeof CreateRegistrationStartInputSchema>;\n// `started` wrote both records; `alreadyStarted` found the registration already started and wrote\n// nothing — a retry, or a resume after a later step failed; `registrationExpired` found the login\n// claimed by the orphan-registration cleanup and wrote nothing — the person signs up again.\nexport const REGISTRATION_START_OUTCOMES = ['started', 'alreadyStarted', 'registrationExpired'] as const;\nexport type RegistrationStartOutcome = (typeof REGISTRATION_START_OUTCOMES)[number];\nexport const CreateRegistrationStartResultSchema = z\n .object({ outcome: z.enum(REGISTRATION_START_OUTCOMES) })\n .strict();\nexport type CreateRegistrationStartResult = z.infer<typeof CreateRegistrationStartResultSchema>;\n"]}
@@ -13,6 +13,7 @@ export declare const AdminCreateWaiverTemplateResultSchema: z.ZodObject<{
13
13
  export type AdminCreateWaiverTemplateResult = z.infer<typeof AdminCreateWaiverTemplateResultSchema>;
14
14
  export declare const AdminUpdateWaiverTemplateInputSchema: z.ZodObject<{
15
15
  waiverTemplateId: z.ZodString;
16
+ expectedVersion: z.ZodNumber;
16
17
  title: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
17
18
  waiverText: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
18
19
  }, z.core.$strict>;
@@ -1 +1 @@
1
- {"version":3,"file":"waiver-templates.d.ts","sourceRoot":"","sources":["../../src/schemas/waiver-templates.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB,eAAO,MAAM,yBAAyB,wDAAsD,CAAC;AAC7F,eAAO,MAAM,wBAAwB,wDAAqD,CAAC;AAE3F,eAAO,MAAM,oCAAoC;;;kBAEtC,CAAC;AACZ,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC,CAAC;AAClG,eAAO,MAAM,qCAAqC;;;kBAEvC,CAAC;AACZ,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qCAAqC,CAAC,CAAC;AAIpG,eAAO,MAAM,oCAAoC;;;;kBAMtC,CAAC;AACZ,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC,CAAC;AAClG,eAAO,MAAM,qCAAqC;;;;kBAQvC,CAAC;AACZ,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qCAAqC,CAAC,CAAC;AAEpG,eAAO,MAAM,oCAAoC;;kBAEtC,CAAC;AACZ,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC,CAAC;AAClG,eAAO,MAAM,qCAAqC;;;;;;kBAKvC,CAAC;AACZ,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qCAAqC,CAAC,CAAC"}
1
+ {"version":3,"file":"waiver-templates.d.ts","sourceRoot":"","sources":["../../src/schemas/waiver-templates.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB,eAAO,MAAM,yBAAyB,wDAAsD,CAAC;AAC7F,eAAO,MAAM,wBAAwB,wDAAqD,CAAC;AAE3F,eAAO,MAAM,oCAAoC;;;kBAEtC,CAAC;AACZ,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC,CAAC;AAClG,eAAO,MAAM,qCAAqC;;;kBAEvC,CAAC;AACZ,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qCAAqC,CAAC,CAAC;AAMpG,eAAO,MAAM,oCAAoC;;;;;kBAOtC,CAAC;AACZ,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC,CAAC;AAClG,eAAO,MAAM,qCAAqC;;;;kBAQvC,CAAC;AACZ,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qCAAqC,CAAC,CAAC;AAEpG,eAAO,MAAM,oCAAoC;;kBAEtC,CAAC;AACZ,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC,CAAC;AAClG,eAAO,MAAM,qCAAqC;;;;;;kBAKvC,CAAC;AACZ,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qCAAqC,CAAC,CAAC"}
@@ -13,10 +13,13 @@ export const AdminCreateWaiverTemplateResultSchema = z
13
13
  .object({ waiverTemplateId: waiverTemplateIdSchema, version: waiverTemplateVersionNumberSchema })
14
14
  .strict();
15
15
  // The template's whole wording as the admin wants it to read. Wording that differs from the current
16
- // version publishes the next version; the same wording changes nothing.
16
+ // version publishes the next version; the same wording changes nothing. `expectedVersion` is the
17
+ // version the editor loaded: a save whose base is no longer current is refused, so a publication
18
+ // never brings back wording another admin has since replaced.
17
19
  export const AdminUpdateWaiverTemplateInputSchema = z
18
20
  .object({
19
21
  waiverTemplateId: waiverTemplateIdSchema,
22
+ expectedVersion: waiverTemplateVersionNumberSchema,
20
23
  title: waiverTemplateTitleSchema,
21
24
  waiverText: waiverTemplateTextSchema,
22
25
  })
@@ -1 +1 @@
1
- {"version":3,"file":"waiver-templates.js","sourceRoot":"","sources":["../../src/schemas/waiver-templates.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAE7F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EACL,sBAAsB,EACtB,iCAAiC,GAClC,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,mCAAmC,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EACL,iCAAiC,EACjC,kCAAkC,GACnC,MAAM,2BAA2B,CAAC;AAEnC,MAAM,CAAC,MAAM,yBAAyB,GAAG,eAAe,CAAC,kCAAkC,CAAC,CAAC;AAC7F,MAAM,CAAC,MAAM,wBAAwB,GAAG,eAAe,CAAC,iCAAiC,CAAC,CAAC;AAE3F,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC;KAClD,MAAM,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,UAAU,EAAE,wBAAwB,EAAE,CAAC;KAClF,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAC;KACnD,MAAM,CAAC,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,OAAO,EAAE,iCAAiC,EAAE,CAAC;KAChG,MAAM,EAAE,CAAC;AAGZ,oGAAoG;AACpG,wEAAwE;AACxE,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC;KAClD,MAAM,CAAC;IACN,gBAAgB,EAAE,sBAAsB;IACxC,KAAK,EAAE,yBAAyB;IAChC,UAAU,EAAE,wBAAwB;CACrC,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAC;KACnD,MAAM,CAAC;IACN,gBAAgB,EAAE,sBAAsB;IACxC,iDAAiD;IACjD,OAAO,EAAE,iCAAiC;IAC1C,8EAA8E;IAC9E,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;CACvB,CAAC;KACD,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC;KAClD,MAAM,CAAC,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,CAAC;KACpD,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAC;KACnD,MAAM,CAAC;IACN,gBAAgB,EAAE,sBAAsB;IACxC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,mCAAmC,CAAC;CACrD,CAAC;KACD,MAAM,EAAE,CAAC","sourcesContent":["// Callable contracts for waiver templates: create, save new wording, and delete. Admin only.\n\nimport { z } from 'zod';\nimport { textFieldSchema } from '../doc-schemas/atoms.js';\nimport {\n waiverTemplateIdSchema,\n waiverTemplateVersionNumberSchema,\n} from '../doc-schemas/waiver-template.js';\nimport { WAIVER_TEMPLATE_DELETE_OUTCOME_KEYS } from '../types/unions.js';\nimport {\n WAIVER_TEMPLATE_TEXT_INPUT_FORMAT,\n WAIVER_TEMPLATE_TITLE_INPUT_FORMAT,\n} from '../input-formats/index.js';\n\nexport const waiverTemplateTitleSchema = textFieldSchema(WAIVER_TEMPLATE_TITLE_INPUT_FORMAT);\nexport const waiverTemplateTextSchema = textFieldSchema(WAIVER_TEMPLATE_TEXT_INPUT_FORMAT);\n\nexport const AdminCreateWaiverTemplateInputSchema = z\n .object({ title: waiverTemplateTitleSchema, waiverText: waiverTemplateTextSchema })\n .strict();\nexport type AdminCreateWaiverTemplateInput = z.infer<typeof AdminCreateWaiverTemplateInputSchema>;\nexport const AdminCreateWaiverTemplateResultSchema = z\n .object({ waiverTemplateId: waiverTemplateIdSchema, version: waiverTemplateVersionNumberSchema })\n .strict();\nexport type AdminCreateWaiverTemplateResult = z.infer<typeof AdminCreateWaiverTemplateResultSchema>;\n\n// The template's whole wording as the admin wants it to read. Wording that differs from the current\n// version publishes the next version; the same wording changes nothing.\nexport const AdminUpdateWaiverTemplateInputSchema = z\n .object({\n waiverTemplateId: waiverTemplateIdSchema,\n title: waiverTemplateTitleSchema,\n waiverText: waiverTemplateTextSchema,\n })\n .strict();\nexport type AdminUpdateWaiverTemplateInput = z.infer<typeof AdminUpdateWaiverTemplateInputSchema>;\nexport const AdminUpdateWaiverTemplateResultSchema = z\n .object({\n waiverTemplateId: waiverTemplateIdSchema,\n // The template's current version after the save.\n version: waiverTemplateVersionNumberSchema,\n // False when the wording matched the current version and nothing was written.\n published: z.boolean(),\n })\n .strict();\nexport type AdminUpdateWaiverTemplateResult = z.infer<typeof AdminUpdateWaiverTemplateResultSchema>;\n\nexport const AdminDeleteWaiverTemplateInputSchema = z\n .object({ waiverTemplateId: waiverTemplateIdSchema })\n .strict();\nexport type AdminDeleteWaiverTemplateInput = z.infer<typeof AdminDeleteWaiverTemplateInputSchema>;\nexport const AdminDeleteWaiverTemplateResultSchema = z\n .object({\n waiverTemplateId: waiverTemplateIdSchema,\n outcome: z.enum(WAIVER_TEMPLATE_DELETE_OUTCOME_KEYS),\n })\n .strict();\nexport type AdminDeleteWaiverTemplateResult = z.infer<typeof AdminDeleteWaiverTemplateResultSchema>;\n"]}
1
+ {"version":3,"file":"waiver-templates.js","sourceRoot":"","sources":["../../src/schemas/waiver-templates.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAE7F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EACL,sBAAsB,EACtB,iCAAiC,GAClC,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,mCAAmC,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EACL,iCAAiC,EACjC,kCAAkC,GACnC,MAAM,2BAA2B,CAAC;AAEnC,MAAM,CAAC,MAAM,yBAAyB,GAAG,eAAe,CAAC,kCAAkC,CAAC,CAAC;AAC7F,MAAM,CAAC,MAAM,wBAAwB,GAAG,eAAe,CAAC,iCAAiC,CAAC,CAAC;AAE3F,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC;KAClD,MAAM,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,UAAU,EAAE,wBAAwB,EAAE,CAAC;KAClF,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAC;KACnD,MAAM,CAAC,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,OAAO,EAAE,iCAAiC,EAAE,CAAC;KAChG,MAAM,EAAE,CAAC;AAGZ,oGAAoG;AACpG,iGAAiG;AACjG,iGAAiG;AACjG,8DAA8D;AAC9D,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC;KAClD,MAAM,CAAC;IACN,gBAAgB,EAAE,sBAAsB;IACxC,eAAe,EAAE,iCAAiC;IAClD,KAAK,EAAE,yBAAyB;IAChC,UAAU,EAAE,wBAAwB;CACrC,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAC;KACnD,MAAM,CAAC;IACN,gBAAgB,EAAE,sBAAsB;IACxC,iDAAiD;IACjD,OAAO,EAAE,iCAAiC;IAC1C,8EAA8E;IAC9E,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;CACvB,CAAC;KACD,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC;KAClD,MAAM,CAAC,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,CAAC;KACpD,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAC;KACnD,MAAM,CAAC;IACN,gBAAgB,EAAE,sBAAsB;IACxC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,mCAAmC,CAAC;CACrD,CAAC;KACD,MAAM,EAAE,CAAC","sourcesContent":["// Callable contracts for waiver templates: create, save new wording, and delete. Admin only.\n\nimport { z } from 'zod';\nimport { textFieldSchema } from '../doc-schemas/atoms.js';\nimport {\n waiverTemplateIdSchema,\n waiverTemplateVersionNumberSchema,\n} from '../doc-schemas/waiver-template.js';\nimport { WAIVER_TEMPLATE_DELETE_OUTCOME_KEYS } from '../types/unions.js';\nimport {\n WAIVER_TEMPLATE_TEXT_INPUT_FORMAT,\n WAIVER_TEMPLATE_TITLE_INPUT_FORMAT,\n} from '../input-formats/index.js';\n\nexport const waiverTemplateTitleSchema = textFieldSchema(WAIVER_TEMPLATE_TITLE_INPUT_FORMAT);\nexport const waiverTemplateTextSchema = textFieldSchema(WAIVER_TEMPLATE_TEXT_INPUT_FORMAT);\n\nexport const AdminCreateWaiverTemplateInputSchema = z\n .object({ title: waiverTemplateTitleSchema, waiverText: waiverTemplateTextSchema })\n .strict();\nexport type AdminCreateWaiverTemplateInput = z.infer<typeof AdminCreateWaiverTemplateInputSchema>;\nexport const AdminCreateWaiverTemplateResultSchema = z\n .object({ waiverTemplateId: waiverTemplateIdSchema, version: waiverTemplateVersionNumberSchema })\n .strict();\nexport type AdminCreateWaiverTemplateResult = z.infer<typeof AdminCreateWaiverTemplateResultSchema>;\n\n// The template's whole wording as the admin wants it to read. Wording that differs from the current\n// version publishes the next version; the same wording changes nothing. `expectedVersion` is the\n// version the editor loaded: a save whose base is no longer current is refused, so a publication\n// never brings back wording another admin has since replaced.\nexport const AdminUpdateWaiverTemplateInputSchema = z\n .object({\n waiverTemplateId: waiverTemplateIdSchema,\n expectedVersion: waiverTemplateVersionNumberSchema,\n title: waiverTemplateTitleSchema,\n waiverText: waiverTemplateTextSchema,\n })\n .strict();\nexport type AdminUpdateWaiverTemplateInput = z.infer<typeof AdminUpdateWaiverTemplateInputSchema>;\nexport const AdminUpdateWaiverTemplateResultSchema = z\n .object({\n waiverTemplateId: waiverTemplateIdSchema,\n // The template's current version after the save.\n version: waiverTemplateVersionNumberSchema,\n // False when the wording matched the current version and nothing was written.\n published: z.boolean(),\n })\n .strict();\nexport type AdminUpdateWaiverTemplateResult = z.infer<typeof AdminUpdateWaiverTemplateResultSchema>;\n\nexport const AdminDeleteWaiverTemplateInputSchema = z\n .object({ waiverTemplateId: waiverTemplateIdSchema })\n .strict();\nexport type AdminDeleteWaiverTemplateInput = z.infer<typeof AdminDeleteWaiverTemplateInputSchema>;\nexport const AdminDeleteWaiverTemplateResultSchema = z\n .object({\n waiverTemplateId: waiverTemplateIdSchema,\n outcome: z.enum(WAIVER_TEMPLATE_DELETE_OUTCOME_KEYS),\n })\n .strict();\nexport type AdminDeleteWaiverTemplateResult = z.infer<typeof AdminDeleteWaiverTemplateResultSchema>;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"basketball-scoring.js","sourceRoot":"","sources":["../../src/sports/basketball-scoring.ts"],"names":[],"mappings":"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","sourcesContent":["// The basketball adapter's scoring, display, and bulk-entry members. Basketball is player-scored: a\r\n// shot credits its scorer's points and its team's score, and — when it names one — its assister's\r\n// assists, all on the one event (SPORT-003).\r\n//\r\n// `apply` and `undo` are one function over an event's effects with opposite signs, so they are exact\r\n// inverses by construction (SPORT-103).\r\n\r\nimport { z } from 'zod';\r\nimport {\r\n BASKETBALL_FANTASY_POINT_WEIGHTS,\r\n BASKETBALL_POINTS_BY_EVENT_TYPE,\r\n MAX_STAT_EVENTS_PER_WRITE,\r\n NOT_ON_GAME_ROSTER_MESSAGE,\r\n} from '../constants/sports.js';\r\nimport type { BasketballPlayerStats, BasketballTeamStats, GameStatEvent } from '../doc-schemas/game-stats.js';\r\nimport type { BasketballGameStats, GameStats } from '../doc-schemas/sport-game.js';\r\nimport { buildGameRosterPlayerId, parseGameRosterPlayerId } from '../ids/compound-ids.js';\r\nimport {\r\n BASKETBALL_ASSISTABLE_SHOT_EVENT_TYPE_KEYS,\r\n BASKETBALL_ASSIST_EVENT_TYPE,\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_REBOUND_EVENT_TYPE,\r\n BASKETBALL_SCORE_EVENT_TYPE_KEYS,\r\n BASKETBALL_STAT_EVENT_TYPE_KEYS,\r\n BASKETBALL_TEAM_STAT_KEYS,\r\n BASKETBALL_THREE_POINT_EVENT_TYPE,\r\n BASKETBALL_TIMEOUT_EVENT_TYPE,\r\n BASKETBALL_TWO_POINT_EVENT_TYPE,\r\n} from '../types/sports.js';\r\nimport type {\r\n BasketballPlayerStatKey,\r\n BasketballStatEventType,\r\n BasketballTeamStatKey,\r\n} from '../types/sports.js';\r\nimport { PLAYER_STAT_LINE_KIND_KEYS } from '../types/stats.js';\r\nimport type { StatLineKind } from '../types/stats.js';\r\nimport {\r\n BULK_ENTRY_TOO_LARGE_MESSAGE,\r\n bulkEntryCountField,\r\n type BulkEntryContext,\r\n type PlayerLinesBulkEntry,\r\n type PlayerLinesValues,\r\n type StatEventDraft,\r\n} from './bulk-entry.js';\r\nimport { buildGameContribution, decideParticipation, type ContributionSpec } from './contribution.js';\r\nimport {\r\n FINALIZATION_READY,\r\n STAT_EVENT_ACCEPTED,\r\n isAllZeroLine,\r\n isSportStatEventIn,\r\n isStatCorrection,\r\n refuseStatEvent,\r\n type CorrectableFields,\r\n type GameTeamLine,\r\n type SportScoring,\r\n type SportStatEventBody,\r\n type StatCorrectionBody,\r\n type StatEventBody,\r\n type StatLineValues,\r\n} from './scoring.js';\r\nimport {\r\n describeStoreEvent,\r\n formatSignedValue,\r\n type PlayerEventsScoringPanel,\r\n type Scoreboard,\r\n type StatEventLabel,\r\n type StatEventNameResolver,\r\n type StatFieldLabels,\r\n} from './scoring-display.js';\r\n\r\ntype BasketballEvent = Extract<SportStatEventBody, { type: BasketballStatEventType }>;\r\ntype PlayerCounters = Record<BasketballPlayerStatKey, number>;\r\n\r\nfunction isBasketballEvent(event: StatEventBody | undefined): event is BasketballEvent {\r\n return isSportStatEventIn(BASKETBALL_STAT_EVENT_TYPE_KEYS, event);\r\n}\r\n\r\n// The registry chose this adapter by the game's `leagueType`, so the rollup it is handed is a\r\n// basketball game's (SPORT-002).\r\nfunction ownStats(state: GameStats): BasketballGameStats {\r\n return state as BasketballGameStats;\r\n}\r\n\r\nfunction ownTeamLine(line: GameTeamLine): BasketballTeamStats {\r\n return line as BasketballTeamStats;\r\n}\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Lines\r\n// ---------------------------------------------------------------------------------------------\r\n\r\n/**\r\n * Fantasy points (FP) of a basketball line: each player counter times its weight. Every stored\r\n * `fantasyPoints` equals this over the counters of its own line; `deriveLine` is what applies it.\r\n */\r\nexport function basketballFantasyPoints(line: Pick<BasketballPlayerStats, BasketballPlayerStatKey>): number {\r\n return BASKETBALL_PLAYER_STAT_KEYS.reduce(\r\n (total, key) => total + line[key] * BASKETBALL_FANTASY_POINT_WEIGHTS[key],\r\n 0,\r\n );\r\n}\r\n\r\nconst FANTASY_POINTS_FIELD = 'fantasyPoints' satisfies keyof BasketballPlayerStats;\r\nconst PLAYER_LINE_KINDS: readonly StatLineKind[] = PLAYER_STAT_LINE_KIND_KEYS;\r\n\r\nexport function emptyBasketballTeamLine(): BasketballTeamStats {\r\n return Object.fromEntries(BASKETBALL_TEAM_STAT_KEYS.map((key) => [key, 0])) as BasketballTeamStats;\r\n}\r\n\r\nfunction emptyPlayerCounters(): PlayerCounters {\r\n return Object.fromEntries(BASKETBALL_PLAYER_STAT_KEYS.map((key) => [key, 0])) as PlayerCounters;\r\n}\r\n\r\nfunction counterOf(line: StatLineValues, field: string): number {\r\n const value = line[field] ?? 0;\r\n if (typeof value !== 'number') throw new TypeError(`A basketball line's ${field} is not a number.`);\r\n return value;\r\n}\r\n\r\nfunction playerCountersOf(line: StatLineValues | undefined): PlayerCounters {\r\n const counters = emptyPlayerCounters();\r\n if (line === undefined) return counters;\r\n for (const key of BASKETBALL_PLAYER_STAT_KEYS) counters[key] = counterOf(line, key);\r\n return counters;\r\n}\r\n\r\n// FP is an individual stat: it goes on the four player kinds and on no team kind.\r\nfunction deriveBasketballLine(kind: StatLineKind, line: StatLineValues): StatLineValues {\r\n const withoutDerived = Object.fromEntries(Object.entries(line).filter(([field]) => field !== FANTASY_POINTS_FIELD));\r\n if (!PLAYER_LINE_KINDS.includes(kind)) return withoutDerived;\r\n return { ...withoutDerived, [FANTASY_POINTS_FIELD]: basketballFantasyPoints(playerCountersOf(line)) };\r\n}\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Events and their effects\r\n// ---------------------------------------------------------------------------------------------\r\n\r\nconst CORRECTABLE_FIELDS: CorrectableFields = {\r\n team: BASKETBALL_TEAM_STAT_KEYS,\r\n player: BASKETBALL_PLAYER_STAT_KEYS,\r\n};\r\n\r\nconst TALLY_FIELD = {\r\n [BASKETBALL_REBOUND_EVENT_TYPE]: 'rebounds',\r\n [BASKETBALL_ASSIST_EVENT_TYPE]: 'assists',\r\n} as const satisfies Record<(typeof BASKETBALL_PLAYER_TALLY_EVENT_TYPE_KEYS)[number], BasketballPlayerStatKey>;\r\n\r\ninterface LineChange<Field extends string> {\r\n /** The team id of a team line, or the roster-entry id of a player line. */\r\n readonly line: string;\r\n readonly field: Field;\r\n readonly amount: number;\r\n}\r\n\r\ninterface Effects {\r\n readonly team: readonly LineChange<BasketballTeamStatKey>[];\r\n readonly player: readonly LineChange<BasketballPlayerStatKey>[];\r\n}\r\n\r\nfunction assisterOf(event: StatEventBody): string | undefined {\r\n return 'assistedByUserId' in event && typeof event.assistedByUserId === 'string' ? event.assistedByUserId : undefined;\r\n}\r\n\r\nfunction namesPlayer(event: StatEventBody): boolean {\r\n return 'playerUserId' in event && event.playerUserId !== undefined;\r\n}\r\n\r\nfunction effectsOf(event: BasketballEvent): Effects {\r\n if (event.type === BASKETBALL_TIMEOUT_EVENT_TYPE) {\r\n return { team: [{ line: event.teamId, field: 'timeouts', amount: 1 }], player: [] };\r\n }\r\n const scorer = buildGameRosterPlayerId(event.teamId, event.playerUserId);\r\n if (event.type === BASKETBALL_BULK_EDIT_EVENT_TYPE) {\r\n // A scorer's points edit keeps the team's score the sum of its players' points.\r\n return {\r\n team: event.stat === 'points' ? [{ line: event.teamId, field: 'score', amount: event.value }] : [],\r\n player: [{ line: scorer, field: event.stat, amount: event.value }],\r\n };\r\n }\r\n\r\n const team: LineChange<BasketballTeamStatKey>[] = [];\r\n const player: LineChange<BasketballPlayerStatKey>[] = [];\r\n const points = BASKETBALL_POINTS_BY_EVENT_TYPE[event.type];\r\n if (points > 0) {\r\n team.push({ line: event.teamId, field: 'score', amount: points });\r\n player.push({ line: scorer, field: 'points', amount: points });\r\n }\r\n if (event.type === BASKETBALL_REBOUND_EVENT_TYPE || event.type === BASKETBALL_ASSIST_EVENT_TYPE) {\r\n player.push({ line: scorer, field: TALLY_FIELD[event.type], amount: 1 });\r\n }\r\n const assister = assisterOf(event);\r\n if (assister !== undefined) {\r\n player.push({ line: buildGameRosterPlayerId(event.teamId, assister), field: 'assists', amount: 1 });\r\n }\r\n return { team, player };\r\n}\r\n\r\nfunction correctionEffects(event: StatCorrectionBody): Effects {\r\n const fields = event.playerUserId === undefined ? CORRECTABLE_FIELDS.team : CORRECTABLE_FIELDS.player;\r\n if (!fields.includes(event.stat)) {\r\n throw new Error(`A basketball correction cannot change ${event.stat} on a ${event.playerUserId === undefined ? 'team' : 'player'} line.`);\r\n }\r\n // A correction moves only its own field: a player-points correction does not move the team score.\r\n return event.playerUserId === undefined\r\n ? { team: [{ line: event.teamId, field: event.stat as BasketballTeamStatKey, amount: event.value }], player: [] }\r\n : {\r\n team: [],\r\n player: [\r\n {\r\n line: buildGameRosterPlayerId(event.teamId, event.playerUserId),\r\n field: event.stat as BasketballPlayerStatKey,\r\n amount: event.value,\r\n },\r\n ],\r\n };\r\n}\r\n\r\nfunction applyEffects(state: BasketballGameStats, effects: Effects, sign: 1 | -1): BasketballGameStats {\r\n const teamStats = { ...state.teamStats };\r\n for (const change of effects.team) {\r\n const line = { ...(teamStats[change.line] ?? emptyBasketballTeamLine()) };\r\n line[change.field] += sign * change.amount;\r\n teamStats[change.line] = line;\r\n }\r\n\r\n const playerStats = { ...state.playerStats };\r\n for (const change of effects.player) {\r\n const counters = playerCountersOf(playerStats[change.line]);\r\n counters[change.field] += sign * change.amount;\r\n if (isAllZeroLine(counters, BASKETBALL_PLAYER_STAT_KEYS)) delete playerStats[change.line];\r\n else playerStats[change.line] = deriveBasketballLine('gamePlayer', counters) as BasketballPlayerStats;\r\n }\r\n return { teamStats, playerStats };\r\n}\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Validation — the same rules the bulk form holds, re-checked on the server (SPORT-006)\r\n// ---------------------------------------------------------------------------------------------\r\n\r\nfunction isAssistableShot(type: BasketballStatEventType): boolean {\r\n return (BASKETBALL_ASSISTABLE_SHOT_EVENT_TYPE_KEYS as readonly string[]).includes(type);\r\n}\r\n\r\nconst validate: SportScoring['validate'] = (stateIn, event, roster) => {\r\n if (!isBasketballEvent(event)) return refuseStatEvent('eventTypeNotInSport');\r\n if (!roster.teamIds.includes(event.teamId)) return refuseStatEvent('teamNotInGame');\r\n if (event.type === BASKETBALL_TIMEOUT_EVENT_TYPE) {\r\n return namesPlayer(event) || assisterOf(event) !== undefined ? refuseStatEvent('playerNotAllowed') : STAT_EVENT_ACCEPTED;\r\n }\r\n\r\n const scorer = buildGameRosterPlayerId(event.teamId, event.playerUserId);\r\n if (!roster.rosterPlayerIds.has(scorer)) return refuseStatEvent('playerNotRostered');\r\n\r\n const assister = assisterOf(event);\r\n if (assister !== undefined) {\r\n if (!isAssistableShot(event.type) || assister === event.playerUserId) return refuseStatEvent('assistNotAllowed');\r\n if (!roster.rosterPlayerIds.has(buildGameRosterPlayerId(event.teamId, assister))) {\r\n return refuseStatEvent('assisterNotRostered');\r\n }\r\n }\r\n\r\n if (event.type === BASKETBALL_BULK_EDIT_EVENT_TYPE) {\r\n if (!Number.isInteger(event.value) || event.value === 0) return refuseStatEvent('bulkValueInvalid');\r\n const state = ownStats(stateIn);\r\n const current = playerCountersOf(state.playerStats[scorer])[event.stat];\r\n if (event.previousValue !== current) return refuseStatEvent('bulkStale');\r\n if (current + event.value < 0) return refuseStatEvent('bulkValueInvalid');\r\n const teamScore = (state.teamStats[event.teamId] ?? emptyBasketballTeamLine()).score;\r\n if (event.stat === 'points' && teamScore + event.value < 0) return refuseStatEvent('bulkValueInvalid');\r\n }\r\n return STAT_EVENT_ACCEPTED;\r\n};\r\n\r\n// What a completed basketball game adds: each entry's points, rebounds, assists, and FP to its row,\r\n// and the team's rebounds and assists to its standings line. A present entry with no points,\r\n// rebounds, or assists is credited no game played — zero points alone is not exclusion.\r\nconst BASKETBALL_CONTRIBUTION: ContributionSpec = {\r\n playerStatKeys: BASKETBALL_PLAYER_STAT_KEYS,\r\n teamSeasonPlayerSums: ['rebounds', 'assists'] satisfies BasketballPlayerStatKey[],\r\n zeroLineIsNonScoring: true,\r\n deriveLine: deriveBasketballLine,\r\n};\r\n\r\nexport const BASKETBALL_SCORING: SportScoring = {\r\n validate,\r\n apply: (state, event) => {\r\n if (isStatCorrection(event)) return applyEffects(ownStats(state), correctionEffects(event), 1);\r\n if (!isBasketballEvent(event)) throw new Error(`The basketball adapter does not apply ${event.type}.`);\r\n return applyEffects(ownStats(state), effectsOf(event), 1);\r\n },\r\n undo: (state, target) => {\r\n if (!isBasketballEvent(target)) throw new Error(`The basketball adapter does not undo ${target.type}.`);\r\n return applyEffects(ownStats(state), effectsOf(target), -1);\r\n },\r\n deriveLine: deriveBasketballLine,\r\n correctableFields: CORRECTABLE_FIELDS,\r\n // Played in no rounds, and finalized by hand whenever the scorer chooses.\r\n nextRound: () => null,\r\n finalizationReadiness: () => FINALIZATION_READY,\r\n participation: (state, rosterPlayerIds, absentRosterPlayerIds) =>\r\n decideParticipation(BASKETBALL_CONTRIBUTION, state, rosterPlayerIds, absentRosterPlayerIds),\r\n contribution: (game) => buildGameContribution(BASKETBALL_CONTRIBUTION, game),\r\n};\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Display\r\n// ---------------------------------------------------------------------------------------------\r\n\r\nexport const BASKETBALL_EVENT_LABELS = {\r\n [BASKETBALL_ONE_POINT_EVENT_TYPE]: { button: '+1 PT', play: '1-point basket' },\r\n [BASKETBALL_TWO_POINT_EVENT_TYPE]: { button: '+2 PT', play: '2-point basket' },\r\n [BASKETBALL_THREE_POINT_EVENT_TYPE]: { button: '+3 PT', play: '3-point basket' },\r\n [BASKETBALL_REBOUND_EVENT_TYPE]: { button: 'Rebound', play: 'Rebound' },\r\n [BASKETBALL_ASSIST_EVENT_TYPE]: { button: 'Assist', play: 'Assist' },\r\n [BASKETBALL_TIMEOUT_EVENT_TYPE]: { button: 'Timeout', play: 'Timeout' },\r\n [BASKETBALL_BULK_EDIT_EVENT_TYPE]: { button: 'Bulk entry', play: 'Bulk entry' },\r\n} as const satisfies Record<BasketballStatEventType, StatEventLabel>;\r\n\r\nexport const BASKETBALL_FIELD_LABELS = {\r\n team: { score: 'Score', timeouts: 'Timeouts' },\r\n player: { points: 'Points', rebounds: 'Rebounds', assists: 'Assists' },\r\n} as const satisfies StatFieldLabels<BasketballTeamStatKey, BasketballPlayerStatKey>;\r\n\r\nexport function describeBasketballEvent(event: GameStatEvent, resolve: StatEventNameResolver): string {\r\n const storeEvent = describeStoreEvent(event, resolve, BASKETBALL_FIELD_LABELS);\r\n if (storeEvent !== null) return storeEvent;\r\n if (!isBasketballEvent(event)) return event.type;\r\n\r\n const team = resolve.team(event.teamId);\r\n if (event.type === BASKETBALL_TIMEOUT_EVENT_TYPE) return `${team}: ${BASKETBALL_EVENT_LABELS[event.type].play}`;\r\n\r\n const player = `${resolve.player(event.playerUserId)} (${team})`;\r\n if (event.type === BASKETBALL_BULK_EDIT_EVENT_TYPE) {\r\n const field = BASKETBALL_FIELD_LABELS.player[event.stat].toLowerCase();\r\n return `${player}: ${formatSignedValue(event.value)} ${field} (${BASKETBALL_EVENT_LABELS[event.type].play.toLowerCase()})`;\r\n }\r\n const play = `${player}: ${BASKETBALL_EVENT_LABELS[event.type].play}`;\r\n const assister = assisterOf(event);\r\n return assister === undefined ? play : `${play}, assisted by ${resolve.player(assister)}`;\r\n}\r\n\r\nfunction sumOf(lines: readonly { readonly rebounds: number; readonly assists: number }[], field: 'rebounds' | 'assists'): number {\r\n return lines.reduce((total, line) => total + line[field], 0);\r\n}\r\n\r\nexport const BASKETBALL_SCOREBOARD: Scoreboard = {\r\n figures: [\r\n { id: 'points', label: BASKETBALL_FIELD_LABELS.player.points, value: (teamLine) => teamLine.score },\r\n { id: 'rebounds', label: BASKETBALL_FIELD_LABELS.player.rebounds, value: (_teamLine, sideLines) => sumOf(sideLines, 'rebounds') },\r\n { id: 'assists', label: BASKETBALL_FIELD_LABELS.player.assists, value: (_teamLine, sideLines) => sumOf(sideLines, 'assists') },\r\n { id: 'timeouts', label: BASKETBALL_FIELD_LABELS.team.timeouts, value: (teamLine) => ownTeamLine(teamLine).timeouts },\r\n ],\r\n jumpBall: true,\r\n};\r\n\r\nexport const BASKETBALL_SCORING_PANEL: PlayerEventsScoringPanel = {\r\n kind: 'playerEvents',\r\n playerEventTypes: [...BASKETBALL_SCORE_EVENT_TYPE_KEYS, ...BASKETBALL_PLAYER_TALLY_EVENT_TYPE_KEYS],\r\n assistableEventTypes: BASKETBALL_ASSISTABLE_SHOT_EVENT_TYPE_KEYS,\r\n teamEventTypes: [BASKETBALL_TIMEOUT_EVENT_TYPE],\r\n};\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Bulk entry — one row per roster entry, absent entries included\r\n// ---------------------------------------------------------------------------------------------\r\n\r\nexport const BASKETBALL_TEAM_SCORE_FLOOR_MESSAGE = \"These changes would leave a team's score below zero.\";\r\n\r\nconst playerLineValuesSchema = z.strictObject(\r\n Object.fromEntries(BASKETBALL_PLAYER_STAT_KEYS.map((key) => [key, bulkEntryCountField])) as Record<\r\n BasketballPlayerStatKey,\r\n typeof bulkEntryCountField\r\n >,\r\n);\r\n\r\nfunction currentPlayerCounters(context: BulkEntryContext, entryId: string): PlayerCounters {\r\n return playerCountersOf(ownStats(context.state).playerStats[entryId]);\r\n}\r\n\r\nfunction bulkDrafts(values: PlayerLinesValues, context: BulkEntryContext): StatEventDraft[] {\r\n const increases: StatEventDraft[] = [];\r\n const decreases: StatEventDraft[] = [];\r\n for (const entryId of context.rosterPlayerIds) {\r\n const entered = values.lines[entryId];\r\n const entry = parseGameRosterPlayerId(entryId);\r\n if (entered === undefined || entry === null) continue;\r\n const before = currentPlayerCounters(context, entryId);\r\n for (const stat of BASKETBALL_PLAYER_STAT_KEYS) {\r\n const value = (entered[stat] ?? before[stat]) - before[stat];\r\n if (value === 0) continue;\r\n const draft: StatEventDraft = {\r\n type: BASKETBALL_BULK_EDIT_EVENT_TYPE,\r\n teamId: entry.teamId,\r\n playerUserId: entry.userId,\r\n stat,\r\n value,\r\n previousValue: before[stat],\r\n };\r\n (value > 0 ? increases : decreases).push(draft);\r\n }\r\n }\r\n // Every increase before any decrease, so a team's running score never dips below the floor its\r\n // final score clears — each draft passes `validate` against the state the ones before it leave.\r\n return [...increases, ...decreases];\r\n}\r\n\r\nexport const BASKETBALL_BULK_ENTRY: PlayerLinesBulkEntry = {\r\n kind: 'playerLines',\r\n formDefaults: (context) => ({\r\n lines: Object.fromEntries(context.rosterPlayerIds.map((entryId) => [entryId, currentPlayerCounters(context, entryId)])),\r\n }),\r\n formSchema: (context) => {\r\n const roster = new Set(context.rosterPlayerIds);\r\n return z.object({ lines: z.record(z.string(), playerLineValuesSchema) }).superRefine((values, issues) => {\r\n for (const entryId of Object.keys(values.lines)) {\r\n if (!roster.has(entryId)) {\r\n issues.addIssue({ code: 'custom', path: ['lines', entryId], message: NOT_ON_GAME_ROSTER_MESSAGE });\r\n }\r\n }\r\n const state = ownStats(context.state);\r\n for (const teamId of context.game.teamIds) {\r\n let score = (state.teamStats[teamId] ?? emptyBasketballTeamLine()).score;\r\n for (const [entryId, entered] of Object.entries(values.lines)) {\r\n if (parseGameRosterPlayerId(entryId)?.teamId !== teamId) continue;\r\n score += entered.points - currentPlayerCounters(context, entryId).points;\r\n }\r\n if (score < 0) issues.addIssue({ code: 'custom', path: ['lines'], message: BASKETBALL_TEAM_SCORE_FLOOR_MESSAGE });\r\n }\r\n if (bulkDrafts(values, context).length > MAX_STAT_EVENTS_PER_WRITE) {\r\n issues.addIssue({ code: 'custom', path: ['lines'], message: BULK_ENTRY_TOO_LARGE_MESSAGE });\r\n }\r\n });\r\n },\r\n toEvents: bulkDrafts,\r\n};\r\n"]}
1
+ {"version":3,"file":"basketball-scoring.js","sourceRoot":"","sources":["../../src/sports/basketball-scoring.ts"],"names":[],"mappings":"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","sourcesContent":["// The basketball adapter's scoring, display, and bulk-entry members. Basketball is player-scored: a\n// shot credits its scorer's points and its team's score, and — when it names one — its assister's\n// assists, all on the one event (SPORT-003).\n//\n// `apply` and `undo` are one function over an event's effects with opposite signs, so they are exact\n// inverses by construction (SPORT-103).\n\nimport { z } from 'zod';\nimport {\n BASKETBALL_FANTASY_POINT_WEIGHTS,\n BASKETBALL_POINTS_BY_EVENT_TYPE,\n MAX_STAT_EVENTS_PER_WRITE,\n NOT_ON_GAME_ROSTER_MESSAGE,\n} from '../constants/sports.js';\nimport type { BasketballPlayerStats, BasketballTeamStats, GameStatEvent } from '../doc-schemas/game-stats.js';\nimport type { BasketballGameStats, GameStats } from '../doc-schemas/sport-game.js';\nimport { buildGameRosterPlayerId, parseGameRosterPlayerId } from '../ids/compound-ids.js';\nimport {\n BASKETBALL_ASSISTABLE_SHOT_EVENT_TYPE_KEYS,\n BASKETBALL_ASSIST_EVENT_TYPE,\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_REBOUND_EVENT_TYPE,\n BASKETBALL_SCORE_EVENT_TYPE_KEYS,\n BASKETBALL_STAT_EVENT_TYPE_KEYS,\n BASKETBALL_TEAM_STAT_KEYS,\n BASKETBALL_THREE_POINT_EVENT_TYPE,\n BASKETBALL_TIMEOUT_EVENT_TYPE,\n BASKETBALL_TWO_POINT_EVENT_TYPE,\n} from '../types/sports.js';\nimport type {\n BasketballPlayerStatKey,\n BasketballStatEventType,\n BasketballTeamStatKey,\n} from '../types/sports.js';\nimport { PLAYER_STAT_LINE_KIND_KEYS } from '../types/stats.js';\nimport type { StatLineKind } from '../types/stats.js';\nimport {\n BULK_ENTRY_TOO_LARGE_MESSAGE,\n bulkEntryCountField,\n type BulkEntryContext,\n type PlayerLinesBulkEntry,\n type PlayerLinesValues,\n type StatEventDraft,\n} from './bulk-entry.js';\nimport { buildGameContribution, decideParticipation, type ContributionSpec } from './contribution.js';\nimport {\n FINALIZATION_READY,\n STAT_EVENT_ACCEPTED,\n isAllZeroLine,\n isSportStatEventIn,\n isStatCorrection,\n refuseStatEvent,\n type CorrectableFields,\n type GameTeamLine,\n type SportScoring,\n type SportStatEventBody,\n type StatCorrectionBody,\n type StatEventBody,\n type StatLineValues,\n} from './scoring.js';\nimport {\n describeStoreEvent,\n formatSignedValue,\n type PlayerEventsScoringPanel,\n type Scoreboard,\n type StatEventLabel,\n type StatEventNameResolver,\n type StatFieldLabels,\n} from './scoring-display.js';\n\ntype BasketballEvent = Extract<SportStatEventBody, { type: BasketballStatEventType }>;\ntype PlayerCounters = Record<BasketballPlayerStatKey, number>;\n\nfunction isBasketballEvent(event: StatEventBody | undefined): event is BasketballEvent {\n return isSportStatEventIn(BASKETBALL_STAT_EVENT_TYPE_KEYS, event);\n}\n\n// The registry chose this adapter by the game's `leagueType`, so the rollup it is handed is a\n// basketball game's (SPORT-002).\nfunction ownStats(state: GameStats): BasketballGameStats {\n return state as BasketballGameStats;\n}\n\nfunction ownTeamLine(line: GameTeamLine): BasketballTeamStats {\n return line as BasketballTeamStats;\n}\n\n// ---------------------------------------------------------------------------------------------\n// Lines\n// ---------------------------------------------------------------------------------------------\n\n/**\n * Fantasy points (FP) of a basketball line: each player counter times its weight. Every stored\n * `fantasyPoints` equals this over the counters of its own line; `deriveLine` is what applies it.\n */\nexport function basketballFantasyPoints(line: Pick<BasketballPlayerStats, BasketballPlayerStatKey>): number {\n return BASKETBALL_PLAYER_STAT_KEYS.reduce(\n (total, key) => total + line[key] * BASKETBALL_FANTASY_POINT_WEIGHTS[key],\n 0,\n );\n}\n\nconst FANTASY_POINTS_FIELD = 'fantasyPoints' satisfies keyof BasketballPlayerStats;\nconst PLAYER_LINE_KINDS: readonly StatLineKind[] = PLAYER_STAT_LINE_KIND_KEYS;\n\nexport function emptyBasketballTeamLine(): BasketballTeamStats {\n return Object.fromEntries(BASKETBALL_TEAM_STAT_KEYS.map((key) => [key, 0])) as BasketballTeamStats;\n}\n\nfunction emptyPlayerCounters(): PlayerCounters {\n return Object.fromEntries(BASKETBALL_PLAYER_STAT_KEYS.map((key) => [key, 0])) as PlayerCounters;\n}\n\nfunction counterOf(line: StatLineValues, field: string): number {\n const value = line[field] ?? 0;\n if (typeof value !== 'number') throw new TypeError(`A basketball line's ${field} is not a number.`);\n return value;\n}\n\nfunction playerCountersOf(line: StatLineValues | undefined): PlayerCounters {\n const counters = emptyPlayerCounters();\n if (line === undefined) return counters;\n for (const key of BASKETBALL_PLAYER_STAT_KEYS) counters[key] = counterOf(line, key);\n return counters;\n}\n\n// FP is an individual stat: it goes on the four player kinds and on no team kind.\nfunction deriveBasketballLine(kind: StatLineKind, line: StatLineValues): StatLineValues {\n const withoutDerived = Object.fromEntries(Object.entries(line).filter(([field]) => field !== FANTASY_POINTS_FIELD));\n if (!PLAYER_LINE_KINDS.includes(kind)) return withoutDerived;\n return { ...withoutDerived, [FANTASY_POINTS_FIELD]: basketballFantasyPoints(playerCountersOf(line)) };\n}\n\n// ---------------------------------------------------------------------------------------------\n// Events and their effects\n// ---------------------------------------------------------------------------------------------\n\nconst CORRECTABLE_FIELDS: CorrectableFields = {\n team: BASKETBALL_TEAM_STAT_KEYS,\n player: BASKETBALL_PLAYER_STAT_KEYS,\n};\n\nconst TALLY_FIELD = {\n [BASKETBALL_REBOUND_EVENT_TYPE]: 'rebounds',\n [BASKETBALL_ASSIST_EVENT_TYPE]: 'assists',\n} as const satisfies Record<(typeof BASKETBALL_PLAYER_TALLY_EVENT_TYPE_KEYS)[number], BasketballPlayerStatKey>;\n\ninterface LineChange<Field extends string> {\n /** The team id of a team line, or the roster-entry id of a player line. */\n readonly line: string;\n readonly field: Field;\n readonly amount: number;\n}\n\ninterface Effects {\n readonly team: readonly LineChange<BasketballTeamStatKey>[];\n readonly player: readonly LineChange<BasketballPlayerStatKey>[];\n}\n\nfunction assisterOf(event: StatEventBody): string | undefined {\n return 'assistedByUserId' in event && typeof event.assistedByUserId === 'string' ? event.assistedByUserId : undefined;\n}\n\nfunction namesPlayer(event: StatEventBody): boolean {\n return 'playerUserId' in event && event.playerUserId !== undefined;\n}\n\nfunction effectsOf(event: BasketballEvent): Effects {\n if (event.type === BASKETBALL_TIMEOUT_EVENT_TYPE) {\n return { team: [{ line: event.teamId, field: 'timeouts', amount: 1 }], player: [] };\n }\n const scorer = buildGameRosterPlayerId(event.teamId, event.playerUserId);\n if (event.type === BASKETBALL_BULK_EDIT_EVENT_TYPE) {\n // A scorer's points edit keeps the team's score the sum of its players' points.\n return {\n team: event.stat === 'points' ? [{ line: event.teamId, field: 'score', amount: event.value }] : [],\n player: [{ line: scorer, field: event.stat, amount: event.value }],\n };\n }\n\n const team: LineChange<BasketballTeamStatKey>[] = [];\n const player: LineChange<BasketballPlayerStatKey>[] = [];\n const points = BASKETBALL_POINTS_BY_EVENT_TYPE[event.type];\n if (points > 0) {\n team.push({ line: event.teamId, field: 'score', amount: points });\n player.push({ line: scorer, field: 'points', amount: points });\n }\n if (event.type === BASKETBALL_REBOUND_EVENT_TYPE || event.type === BASKETBALL_ASSIST_EVENT_TYPE) {\n player.push({ line: scorer, field: TALLY_FIELD[event.type], amount: 1 });\n }\n const assister = assisterOf(event);\n if (assister !== undefined) {\n player.push({ line: buildGameRosterPlayerId(event.teamId, assister), field: 'assists', amount: 1 });\n }\n return { team, player };\n}\n\nfunction correctionEffects(event: StatCorrectionBody): Effects {\n const fields = event.playerUserId === undefined ? CORRECTABLE_FIELDS.team : CORRECTABLE_FIELDS.player;\n if (!fields.includes(event.stat)) {\n throw new Error(`A basketball correction cannot change ${event.stat} on a ${event.playerUserId === undefined ? 'team' : 'player'} line.`);\n }\n // A correction moves only its own field: a player-points correction does not move the team score.\n return event.playerUserId === undefined\n ? { team: [{ line: event.teamId, field: event.stat as BasketballTeamStatKey, amount: event.value }], player: [] }\n : {\n team: [],\n player: [\n {\n line: buildGameRosterPlayerId(event.teamId, event.playerUserId),\n field: event.stat as BasketballPlayerStatKey,\n amount: event.value,\n },\n ],\n };\n}\n\nfunction applyEffects(state: BasketballGameStats, effects: Effects, sign: 1 | -1): BasketballGameStats {\n const teamStats = { ...state.teamStats };\n for (const change of effects.team) {\n const line = { ...(teamStats[change.line] ?? emptyBasketballTeamLine()) };\n line[change.field] += sign * change.amount;\n teamStats[change.line] = line;\n }\n\n const playerStats = { ...state.playerStats };\n for (const change of effects.player) {\n const counters = playerCountersOf(playerStats[change.line]);\n counters[change.field] += sign * change.amount;\n if (isAllZeroLine(counters, BASKETBALL_PLAYER_STAT_KEYS)) delete playerStats[change.line];\n else playerStats[change.line] = deriveBasketballLine('gamePlayer', counters) as BasketballPlayerStats;\n }\n return { teamStats, playerStats };\n}\n\n// ---------------------------------------------------------------------------------------------\n// Validation — the same rules the bulk form holds, re-checked on the server (SPORT-006)\n// ---------------------------------------------------------------------------------------------\n\nfunction isAssistableShot(type: BasketballStatEventType): boolean {\n return (BASKETBALL_ASSISTABLE_SHOT_EVENT_TYPE_KEYS as readonly string[]).includes(type);\n}\n\nconst validate: SportScoring['validate'] = (stateIn, event, roster) => {\n if (!isBasketballEvent(event)) return refuseStatEvent('eventTypeNotInSport');\n if (!roster.teamIds.includes(event.teamId)) return refuseStatEvent('teamNotInGame');\n if (event.type === BASKETBALL_TIMEOUT_EVENT_TYPE) {\n return namesPlayer(event) || assisterOf(event) !== undefined ? refuseStatEvent('playerNotAllowed') : STAT_EVENT_ACCEPTED;\n }\n\n const scorer = buildGameRosterPlayerId(event.teamId, event.playerUserId);\n if (!roster.rosterPlayerIds.has(scorer)) return refuseStatEvent('playerNotRostered');\n\n const assister = assisterOf(event);\n if (assister !== undefined) {\n if (!isAssistableShot(event.type) || assister === event.playerUserId) return refuseStatEvent('assistNotAllowed');\n if (!roster.rosterPlayerIds.has(buildGameRosterPlayerId(event.teamId, assister))) {\n return refuseStatEvent('assisterNotRostered');\n }\n }\n\n if (event.type === BASKETBALL_BULK_EDIT_EVENT_TYPE) {\n if (!Number.isInteger(event.value) || event.value === 0) return refuseStatEvent('bulkValueInvalid');\n const state = ownStats(stateIn);\n const current = playerCountersOf(state.playerStats[scorer])[event.stat];\n if (event.previousValue !== current) return refuseStatEvent('bulkStale');\n if (current + event.value < 0) return refuseStatEvent('bulkValueInvalid');\n const teamScore = (state.teamStats[event.teamId] ?? emptyBasketballTeamLine()).score;\n if (event.stat === 'points' && teamScore + event.value < 0) return refuseStatEvent('bulkValueInvalid');\n }\n return STAT_EVENT_ACCEPTED;\n};\n\n// What a completed basketball game adds: each entry's points, rebounds, assists, and FP to its row,\n// and the team's rebounds and assists to its standings line. A present entry with no points,\n// rebounds, or assists is credited no game played — zero points alone is not exclusion.\nconst BASKETBALL_CONTRIBUTION: ContributionSpec = {\n playerStatKeys: BASKETBALL_PLAYER_STAT_KEYS,\n teamSeasonPlayerSums: ['rebounds', 'assists'] satisfies BasketballPlayerStatKey[],\n zeroLineIsNonScoring: true,\n deriveLine: deriveBasketballLine,\n};\n\nexport const BASKETBALL_SCORING: SportScoring = {\n validate,\n apply: (state, event) => {\n if (isStatCorrection(event)) return applyEffects(ownStats(state), correctionEffects(event), 1);\n if (!isBasketballEvent(event)) throw new Error(`The basketball adapter does not apply ${event.type}.`);\n return applyEffects(ownStats(state), effectsOf(event), 1);\n },\n undo: (state, target) => {\n if (!isBasketballEvent(target)) throw new Error(`The basketball adapter does not undo ${target.type}.`);\n return applyEffects(ownStats(state), effectsOf(target), -1);\n },\n deriveLine: deriveBasketballLine,\n correctableFields: CORRECTABLE_FIELDS,\n // Played in no rounds, and finalized by hand whenever the scorer chooses.\n nextRound: () => null,\n finalizationReadiness: () => FINALIZATION_READY,\n participation: (state, rosterPlayerIds, absentRosterPlayerIds) =>\n decideParticipation(BASKETBALL_CONTRIBUTION, state, rosterPlayerIds, absentRosterPlayerIds),\n contribution: (game) => buildGameContribution(BASKETBALL_CONTRIBUTION, game),\n};\n\n// ---------------------------------------------------------------------------------------------\n// Display\n// ---------------------------------------------------------------------------------------------\n\nexport const BASKETBALL_EVENT_LABELS = {\n [BASKETBALL_ONE_POINT_EVENT_TYPE]: { button: '+1 PT', play: '1-point basket' },\n [BASKETBALL_TWO_POINT_EVENT_TYPE]: { button: '+2 PT', play: '2-point basket' },\n [BASKETBALL_THREE_POINT_EVENT_TYPE]: { button: '+3 PT', play: '3-point basket' },\n [BASKETBALL_REBOUND_EVENT_TYPE]: { button: 'Rebound', play: 'Rebound' },\n [BASKETBALL_ASSIST_EVENT_TYPE]: { button: 'Assist', play: 'Assist' },\n [BASKETBALL_TIMEOUT_EVENT_TYPE]: { button: 'Timeout', play: 'Timeout' },\n [BASKETBALL_BULK_EDIT_EVENT_TYPE]: { button: 'Bulk entry', play: 'Bulk entry' },\n} as const satisfies Record<BasketballStatEventType, StatEventLabel>;\n\nexport const BASKETBALL_FIELD_LABELS = {\n team: { score: 'Score', timeouts: 'Timeouts' },\n player: { points: 'Points', rebounds: 'Rebounds', assists: 'Assists' },\n} as const satisfies StatFieldLabels<BasketballTeamStatKey, BasketballPlayerStatKey>;\n\nexport function describeBasketballEvent(event: GameStatEvent, resolve: StatEventNameResolver): string {\n const storeEvent = describeStoreEvent(event, resolve, BASKETBALL_FIELD_LABELS);\n if (storeEvent !== null) return storeEvent;\n if (!isBasketballEvent(event)) return event.type;\n\n const team = resolve.team(event.teamId);\n if (event.type === BASKETBALL_TIMEOUT_EVENT_TYPE) return `${team}: ${BASKETBALL_EVENT_LABELS[event.type].play}`;\n\n const player = `${resolve.player(event.playerUserId)} (${team})`;\n if (event.type === BASKETBALL_BULK_EDIT_EVENT_TYPE) {\n const field = BASKETBALL_FIELD_LABELS.player[event.stat].toLowerCase();\n return `${player}: ${formatSignedValue(event.value)} ${field} (${BASKETBALL_EVENT_LABELS[event.type].play.toLowerCase()})`;\n }\n const play = `${player}: ${BASKETBALL_EVENT_LABELS[event.type].play}`;\n const assister = assisterOf(event);\n return assister === undefined ? play : `${play}, assisted by ${resolve.player(assister)}`;\n}\n\nfunction sumOf(lines: readonly { readonly rebounds: number; readonly assists: number }[], field: 'rebounds' | 'assists'): number {\n return lines.reduce((total, line) => total + line[field], 0);\n}\n\nexport const BASKETBALL_SCOREBOARD: Scoreboard = {\n figures: [\n { id: 'points', label: BASKETBALL_FIELD_LABELS.player.points, value: (teamLine) => teamLine.score },\n { id: 'rebounds', label: BASKETBALL_FIELD_LABELS.player.rebounds, value: (_teamLine, sideLines) => sumOf(sideLines, 'rebounds') },\n { id: 'assists', label: BASKETBALL_FIELD_LABELS.player.assists, value: (_teamLine, sideLines) => sumOf(sideLines, 'assists') },\n { id: 'timeouts', label: BASKETBALL_FIELD_LABELS.team.timeouts, value: (teamLine) => ownTeamLine(teamLine).timeouts },\n ],\n jumpBall: true,\n};\n\nexport const BASKETBALL_SCORING_PANEL: PlayerEventsScoringPanel = {\n kind: 'playerEvents',\n playerEventTypes: [...BASKETBALL_SCORE_EVENT_TYPE_KEYS, ...BASKETBALL_PLAYER_TALLY_EVENT_TYPE_KEYS],\n assistableEventTypes: BASKETBALL_ASSISTABLE_SHOT_EVENT_TYPE_KEYS,\n teamEventTypes: [BASKETBALL_TIMEOUT_EVENT_TYPE],\n};\n\n// ---------------------------------------------------------------------------------------------\n// Bulk entry — one row per roster entry, absent entries included\n// ---------------------------------------------------------------------------------------------\n\nexport const BASKETBALL_TEAM_SCORE_FLOOR_MESSAGE = \"These changes would leave a team's score below zero.\";\n\nconst playerLineValuesSchema = z.strictObject(\n Object.fromEntries(BASKETBALL_PLAYER_STAT_KEYS.map((key) => [key, bulkEntryCountField])) as Record<\n BasketballPlayerStatKey,\n typeof bulkEntryCountField\n >,\n);\n\nfunction currentPlayerCounters(context: BulkEntryContext, entryId: string): PlayerCounters {\n return playerCountersOf(ownStats(context.state).playerStats[entryId]);\n}\n\nfunction bulkDrafts(values: PlayerLinesValues, context: BulkEntryContext): StatEventDraft[] {\n const increases: StatEventDraft[] = [];\n const decreases: StatEventDraft[] = [];\n for (const entryId of context.rosterPlayerIds) {\n const entered = values.lines[entryId];\n const entry = parseGameRosterPlayerId(entryId);\n if (entered === undefined || entry === null) continue;\n const before = currentPlayerCounters(context, entryId);\n for (const stat of BASKETBALL_PLAYER_STAT_KEYS) {\n const value = (entered[stat] ?? before[stat]) - before[stat];\n if (value === 0) continue;\n const draft: StatEventDraft = {\n type: BASKETBALL_BULK_EDIT_EVENT_TYPE,\n teamId: entry.teamId,\n playerUserId: entry.userId,\n stat,\n value,\n previousValue: before[stat],\n };\n (value > 0 ? increases : decreases).push(draft);\n }\n }\n // Every increase before any decrease, so a team's running score never dips below the floor its\n // final score clears — each draft passes `validate` against the state the ones before it leave.\n return [...increases, ...decreases];\n}\n\nexport const BASKETBALL_BULK_ENTRY: PlayerLinesBulkEntry = {\n kind: 'playerLines',\n formDefaults: (context) => ({\n lines: Object.fromEntries(context.rosterPlayerIds.map((entryId) => [entryId, currentPlayerCounters(context, entryId)])),\n }),\n formSchema: (context) => {\n const roster = new Set(context.rosterPlayerIds);\n return z.object({ lines: z.record(z.string(), playerLineValuesSchema) }).superRefine((values, issues) => {\n for (const entryId of Object.keys(values.lines)) {\n if (!roster.has(entryId)) {\n issues.addIssue({ code: 'custom', path: ['lines', entryId], message: NOT_ON_GAME_ROSTER_MESSAGE });\n }\n }\n const state = ownStats(context.state);\n for (const teamId of context.game.teamIds) {\n let score = (state.teamStats[teamId] ?? emptyBasketballTeamLine()).score;\n for (const [entryId, entered] of Object.entries(values.lines)) {\n if (parseGameRosterPlayerId(entryId)?.teamId !== teamId) continue;\n score += entered.points - currentPlayerCounters(context, entryId).points;\n }\n if (score < 0) issues.addIssue({ code: 'custom', path: ['lines'], message: BASKETBALL_TEAM_SCORE_FLOOR_MESSAGE });\n }\n if (bulkDrafts(values, context).length > MAX_STAT_EVENTS_PER_WRITE) {\n issues.addIssue({ code: 'custom', path: ['lines'], message: BULK_ENTRY_TOO_LARGE_MESSAGE });\n }\n });\n },\n toEvents: bulkDrafts,\n};\n"]}