@ttt-productions/q-core 0.1.0 → 0.1.1

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 (60) hide show
  1. package/dist/constants/business.js.map +1 -1
  2. package/dist/constants/sports.js.map +1 -1
  3. package/dist/constants/storage-keys.js.map +1 -1
  4. package/dist/doc-schemas/catalogs.js.map +1 -1
  5. package/dist/doc-schemas/game-location.js.map +1 -1
  6. package/dist/doc-schemas/game-stats.js.map +1 -1
  7. package/dist/doc-schemas/league-team.js.map +1 -1
  8. package/dist/doc-schemas/pending-media.js.map +1 -1
  9. package/dist/doc-schemas/registry.js.map +1 -1
  10. package/dist/doc-schemas/sport-game.js.map +1 -1
  11. package/dist/doc-schemas/system.js.map +1 -1
  12. package/dist/doc-schemas/user-profile.js.map +1 -1
  13. package/dist/doc-schemas/waiver-template.js.map +1 -1
  14. package/dist/doc-schemas/waivers-and-hardware.js.map +1 -1
  15. package/dist/ids/index.js.map +1 -1
  16. package/dist/ids/minted-ids.js.map +1 -1
  17. package/dist/ids/stats-operation-ids.js.map +1 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/media/file-origins.js.map +1 -1
  20. package/dist/paths/collection-refs.js.map +1 -1
  21. package/dist/paths/collections.js.map +1 -1
  22. package/dist/paths/path-builders.js.map +1 -1
  23. package/dist/paths/utils.js.map +1 -1
  24. package/dist/schemas/account-settings.js.map +1 -1
  25. package/dist/schemas/atoms.js.map +1 -1
  26. package/dist/schemas/awards.js.map +1 -1
  27. package/dist/schemas/hardware-loan-contracts.js.map +1 -1
  28. package/dist/schemas/schedules.js.map +1 -1
  29. package/dist/schemas/scoring.js.map +1 -1
  30. package/dist/schemas/stats.js.map +1 -1
  31. package/dist/schemas/team-joining.js.map +1 -1
  32. package/dist/schemas/teams.js.map +1 -1
  33. package/dist/schemas/uploads.js.map +1 -1
  34. package/dist/schemas/users.js.map +1 -1
  35. package/dist/sports/basketball-scoring.js.map +1 -1
  36. package/dist/sports/basketball.js.map +1 -1
  37. package/dist/sports/bulk-entry.js.map +1 -1
  38. package/dist/sports/contribution.js.map +1 -1
  39. package/dist/sports/curling-scoring.js.map +1 -1
  40. package/dist/sports/finalized-record.js.map +1 -1
  41. package/dist/sports/football-scoring.js.map +1 -1
  42. package/dist/sports/index.js.map +1 -1
  43. package/dist/sports/rankings.js.map +1 -1
  44. package/dist/sports/rollup-check.js.map +1 -1
  45. package/dist/sports/scoring.js.map +1 -1
  46. package/dist/sports/store-driver.js.map +1 -1
  47. package/dist/types/documents.js.map +1 -1
  48. package/dist/types/notifications.js.map +1 -1
  49. package/dist/types/picture-owners.js.map +1 -1
  50. package/dist/types/sports.js.map +1 -1
  51. package/dist/types/stats.js.map +1 -1
  52. package/dist/types/unions.js.map +1 -1
  53. package/dist/utils/account-status.js.map +1 -1
  54. package/dist/utils/app-config.js.map +1 -1
  55. package/dist/utils/app-routes.js.map +1 -1
  56. package/dist/utils/index.js.map +1 -1
  57. package/dist/utils/league-calendar.js.map +1 -1
  58. package/dist/utils/league-mode.js.map +1 -1
  59. package/dist/utils/team-member-actions.js.map +1 -1
  60. package/package.json +90 -90
@@ -1 +1 @@
1
- {"version":3,"file":"waivers-and-hardware.js","sourceRoot":"","sources":["../../src/doc-schemas/waivers-and-hardware.ts"],"names":[],"mappings":"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","sourcesContent":["// Signed waivers and referee hardware contracts. Signatures are legal artifacts: a signed waiver\r\n// carries the exact wording the signer saw, as named snapshots. The templates they are signed from\r\n// are ./waiver-template.ts.\r\n\r\nimport { z } from 'zod';\r\nimport {\r\n epochMsSchema,\r\n hardwareLoanContractStatusSchema,\r\n leagueIdSchema,\r\n teamIdSchema,\r\n userIdSchema,\r\n waiverWitnessAuthoritySchema,\r\n} from './atoms.js';\r\nimport {\r\n PENDING_HARDWARE_LOAN_CONTRACT_STATUS,\r\n RETURNED_HARDWARE_LOAN_CONTRACT_STATUS,\r\n} from '../types/unions.js';\r\nimport { StorageObjectRefSchema } from './pending-media.js';\r\nimport { waiverTemplateIdSchema, waiverTemplateVersionNumberSchema } from './waiver-template.js';\r\n\r\n// `signedWaivers/{leagueId}_{userId}` — one signed waiver per player per league, never replaced,\r\n// moved, or deleted: a ghost's stays under the ghost's id after the ghost is removed or linked.\r\nexport const SignedWaiverSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n userId: userIdSchema,\r\n waiverTemplateId: waiverTemplateIdSchema,\r\n // The published version of the template the signature was captured under. A record that names\r\n // no version has its wording snapshot as its whole record.\r\n waiverTemplateVersion: waiverTemplateVersionNumberSchema.optional(),\r\n waiverTitleSnapshot: z.string(),\r\n waiverTextSnapshot: z.string(),\r\n // The kept signature image. Read only through the signature-read callable, never by URL.\r\n signatureFile: StorageObjectRefSchema,\r\n signedAt: epochMsSchema,\r\n // A ghost player's waiver is signed by a witness for the ghost's team: the witness's account,\r\n // the authority they signed under, and the ghost's name at signing — a named snapshot, so the\r\n // record still says whom it was for after the ghost's public identity is gone (ARCH-103).\r\n teamId: teamIdSchema.optional(),\r\n witnessUserId: userIdSchema.optional(),\r\n witnessAuthority: waiverWitnessAuthoritySchema.optional(),\r\n subjectDisplayNameSnapshot: z.string().optional(),\r\n })\r\n .refine(\r\n (waiver) => {\r\n const witnessFields = [\r\n waiver.teamId,\r\n waiver.witnessUserId,\r\n waiver.witnessAuthority,\r\n waiver.subjectDisplayNameSnapshot,\r\n ];\r\n const present = witnessFields.filter((field) => field !== undefined).length;\r\n return present === 0 || present === witnessFields.length;\r\n },\r\n { message: \"A ghost's waiver carries its team, witness, authority, and name together, or none of them.\", path: ['witnessUserId'] },\r\n );\r\nexport type SignedWaiver = z.infer<typeof SignedWaiverSchema>;\r\n\r\n// One loaned item, as the contract was created with it: its catalog id and name. A contract keeps\r\n// what it loaned even if the catalog later changes.\r\nexport const HardwareItemSchema = z.strictObject({\r\n id: z.string().min(1),\r\n name: z.string().min(1),\r\n});\r\nexport type HardwareItem = z.infer<typeof HardwareItemSchema>;\r\n\r\n// `hardwareLoanContracts/{contractId}` — equipment loaned to a referee: who holds it, what they hold,\r\n// and their signature on the loan agreement, a legal artifact. Names resolve from `publicUsers` at\r\n// read time (ARCH-103). `pending` until the referee signs; `loaned` from the signing, which keeps the\r\n// signature for good; `returned` once an admin records the equipment back, the signature retained.\r\nexport const HardwareLoanContractSchema = z\r\n .strictObject({\r\n refereeUserId: userIdSchema,\r\n createdByUserId: userIdSchema,\r\n hardware: z.array(HardwareItemSchema).min(1),\r\n status: hardwareLoanContractStatusSchema,\r\n // The kept signature image. Read only through the signature-read callables, never by URL.\r\n signatureFile: StorageObjectRefSchema.optional(),\r\n createdAt: epochMsSchema,\r\n loanedAt: epochMsSchema.optional(),\r\n returnedAt: epochMsSchema.optional(),\r\n })\r\n .refine(\r\n (contract) =>\r\n contract.status === PENDING_HARDWARE_LOAN_CONTRACT_STATUS\r\n ? contract.signatureFile === undefined && contract.loanedAt === undefined\r\n : contract.signatureFile !== undefined && contract.loanedAt !== undefined,\r\n { message: 'A contract carries its signature and loan date exactly once it is signed.', path: ['signatureFile'] },\r\n )\r\n .refine(\r\n (contract) => (contract.status === RETURNED_HARDWARE_LOAN_CONTRACT_STATUS) === (contract.returnedAt !== undefined),\r\n { message: 'A contract carries its return date exactly while it is returned.', path: ['returnedAt'] },\r\n );\r\nexport type HardwareLoanContract = z.infer<typeof HardwareLoanContractSchema>;\r\n"]}
1
+ {"version":3,"file":"waivers-and-hardware.js","sourceRoot":"","sources":["../../src/doc-schemas/waivers-and-hardware.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,mGAAmG;AACnG,4BAA4B;AAE5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,aAAa,EACb,gCAAgC,EAChC,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,4BAA4B,GAC7B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,qCAAqC,EACrC,sCAAsC,GACvC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,iCAAiC,EAAE,MAAM,sBAAsB,CAAC;AAEjG,iGAAiG;AACjG,gGAAgG;AAChG,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC;KAChC,MAAM,CAAC;IACN,QAAQ,EAAE,cAAc;IACxB,MAAM,EAAE,YAAY;IACpB,gBAAgB,EAAE,sBAAsB;IACxC,8FAA8F;IAC9F,2DAA2D;IAC3D,qBAAqB,EAAE,iCAAiC,CAAC,QAAQ,EAAE;IACnE,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC/B,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC9B,yFAAyF;IACzF,aAAa,EAAE,sBAAsB;IACrC,QAAQ,EAAE,aAAa;IACvB,8FAA8F;IAC9F,8FAA8F;IAC9F,0FAA0F;IAC1F,MAAM,EAAE,YAAY,CAAC,QAAQ,EAAE;IAC/B,aAAa,EAAE,YAAY,CAAC,QAAQ,EAAE;IACtC,gBAAgB,EAAE,4BAA4B,CAAC,QAAQ,EAAE;IACzD,0BAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClD,CAAC;KACD,MAAM,CACL,CAAC,MAAM,EAAE,EAAE;IACT,MAAM,aAAa,GAAG;QACpB,MAAM,CAAC,MAAM;QACb,MAAM,CAAC,aAAa;QACpB,MAAM,CAAC,gBAAgB;QACvB,MAAM,CAAC,0BAA0B;KAClC,CAAC;IACF,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;IAC5E,OAAO,OAAO,KAAK,CAAC,IAAI,OAAO,KAAK,aAAa,CAAC,MAAM,CAAC;AAC3D,CAAC,EACD,EAAE,OAAO,EAAE,4FAA4F,EAAE,IAAI,EAAE,CAAC,eAAe,CAAC,EAAE,CACnI,CAAC;AAGJ,kGAAkG;AAClG,oDAAoD;AACpD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,YAAY,CAAC;IAC/C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACxB,CAAC,CAAC;AAGH,sGAAsG;AACtG,mGAAmG;AACnG,sGAAsG;AACtG,mGAAmG;AACnG,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC;KACxC,YAAY,CAAC;IACZ,aAAa,EAAE,YAAY;IAC3B,eAAe,EAAE,YAAY;IAC7B,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,MAAM,EAAE,gCAAgC;IACxC,0FAA0F;IAC1F,aAAa,EAAE,sBAAsB,CAAC,QAAQ,EAAE;IAChD,SAAS,EAAE,aAAa;IACxB,QAAQ,EAAE,aAAa,CAAC,QAAQ,EAAE;IAClC,UAAU,EAAE,aAAa,CAAC,QAAQ,EAAE;CACrC,CAAC;KACD,MAAM,CACL,CAAC,QAAQ,EAAE,EAAE,CACX,QAAQ,CAAC,MAAM,KAAK,qCAAqC;IACvD,CAAC,CAAC,QAAQ,CAAC,aAAa,KAAK,SAAS,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS;IACzE,CAAC,CAAC,QAAQ,CAAC,aAAa,KAAK,SAAS,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,EAC7E,EAAE,OAAO,EAAE,2EAA2E,EAAE,IAAI,EAAE,CAAC,eAAe,CAAC,EAAE,CAClH;KACA,MAAM,CACL,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,sCAAsC,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,KAAK,SAAS,CAAC,EAClH,EAAE,OAAO,EAAE,kEAAkE,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE,CACtG,CAAC","sourcesContent":["// Signed waivers and referee hardware contracts. Signatures are legal artifacts: a signed waiver\n// carries the exact wording the signer saw, as named snapshots. The templates they are signed from\n// are ./waiver-template.ts.\n\nimport { z } from 'zod';\nimport {\n epochMsSchema,\n hardwareLoanContractStatusSchema,\n leagueIdSchema,\n teamIdSchema,\n userIdSchema,\n waiverWitnessAuthoritySchema,\n} from './atoms.js';\nimport {\n PENDING_HARDWARE_LOAN_CONTRACT_STATUS,\n RETURNED_HARDWARE_LOAN_CONTRACT_STATUS,\n} from '../types/unions.js';\nimport { StorageObjectRefSchema } from './pending-media.js';\nimport { waiverTemplateIdSchema, waiverTemplateVersionNumberSchema } from './waiver-template.js';\n\n// `signedWaivers/{leagueId}_{userId}` — one signed waiver per player per league, never replaced,\n// moved, or deleted: a ghost's stays under the ghost's id after the ghost is removed or linked.\nexport const SignedWaiverSchema = z\n .object({\n leagueId: leagueIdSchema,\n userId: userIdSchema,\n waiverTemplateId: waiverTemplateIdSchema,\n // The published version of the template the signature was captured under. A record that names\n // no version has its wording snapshot as its whole record.\n waiverTemplateVersion: waiverTemplateVersionNumberSchema.optional(),\n waiverTitleSnapshot: z.string(),\n waiverTextSnapshot: z.string(),\n // The kept signature image. Read only through the signature-read callable, never by URL.\n signatureFile: StorageObjectRefSchema,\n signedAt: epochMsSchema,\n // A ghost player's waiver is signed by a witness for the ghost's team: the witness's account,\n // the authority they signed under, and the ghost's name at signing — a named snapshot, so the\n // record still says whom it was for after the ghost's public identity is gone (ARCH-103).\n teamId: teamIdSchema.optional(),\n witnessUserId: userIdSchema.optional(),\n witnessAuthority: waiverWitnessAuthoritySchema.optional(),\n subjectDisplayNameSnapshot: z.string().optional(),\n })\n .refine(\n (waiver) => {\n const witnessFields = [\n waiver.teamId,\n waiver.witnessUserId,\n waiver.witnessAuthority,\n waiver.subjectDisplayNameSnapshot,\n ];\n const present = witnessFields.filter((field) => field !== undefined).length;\n return present === 0 || present === witnessFields.length;\n },\n { message: \"A ghost's waiver carries its team, witness, authority, and name together, or none of them.\", path: ['witnessUserId'] },\n );\nexport type SignedWaiver = z.infer<typeof SignedWaiverSchema>;\n\n// One loaned item, as the contract was created with it: its catalog id and name. A contract keeps\n// what it loaned even if the catalog later changes.\nexport const HardwareItemSchema = z.strictObject({\n id: z.string().min(1),\n name: z.string().min(1),\n});\nexport type HardwareItem = z.infer<typeof HardwareItemSchema>;\n\n// `hardwareLoanContracts/{contractId}` — equipment loaned to a referee: who holds it, what they hold,\n// and their signature on the loan agreement, a legal artifact. Names resolve from `publicUsers` at\n// read time (ARCH-103). `pending` until the referee signs; `loaned` from the signing, which keeps the\n// signature for good; `returned` once an admin records the equipment back, the signature retained.\nexport const HardwareLoanContractSchema = z\n .strictObject({\n refereeUserId: userIdSchema,\n createdByUserId: userIdSchema,\n hardware: z.array(HardwareItemSchema).min(1),\n status: hardwareLoanContractStatusSchema,\n // The kept signature image. Read only through the signature-read callables, never by URL.\n signatureFile: StorageObjectRefSchema.optional(),\n createdAt: epochMsSchema,\n loanedAt: epochMsSchema.optional(),\n returnedAt: epochMsSchema.optional(),\n })\n .refine(\n (contract) =>\n contract.status === PENDING_HARDWARE_LOAN_CONTRACT_STATUS\n ? contract.signatureFile === undefined && contract.loanedAt === undefined\n : contract.signatureFile !== undefined && contract.loanedAt !== undefined,\n { message: 'A contract carries its signature and loan date exactly once it is signed.', path: ['signatureFile'] },\n )\n .refine(\n (contract) => (contract.status === RETURNED_HARDWARE_LOAN_CONTRACT_STATUS) === (contract.returnedAt !== undefined),\n { message: 'A contract carries its return date exactly while it is returned.', path: ['returnedAt'] },\n );\nexport type HardwareLoanContract = z.infer<typeof HardwareLoanContractSchema>;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ids/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC","sourcesContent":["export * from './compound-ids.js';\r\nexport * from './minted-ids.js';\r\nexport * from './stat-event-ids.js';\r\nexport * from './waiver-template-ids.js';\r\nexport * from './picture-ids.js';\r\nexport * from './notification-ids.js';\r\nexport * from './stats-operation-ids.js';\r\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ids/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC","sourcesContent":["export * from './compound-ids.js';\nexport * from './minted-ids.js';\nexport * from './stat-event-ids.js';\nexport * from './waiver-template-ids.js';\nexport * from './picture-ids.js';\nexport * from './notification-ids.js';\nexport * from './stats-operation-ids.js';\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"minted-ids.js","sourceRoot":"","sources":["../../src/ids/minted-ids.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,mGAAmG;AACnG,gDAAgD;AAEhD,oGAAoG;AACpG,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC;AAE7C,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,OAAO,GAAG,oBAAoB,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,OAAO,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC;AAC9B,CAAC;AAED,+FAA+F;AAC/F,qGAAqG;AACrG,yDAAyD;AACzD,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,MAAc;IAC/D,OAAO,QAAQ,KAAK,IAAI,MAAM,EAAE,CAAC;AACnC,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AAEjC,gGAAgG;AAChG,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC;AAEpC,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,MAAM,KAAK,WAAW,CAAC;AAChC,CAAC","sourcesContent":["// Minted identifiers and identity sentinels.\r\n//\r\n// Builders take the clock reading and the random suffix as arguments so they stay pure: the caller\r\n// supplies `Date.now()` and its own randomness.\r\n\r\n// A placeholder player carries a `ghost_`-prefixed id and has a publicUsers document (BACKEND-120).\r\nexport const GHOST_USER_ID_PREFIX = 'ghost_';\r\n\r\nexport function isGhostUserId(userId: string): boolean {\r\n return userId.startsWith(GHOST_USER_ID_PREFIX);\r\n}\r\n\r\nexport function buildGhostUserId(nowMs: number, suffix: string): string {\r\n return `${GHOST_USER_ID_PREFIX}${nowMs}_${suffix}`;\r\n}\r\n\r\n// A new game's id, `{timestamp}_{suffix}`. A copied game keeps the id it was stored under.\r\nexport function buildSportGameId(nowMs: number, suffix: string): string {\r\n return `${nowMs}_${suffix}`;\r\n}\r\n\r\n// A new week's `weekId`, minted by the server when the week is saved. Some stored weeks hold a\r\n// date-derived `week-{YYYY-MM-DD}` id; a minted id never takes that form, and never derives from the\r\n// date, so two weeks starting on one day stay two weeks.\r\nexport function buildScheduleWeekId(nowMs: number, suffix: string): string {\r\n return `week_${nowMs}_${suffix}`;\r\n}\r\n\r\n// The team slot of a bye week. Never a real leagueTeams id.\r\nexport const BYE_TEAM_ID = 'bye';\r\n\r\n// How the bye slot reads wherever a game or a week names it — a matchup, a schedule, a refusal.\r\nexport const BYE_TEAM_LABEL = 'Bye';\r\n\r\nexport function isByeTeamId(teamId: string): boolean {\r\n return teamId === BYE_TEAM_ID;\r\n}\r\n"]}
1
+ {"version":3,"file":"minted-ids.js","sourceRoot":"","sources":["../../src/ids/minted-ids.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,mGAAmG;AACnG,gDAAgD;AAEhD,oGAAoG;AACpG,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC;AAE7C,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,OAAO,GAAG,oBAAoB,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,OAAO,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC;AAC9B,CAAC;AAED,+FAA+F;AAC/F,qGAAqG;AACrG,yDAAyD;AACzD,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,MAAc;IAC/D,OAAO,QAAQ,KAAK,IAAI,MAAM,EAAE,CAAC;AACnC,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AAEjC,gGAAgG;AAChG,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC;AAEpC,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,MAAM,KAAK,WAAW,CAAC;AAChC,CAAC","sourcesContent":["// Minted identifiers and identity sentinels.\n//\n// Builders take the clock reading and the random suffix as arguments so they stay pure: the caller\n// supplies `Date.now()` and its own randomness.\n\n// A placeholder player carries a `ghost_`-prefixed id and has a publicUsers document (BACKEND-120).\nexport const GHOST_USER_ID_PREFIX = 'ghost_';\n\nexport function isGhostUserId(userId: string): boolean {\n return userId.startsWith(GHOST_USER_ID_PREFIX);\n}\n\nexport function buildGhostUserId(nowMs: number, suffix: string): string {\n return `${GHOST_USER_ID_PREFIX}${nowMs}_${suffix}`;\n}\n\n// A new game's id, `{timestamp}_{suffix}`. A copied game keeps the id it was stored under.\nexport function buildSportGameId(nowMs: number, suffix: string): string {\n return `${nowMs}_${suffix}`;\n}\n\n// A new week's `weekId`, minted by the server when the week is saved. Some stored weeks hold a\n// date-derived `week-{YYYY-MM-DD}` id; a minted id never takes that form, and never derives from the\n// date, so two weeks starting on one day stay two weeks.\nexport function buildScheduleWeekId(nowMs: number, suffix: string): string {\n return `week_${nowMs}_${suffix}`;\n}\n\n// The team slot of a bye week. Never a real leagueTeams id.\nexport const BYE_TEAM_ID = 'bye';\n\n// How the bye slot reads wherever a game or a week names it — a matchup, a schedule, a refusal.\nexport const BYE_TEAM_LABEL = 'Bye';\n\nexport function isByeTeamId(teamId: string): boolean {\n return teamId === BYE_TEAM_ID;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"stats-operation-ids.js","sourceRoot":"","sources":["../../src/ids/stats-operation-ids.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,+FAA+F;AAE/F,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,iCAAiC,GAAG,cAAc,CAAC;AAEzD,mGAAmG;AACnG,gFAAgF;AAChF,MAAM,UAAU,4BAA4B,CAAC,MAAc;IACzD,OAAO,CAAC,iCAAiC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,gCAAgC,GAAG,aAAa,CAAC;AAEvD,gGAAgG;AAChG,kGAAkG;AAClG,8FAA8F;AAC9F,MAAM,UAAU,yBAAyB,CAAC,MAAc,EAAE,WAAmB;IAC3E,OAAO,CAAC,gCAAgC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;AAC7F,CAAC","sourcesContent":["// `statsOperations` ids the server derives from what the operation acts on, so a retried call finds\r\n// the operation it started instead of starting a second one, and no client names the document.\r\n\r\nimport { COMPOUND_ID_SEPARATOR } from './compound-ids.js';\r\n\r\nconst GAME_DELETION_OPERATION_ID_PREFIX = 'gameDeletion';\r\n\r\n// A game is deleted at most once, so its id names the one deletion it can have; a client-minted id\r\n// would let a caller address another action's operation document (BACKEND-102).\r\nexport function buildGameDeletionOperationId(gameId: string): string {\r\n return [GAME_DELETION_OPERATION_ID_PREFIX, gameId].join(COMPOUND_ID_SEPARATOR);\r\n}\r\n\r\nconst GHOST_PLAYER_OPERATION_ID_PREFIX = 'ghostPlayer';\r\n\r\n// A ghost has exactly one operation for both of its ways out — a link to a real account, or its\r\n// removal — so two links of one ghost, or a link and a removal, find the same document and refuse\r\n// each other instead of interleaving. The team is part of it because a link acts on one team.\r\nexport function buildGhostLinkOperationId(teamId: string, ghostUserId: string): string {\r\n return [GHOST_PLAYER_OPERATION_ID_PREFIX, teamId, ghostUserId].join(COMPOUND_ID_SEPARATOR);\r\n}\r\n"]}
1
+ {"version":3,"file":"stats-operation-ids.js","sourceRoot":"","sources":["../../src/ids/stats-operation-ids.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,+FAA+F;AAE/F,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,iCAAiC,GAAG,cAAc,CAAC;AAEzD,mGAAmG;AACnG,gFAAgF;AAChF,MAAM,UAAU,4BAA4B,CAAC,MAAc;IACzD,OAAO,CAAC,iCAAiC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,gCAAgC,GAAG,aAAa,CAAC;AAEvD,gGAAgG;AAChG,kGAAkG;AAClG,8FAA8F;AAC9F,MAAM,UAAU,yBAAyB,CAAC,MAAc,EAAE,WAAmB;IAC3E,OAAO,CAAC,gCAAgC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;AAC7F,CAAC","sourcesContent":["// `statsOperations` ids the server derives from what the operation acts on, so a retried call finds\n// the operation it started instead of starting a second one, and no client names the document.\n\nimport { COMPOUND_ID_SEPARATOR } from './compound-ids.js';\n\nconst GAME_DELETION_OPERATION_ID_PREFIX = 'gameDeletion';\n\n// A game is deleted at most once, so its id names the one deletion it can have; a client-minted id\n// would let a caller address another action's operation document (BACKEND-102).\nexport function buildGameDeletionOperationId(gameId: string): string {\n return [GAME_DELETION_OPERATION_ID_PREFIX, gameId].join(COMPOUND_ID_SEPARATOR);\n}\n\nconst GHOST_PLAYER_OPERATION_ID_PREFIX = 'ghostPlayer';\n\n// A ghost has exactly one operation for both of its ways out — a link to a real account, or its\n// removal — so two links of one ghost, or a link and a removal, find the same document and refuse\n// each other instead of interleaving. The team is part of it because a link acts on one team.\nexport function buildGhostLinkOperationId(teamId: string, ghostUserId: string): string {\n return [GHOST_PLAYER_OPERATION_ID_PREFIX, teamId, ghostUserId].join(COMPOUND_ID_SEPARATOR);\n}\n"]}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC","sourcesContent":["export * from './types/index.js';\r\nexport * from './paths/index.js';\r\nexport * from './constants/index.js';\r\nexport * from './utils/index.js';\r\nexport * from './media/index.js';\r\nexport * from './ids/index.js';\r\nexport * from './domain-events/index.js';\r\nexport * from './input-formats/index.js';\r\nexport * from './migration-console/index.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC","sourcesContent":["export * from './types/index.js';\nexport * from './paths/index.js';\nexport * from './constants/index.js';\nexport * from './utils/index.js';\nexport * from './media/index.js';\nexport * from './ids/index.js';\nexport * from './domain-events/index.js';\nexport * from './input-formats/index.js';\nexport * from './migration-console/index.js';\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"file-origins.js","sourceRoot":"","sources":["../../src/media/file-origins.ts"],"names":[],"mappings":"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","sourcesContent":["// The upload origin registry (MEDIA-001, MEDIA-006). One origin value binds everything an\r\n// upload touches: the picker spec, the staging path and its `storage.rules` cap and content type,\r\n// the callable that accepts the upload, and — for a picture — the processing spec and the owner the\r\n// picture is published to. The generic packages treat an origin id as opaque; the policy is here.\r\n//\r\n// Picture origins are processed into their kind's declared sizes and keep no master. Signature\r\n// origins are kept byte-exact (`preserveOriginal`) by the callable that records them and are never\r\n// processed. Adding an origin is one change across this registry, `storage.rules`, the processor\r\n// routing, and their tests; `storage.rules` restates the caps and content types, and a guard pins it\r\n// to this file.\r\n\r\nimport type { MediaAccept, MediaOriginSpec } from '@ttt-productions/media-schemas';\r\nimport { PICTURE_VARIANT_KEYS } from '../types/unions.js';\r\nimport type { PictureVariantKey } from '../types/unions.js';\r\nimport { PICTURE_ASPECT_RATIOS, pictureAspectRatio } from './picture-aspects.js';\r\nimport type { PictureAspect } from './picture-aspects.js';\r\n\r\nexport const PICTURE_ORIGIN_KEYS = [\r\n 'league-picture',\r\n 'team-picture',\r\n 'landing-picture',\r\n 'location-picture',\r\n 'award-badge',\r\n] as const;\r\nexport type PictureOrigin = (typeof PICTURE_ORIGIN_KEYS)[number];\r\n\r\nexport const SIGNATURE_ORIGIN_KEYS = ['waiver-signature', 'hardware-signature'] as const;\r\nexport type SignatureOrigin = (typeof SIGNATURE_ORIGIN_KEYS)[number];\r\n\r\nexport const FILE_ORIGIN_KEYS = [...PICTURE_ORIGIN_KEYS, ...SIGNATURE_ORIGIN_KEYS] as const;\r\nexport type FileOrigin = PictureOrigin | SignatureOrigin;\r\n\r\nconst MB = 1024 * 1024;\r\n\r\n// The raw cap is an abuse bound: the browser uploads a picture already cropped and shrunk to its\r\n// kind's largest size, so a real upload is far below it.\r\nexport const PICTURE_UPLOAD_MAX_BYTES = 25 * MB;\r\n\r\n// A photo's browser crop and every stored size are JPEG at this quality.\r\nexport const PICTURE_JPEG_QUALITY = 85;\r\n\r\n// What a picture kind is stored as: a photo as JPEG, a badge as PNG, which keeps the transparent\r\n// corners of a badge drawn round.\r\nexport const PICTURE_STORED_FORMAT_KEYS = ['jpeg', 'png'] as const;\r\nexport type PictureStoredFormat = (typeof PICTURE_STORED_FORMAT_KEYS)[number];\r\n\r\n// The cropper's mask: a rectangle, or a circle for a badge — which is how a badge is drawn, though\r\n// the stored image is square.\r\nexport const PICTURE_CROP_SHAPE_KEYS = ['rect', 'round'] as const;\r\nexport type PictureCropShape = (typeof PICTURE_CROP_SHAPE_KEYS)[number];\r\n\r\n// Picture formats the server's byte inspection accepts. Scriptable or unproven formats (svg, heic,\r\n// avif) are not accepted.\r\nexport const PICTURE_ACCEPTED_FORMATS = ['jpeg', 'png', 'gif', 'webp', 'bmp', 'tiff'] as const;\r\n\r\nexport const PICTURE_ACCEPT: MediaAccept = {\r\n kinds: ['image'],\r\n formats: [...PICTURE_ACCEPTED_FORMATS],\r\n};\r\n\r\nexport interface PictureSize {\r\n readonly width: number;\r\n readonly height: number;\r\n}\r\n\r\nexport interface PictureKind {\r\n /** The shape the browser crops to, the server re-crops to, and every display frames. */\r\n readonly aspect: PictureAspect;\r\n /** Each stored size, at the kind's shape. `lg` is also the size the browser crops to. */\r\n readonly sizes: Readonly<Record<PictureVariantKey, PictureSize>>;\r\n /** The format of the browser's crop and of every stored size. */\r\n readonly format: PictureStoredFormat;\r\n readonly cropShape: PictureCropShape;\r\n}\r\n\r\nexport const PICTURE_KINDS = {\r\n 'league-picture': {\r\n aspect: 'landscape',\r\n format: 'jpeg',\r\n cropShape: 'rect',\r\n sizes: { sm: { width: 480, height: 270 }, md: { width: 960, height: 540 }, lg: { width: 1920, height: 1080 } },\r\n },\r\n 'team-picture': {\r\n aspect: 'classic',\r\n format: 'jpeg',\r\n cropShape: 'rect',\r\n sizes: { sm: { width: 480, height: 360 }, md: { width: 960, height: 720 }, lg: { width: 1600, height: 1200 } },\r\n },\r\n 'landing-picture': {\r\n aspect: 'banner',\r\n format: 'jpeg',\r\n cropShape: 'rect',\r\n sizes: { sm: { width: 720, height: 240 }, md: { width: 1440, height: 480 }, lg: { width: 2400, height: 800 } },\r\n },\r\n 'location-picture': {\r\n aspect: 'landscape',\r\n format: 'jpeg',\r\n cropShape: 'rect',\r\n sizes: { sm: { width: 480, height: 270 }, md: { width: 960, height: 540 }, lg: { width: 1280, height: 720 } },\r\n },\r\n // A badge is cropped in a round mask and kept square, at the sizes every award has always had.\r\n 'award-badge': {\r\n aspect: 'square',\r\n format: 'png',\r\n cropShape: 'round',\r\n sizes: { sm: { width: 64, height: 64 }, md: { width: 256, height: 256 }, lg: { width: 512, height: 512 } },\r\n },\r\n} as const satisfies Record<PictureOrigin, PictureKind>;\r\n\r\nfunction pictureOriginSpec(kind: PictureKind): MediaOriginSpec {\r\n const ratio = pictureAspectRatio(kind.aspect);\r\n const { width, height } = PICTURE_ASPECT_RATIOS[kind.aspect];\r\n const variants = PICTURE_VARIANT_KEYS.map((key) => ({\r\n key,\r\n crop: { width: kind.sizes[key].width, height: kind.sizes[key].height, gravity: 'center' as const },\r\n format: kind.format,\r\n ...(kind.format === 'jpeg' ? { quality: PICTURE_JPEG_QUALITY } : {}),\r\n }));\r\n return {\r\n kind: 'image',\r\n accept: PICTURE_ACCEPT,\r\n maxBytes: PICTURE_UPLOAD_MAX_BYTES,\r\n imageCrop: {\r\n aspectRatio: ratio,\r\n outputWidth: kind.sizes.lg.width,\r\n outputHeight: kind.sizes.lg.height,\r\n shape: kind.cropShape,\r\n format: kind.format,\r\n ...(kind.format === 'jpeg' ? { quality: PICTURE_JPEG_QUALITY } : {}),\r\n aspectRatioDisplay: `${width}:${height}`,\r\n },\r\n client: {\r\n allowPick: true,\r\n allowCapturePhoto: true,\r\n allowRecordVideo: false,\r\n allowRecordAudio: false,\r\n },\r\n processing: {\r\n // The server trusts nothing the browser did: an upload that bypassed the app's cropper is\r\n // centre-cropped to the kind's shape (`requiredAspectRatio` with `allowAutoFormat`) before\r\n // every size is cut, and a source smaller than a size is never enlarged.\r\n image: {\r\n kind: 'image',\r\n accept: PICTURE_ACCEPT,\r\n maxBytes: PICTURE_UPLOAD_MAX_BYTES,\r\n requiredAspectRatio: ratio,\r\n allowAutoFormat: true,\r\n image: { variants, stripMetadata: true },\r\n },\r\n },\r\n };\r\n}\r\n\r\n// A signature is drawn on a canvas and exported as PNG, so exactly `image/png` is accepted — no\r\n// other image type, and never the neutral octet-stream lane. It is kept byte-exact by the callable\r\n// that records it, and nothing processes it.\r\nexport const SIGNATURE_UPLOAD_MAX_BYTES = 1 * MB;\r\nexport const SIGNATURE_CONTENT_TYPE = 'image/png';\r\n\r\nexport const SIGNATURE_ACCEPT: MediaAccept = {\r\n kinds: ['file'],\r\n mimes: [SIGNATURE_CONTENT_TYPE],\r\n};\r\n\r\nfunction signatureOriginSpec(): MediaOriginSpec {\r\n return {\r\n kind: 'generic',\r\n accept: SIGNATURE_ACCEPT,\r\n maxBytes: SIGNATURE_UPLOAD_MAX_BYTES,\r\n client: {\r\n allowPick: false,\r\n allowCapturePhoto: false,\r\n allowRecordVideo: false,\r\n allowRecordAudio: false,\r\n },\r\n preserveOriginal: true,\r\n };\r\n}\r\n\r\nexport const MEDIA_ORIGIN_SPECS: Readonly<Record<FileOrigin, MediaOriginSpec>> = {\r\n 'league-picture': pictureOriginSpec(PICTURE_KINDS['league-picture']),\r\n 'team-picture': pictureOriginSpec(PICTURE_KINDS['team-picture']),\r\n 'landing-picture': pictureOriginSpec(PICTURE_KINDS['landing-picture']),\r\n 'location-picture': pictureOriginSpec(PICTURE_KINDS['location-picture']),\r\n 'award-badge': pictureOriginSpec(PICTURE_KINDS['award-badge']),\r\n // Promoted to its kept path by the waiver-signing callable.\r\n 'waiver-signature': signatureOriginSpec(),\r\n // Promoted to its kept path by the hardware contract's signing callable.\r\n 'hardware-signature': signatureOriginSpec(),\r\n};\r\n\r\nexport function isFileOrigin(value: string): value is FileOrigin {\r\n return (FILE_ORIGIN_KEYS as readonly string[]).includes(value);\r\n}\r\n\r\nexport function isPictureOrigin(value: string): value is PictureOrigin {\r\n return (PICTURE_ORIGIN_KEYS as readonly string[]).includes(value);\r\n}\r\n\r\nexport function isSignatureOrigin(value: string): value is SignatureOrigin {\r\n return (SIGNATURE_ORIGIN_KEYS as readonly string[]).includes(value);\r\n}\r\n"]}
1
+ {"version":3,"file":"file-origins.js","sourceRoot":"","sources":["../../src/media/file-origins.ts"],"names":[],"mappings":"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","sourcesContent":["// The upload origin registry (MEDIA-001, MEDIA-006). One origin value binds everything an\n// upload touches: the picker spec, the staging path and its `storage.rules` cap and content type,\n// the callable that accepts the upload, and — for a picture — the processing spec and the owner the\n// picture is published to. The generic packages treat an origin id as opaque; the policy is here.\n//\n// Picture origins are processed into their kind's declared sizes and keep no master. Signature\n// origins are kept byte-exact (`preserveOriginal`) by the callable that records them and are never\n// processed. Adding an origin is one change across this registry, `storage.rules`, the processor\n// routing, and their tests; `storage.rules` restates the caps and content types, and a guard pins it\n// to this file.\n\nimport type { MediaAccept, MediaOriginSpec } from '@ttt-productions/media-schemas';\nimport { PICTURE_VARIANT_KEYS } from '../types/unions.js';\nimport type { PictureVariantKey } from '../types/unions.js';\nimport { PICTURE_ASPECT_RATIOS, pictureAspectRatio } from './picture-aspects.js';\nimport type { PictureAspect } from './picture-aspects.js';\n\nexport const PICTURE_ORIGIN_KEYS = [\n 'league-picture',\n 'team-picture',\n 'landing-picture',\n 'location-picture',\n 'award-badge',\n] as const;\nexport type PictureOrigin = (typeof PICTURE_ORIGIN_KEYS)[number];\n\nexport const SIGNATURE_ORIGIN_KEYS = ['waiver-signature', 'hardware-signature'] as const;\nexport type SignatureOrigin = (typeof SIGNATURE_ORIGIN_KEYS)[number];\n\nexport const FILE_ORIGIN_KEYS = [...PICTURE_ORIGIN_KEYS, ...SIGNATURE_ORIGIN_KEYS] as const;\nexport type FileOrigin = PictureOrigin | SignatureOrigin;\n\nconst MB = 1024 * 1024;\n\n// The raw cap is an abuse bound: the browser uploads a picture already cropped and shrunk to its\n// kind's largest size, so a real upload is far below it.\nexport const PICTURE_UPLOAD_MAX_BYTES = 25 * MB;\n\n// A photo's browser crop and every stored size are JPEG at this quality.\nexport const PICTURE_JPEG_QUALITY = 85;\n\n// What a picture kind is stored as: a photo as JPEG, a badge as PNG, which keeps the transparent\n// corners of a badge drawn round.\nexport const PICTURE_STORED_FORMAT_KEYS = ['jpeg', 'png'] as const;\nexport type PictureStoredFormat = (typeof PICTURE_STORED_FORMAT_KEYS)[number];\n\n// The cropper's mask: a rectangle, or a circle for a badge — which is how a badge is drawn, though\n// the stored image is square.\nexport const PICTURE_CROP_SHAPE_KEYS = ['rect', 'round'] as const;\nexport type PictureCropShape = (typeof PICTURE_CROP_SHAPE_KEYS)[number];\n\n// Picture formats the server's byte inspection accepts. Scriptable or unproven formats (svg, heic,\n// avif) are not accepted.\nexport const PICTURE_ACCEPTED_FORMATS = ['jpeg', 'png', 'gif', 'webp', 'bmp', 'tiff'] as const;\n\nexport const PICTURE_ACCEPT: MediaAccept = {\n kinds: ['image'],\n formats: [...PICTURE_ACCEPTED_FORMATS],\n};\n\nexport interface PictureSize {\n readonly width: number;\n readonly height: number;\n}\n\nexport interface PictureKind {\n /** The shape the browser crops to, the server re-crops to, and every display frames. */\n readonly aspect: PictureAspect;\n /** Each stored size, at the kind's shape. `lg` is also the size the browser crops to. */\n readonly sizes: Readonly<Record<PictureVariantKey, PictureSize>>;\n /** The format of the browser's crop and of every stored size. */\n readonly format: PictureStoredFormat;\n readonly cropShape: PictureCropShape;\n}\n\nexport const PICTURE_KINDS = {\n 'league-picture': {\n aspect: 'landscape',\n format: 'jpeg',\n cropShape: 'rect',\n sizes: { sm: { width: 480, height: 270 }, md: { width: 960, height: 540 }, lg: { width: 1920, height: 1080 } },\n },\n 'team-picture': {\n aspect: 'classic',\n format: 'jpeg',\n cropShape: 'rect',\n sizes: { sm: { width: 480, height: 360 }, md: { width: 960, height: 720 }, lg: { width: 1600, height: 1200 } },\n },\n 'landing-picture': {\n aspect: 'banner',\n format: 'jpeg',\n cropShape: 'rect',\n sizes: { sm: { width: 720, height: 240 }, md: { width: 1440, height: 480 }, lg: { width: 2400, height: 800 } },\n },\n 'location-picture': {\n aspect: 'landscape',\n format: 'jpeg',\n cropShape: 'rect',\n sizes: { sm: { width: 480, height: 270 }, md: { width: 960, height: 540 }, lg: { width: 1280, height: 720 } },\n },\n // A badge is cropped in a round mask and kept square, at the sizes every award has always had.\n 'award-badge': {\n aspect: 'square',\n format: 'png',\n cropShape: 'round',\n sizes: { sm: { width: 64, height: 64 }, md: { width: 256, height: 256 }, lg: { width: 512, height: 512 } },\n },\n} as const satisfies Record<PictureOrigin, PictureKind>;\n\nfunction pictureOriginSpec(kind: PictureKind): MediaOriginSpec {\n const ratio = pictureAspectRatio(kind.aspect);\n const { width, height } = PICTURE_ASPECT_RATIOS[kind.aspect];\n const variants = PICTURE_VARIANT_KEYS.map((key) => ({\n key,\n crop: { width: kind.sizes[key].width, height: kind.sizes[key].height, gravity: 'center' as const },\n format: kind.format,\n ...(kind.format === 'jpeg' ? { quality: PICTURE_JPEG_QUALITY } : {}),\n }));\n return {\n kind: 'image',\n accept: PICTURE_ACCEPT,\n maxBytes: PICTURE_UPLOAD_MAX_BYTES,\n imageCrop: {\n aspectRatio: ratio,\n outputWidth: kind.sizes.lg.width,\n outputHeight: kind.sizes.lg.height,\n shape: kind.cropShape,\n format: kind.format,\n ...(kind.format === 'jpeg' ? { quality: PICTURE_JPEG_QUALITY } : {}),\n aspectRatioDisplay: `${width}:${height}`,\n },\n client: {\n allowPick: true,\n allowCapturePhoto: true,\n allowRecordVideo: false,\n allowRecordAudio: false,\n },\n processing: {\n // The server trusts nothing the browser did: an upload that bypassed the app's cropper is\n // centre-cropped to the kind's shape (`requiredAspectRatio` with `allowAutoFormat`) before\n // every size is cut, and a source smaller than a size is never enlarged.\n image: {\n kind: 'image',\n accept: PICTURE_ACCEPT,\n maxBytes: PICTURE_UPLOAD_MAX_BYTES,\n requiredAspectRatio: ratio,\n allowAutoFormat: true,\n image: { variants, stripMetadata: true },\n },\n },\n };\n}\n\n// A signature is drawn on a canvas and exported as PNG, so exactly `image/png` is accepted — no\n// other image type, and never the neutral octet-stream lane. It is kept byte-exact by the callable\n// that records it, and nothing processes it.\nexport const SIGNATURE_UPLOAD_MAX_BYTES = 1 * MB;\nexport const SIGNATURE_CONTENT_TYPE = 'image/png';\n\nexport const SIGNATURE_ACCEPT: MediaAccept = {\n kinds: ['file'],\n mimes: [SIGNATURE_CONTENT_TYPE],\n};\n\nfunction signatureOriginSpec(): MediaOriginSpec {\n return {\n kind: 'generic',\n accept: SIGNATURE_ACCEPT,\n maxBytes: SIGNATURE_UPLOAD_MAX_BYTES,\n client: {\n allowPick: false,\n allowCapturePhoto: false,\n allowRecordVideo: false,\n allowRecordAudio: false,\n },\n preserveOriginal: true,\n };\n}\n\nexport const MEDIA_ORIGIN_SPECS: Readonly<Record<FileOrigin, MediaOriginSpec>> = {\n 'league-picture': pictureOriginSpec(PICTURE_KINDS['league-picture']),\n 'team-picture': pictureOriginSpec(PICTURE_KINDS['team-picture']),\n 'landing-picture': pictureOriginSpec(PICTURE_KINDS['landing-picture']),\n 'location-picture': pictureOriginSpec(PICTURE_KINDS['location-picture']),\n 'award-badge': pictureOriginSpec(PICTURE_KINDS['award-badge']),\n // Promoted to its kept path by the waiver-signing callable.\n 'waiver-signature': signatureOriginSpec(),\n // Promoted to its kept path by the hardware contract's signing callable.\n 'hardware-signature': signatureOriginSpec(),\n};\n\nexport function isFileOrigin(value: string): value is FileOrigin {\n return (FILE_ORIGIN_KEYS as readonly string[]).includes(value);\n}\n\nexport function isPictureOrigin(value: string): value is PictureOrigin {\n return (PICTURE_ORIGIN_KEYS as readonly string[]).includes(value);\n}\n\nexport function isSignatureOrigin(value: string): value is SignatureOrigin {\n return (SIGNATURE_ORIGIN_KEYS as readonly string[]).includes(value);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"collection-refs.js","sourceRoot":"","sources":["../../src/paths/collection-refs.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,EAAE;AACF,8DAA8D;AAC9D,kEAAkE;AAElE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,YAAY,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC;IACzD,WAAW,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC;IACvD,oBAAoB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,sBAAsB,CAAC;IAC1E,kBAAkB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,mBAAmB,CAAC;IACrE,oBAAoB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,sBAAsB,CAAC;IAC1E,YAAY,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC;IACzD,WAAW,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC;IACvD,kBAAkB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,oBAAoB,CAAC;IACtE,eAAe,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;IAC/D,eAAe,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;IAC/D,gBAAgB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC;IAClE,gBAAgB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC;IAClE,qBAAqB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC;IAC5E,UAAU,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC;IACrD,aAAa,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC;IAC3D,eAAe,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;IAC/D,aAAa,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC;IAC3D,qBAAqB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC;IAC5E,gBAAgB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,iBAAiB,CAAC;IACjE,sBAAsB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,wBAAwB,CAAC;IAC9E,eAAe,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;IAC/D,mBAAmB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,qBAAqB,CAAC;IACxE,eAAe,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;IAC/D,YAAY,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC;IACzD,kBAAkB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,mBAAmB,CAAC;IACrE,WAAW,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC;IACvD,wBAAwB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC;IAClF,wBAAwB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC;IAClF,sBAAsB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC;IAC7E,0BAA0B,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,6BAA6B,CAAC;CAC/E,CAAC","sourcesContent":["// Collection reference builders — for collection-level operations.\r\n//\r\n// Frontend: collection(db, ...COLLECTION_REFS.userProfiles())\r\n// Backend: db.collection(toPath(COLLECTION_REFS.userProfiles()))\r\n\r\nimport { COLLECTIONS } from './collections.js';\r\n\r\nexport const COLLECTION_REFS = {\r\n userProfiles: (): [string] => [COLLECTIONS.USER_PROFILES],\r\n publicUsers: (): [string] => [COLLECTIONS.PUBLIC_USERS],\r\n statusReconcileQueue: (): [string] => [COLLECTIONS.STATUS_RECONCILE_QUEUE],\r\n registrationStarts: (): [string] => [COLLECTIONS.REGISTRATION_STARTS],\r\n reservedDisplayNames: (): [string] => [COLLECTIONS.RESERVED_DISPLAY_NAMES],\r\n sportLeagues: (): [string] => [COLLECTIONS.SPORT_LEAGUES],\r\n leagueTeams: (): [string] => [COLLECTIONS.LEAGUE_TEAMS],\r\n leagueTeamContacts: (): [string] => [COLLECTIONS.LEAGUE_TEAM_CONTACTS],\r\n teamMemberships: (): [string] => [COLLECTIONS.TEAM_MEMBERSHIPS],\r\n teamInvitations: (): [string] => [COLLECTIONS.TEAM_INVITATIONS],\r\n teamJoinRequests: (): [string] => [COLLECTIONS.TEAM_JOIN_REQUESTS],\r\n leagueFreeAgents: (): [string] => [COLLECTIONS.LEAGUE_FREE_AGENTS],\r\n membershipRosterSyncs: (): [string] => [COLLECTIONS.MEMBERSHIP_ROSTER_SYNCS],\r\n sportGames: (): [string] => [COLLECTIONS.SPORT_GAMES],\r\n gameLocations: (): [string] => [COLLECTIONS.GAME_LOCATIONS],\r\n waiverTemplates: (): [string] => [COLLECTIONS.WAIVER_TEMPLATES],\r\n signedWaivers: (): [string] => [COLLECTIONS.SIGNED_WAIVERS],\r\n hardwareLoanContracts: (): [string] => [COLLECTIONS.HARDWARE_LOAN_CONTRACTS],\r\n awardDefinitions: (): [string] => [COLLECTIONS.AWARD_DEFINITIONS],\r\n statsValidationReports: (): [string] => [COLLECTIONS.STATS_VALIDATION_REPORTS],\r\n statsOperations: (): [string] => [COLLECTIONS.STATS_OPERATIONS],\r\n migrationActionRuns: (): [string] => [COLLECTIONS.MIGRATION_ACTION_RUNS],\r\n galleryPictures: (): [string] => [COLLECTIONS.GALLERY_PICTURES],\r\n pendingMedia: (): [string] => [COLLECTIONS.PENDING_MEDIA],\r\n pictureRetirements: (): [string] => [COLLECTIONS.PICTURE_RETIREMENTS],\r\n auditEvents: (): [string] => [COLLECTIONS.AUDIT_EVENTS],\r\n activeAdminNotifications: (): [string] => [COLLECTIONS.ACTIVE_ADMIN_NOTIFICATIONS],\r\n adminNotificationHistory: (): [string] => [COLLECTIONS.ADMIN_NOTIFICATION_HISTORY],\r\n notificationDeliveries: (): [string] => [COLLECTIONS.NOTIFICATION_DELIVERIES],\r\n notificationArchiveAllJobs: (): [string] => [COLLECTIONS.NOTIFICATION_ARCHIVE_ALL_JOBS],\r\n} as const;\r\n"]}
1
+ {"version":3,"file":"collection-refs.js","sourceRoot":"","sources":["../../src/paths/collection-refs.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,EAAE;AACF,8DAA8D;AAC9D,kEAAkE;AAElE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,YAAY,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC;IACzD,WAAW,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC;IACvD,oBAAoB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,sBAAsB,CAAC;IAC1E,kBAAkB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,mBAAmB,CAAC;IACrE,oBAAoB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,sBAAsB,CAAC;IAC1E,YAAY,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC;IACzD,WAAW,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC;IACvD,kBAAkB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,oBAAoB,CAAC;IACtE,eAAe,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;IAC/D,eAAe,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;IAC/D,gBAAgB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC;IAClE,gBAAgB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC;IAClE,qBAAqB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC;IAC5E,UAAU,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC;IACrD,aAAa,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC;IAC3D,eAAe,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;IAC/D,aAAa,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC;IAC3D,qBAAqB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC;IAC5E,gBAAgB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,iBAAiB,CAAC;IACjE,sBAAsB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,wBAAwB,CAAC;IAC9E,eAAe,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;IAC/D,mBAAmB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,qBAAqB,CAAC;IACxE,eAAe,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;IAC/D,YAAY,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC;IACzD,kBAAkB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,mBAAmB,CAAC;IACrE,WAAW,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC;IACvD,wBAAwB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC;IAClF,wBAAwB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC;IAClF,sBAAsB,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC;IAC7E,0BAA0B,EAAE,GAAa,EAAE,CAAC,CAAC,WAAW,CAAC,6BAA6B,CAAC;CAC/E,CAAC","sourcesContent":["// Collection reference builders — for collection-level operations.\n//\n// Frontend: collection(db, ...COLLECTION_REFS.userProfiles())\n// Backend: db.collection(toPath(COLLECTION_REFS.userProfiles()))\n\nimport { COLLECTIONS } from './collections.js';\n\nexport const COLLECTION_REFS = {\n userProfiles: (): [string] => [COLLECTIONS.USER_PROFILES],\n publicUsers: (): [string] => [COLLECTIONS.PUBLIC_USERS],\n statusReconcileQueue: (): [string] => [COLLECTIONS.STATUS_RECONCILE_QUEUE],\n registrationStarts: (): [string] => [COLLECTIONS.REGISTRATION_STARTS],\n reservedDisplayNames: (): [string] => [COLLECTIONS.RESERVED_DISPLAY_NAMES],\n sportLeagues: (): [string] => [COLLECTIONS.SPORT_LEAGUES],\n leagueTeams: (): [string] => [COLLECTIONS.LEAGUE_TEAMS],\n leagueTeamContacts: (): [string] => [COLLECTIONS.LEAGUE_TEAM_CONTACTS],\n teamMemberships: (): [string] => [COLLECTIONS.TEAM_MEMBERSHIPS],\n teamInvitations: (): [string] => [COLLECTIONS.TEAM_INVITATIONS],\n teamJoinRequests: (): [string] => [COLLECTIONS.TEAM_JOIN_REQUESTS],\n leagueFreeAgents: (): [string] => [COLLECTIONS.LEAGUE_FREE_AGENTS],\n membershipRosterSyncs: (): [string] => [COLLECTIONS.MEMBERSHIP_ROSTER_SYNCS],\n sportGames: (): [string] => [COLLECTIONS.SPORT_GAMES],\n gameLocations: (): [string] => [COLLECTIONS.GAME_LOCATIONS],\n waiverTemplates: (): [string] => [COLLECTIONS.WAIVER_TEMPLATES],\n signedWaivers: (): [string] => [COLLECTIONS.SIGNED_WAIVERS],\n hardwareLoanContracts: (): [string] => [COLLECTIONS.HARDWARE_LOAN_CONTRACTS],\n awardDefinitions: (): [string] => [COLLECTIONS.AWARD_DEFINITIONS],\n statsValidationReports: (): [string] => [COLLECTIONS.STATS_VALIDATION_REPORTS],\n statsOperations: (): [string] => [COLLECTIONS.STATS_OPERATIONS],\n migrationActionRuns: (): [string] => [COLLECTIONS.MIGRATION_ACTION_RUNS],\n galleryPictures: (): [string] => [COLLECTIONS.GALLERY_PICTURES],\n pendingMedia: (): [string] => [COLLECTIONS.PENDING_MEDIA],\n pictureRetirements: (): [string] => [COLLECTIONS.PICTURE_RETIREMENTS],\n auditEvents: (): [string] => [COLLECTIONS.AUDIT_EVENTS],\n activeAdminNotifications: (): [string] => [COLLECTIONS.ACTIVE_ADMIN_NOTIFICATIONS],\n adminNotificationHistory: (): [string] => [COLLECTIONS.ADMIN_NOTIFICATION_HISTORY],\n notificationDeliveries: (): [string] => [COLLECTIONS.NOTIFICATION_DELIVERIES],\n notificationArchiveAllJobs: (): [string] => [COLLECTIONS.NOTIFICATION_ARCHIVE_ALL_JOBS],\n} as const;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"collections.js","sourceRoot":"","sources":["../../src/paths/collections.ts"],"names":[],"mappings":"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","sourcesContent":["// Firestore collection, subcollection, and fixed-document name constants for Q-Sports.\r\n//\r\n// Every collection value is compound camelCase — it says what the documents are, never a single\r\n// bare word (guarded by __tests__/collections.test.ts). The three underscore buckets hold fixed-ID\r\n// system documents and are placed by who reads them; every one of them is callable-only for writes\r\n// (BACKEND-108). An admin-only document is server-only, read by an admin through a callable:\r\n// _appConfig public read\r\n// _systemData signed-in read\r\n// _serverData no client access\r\n\r\nexport const COLLECTIONS = {\r\n // People\r\n USER_PROFILES: 'userProfiles',\r\n PUBLIC_USERS: 'publicUsers',\r\n // One document per taken display name, keyed by its normalized form — the uniqueness lock.\r\n RESERVED_DISPLAY_NAMES: 'reservedDisplayNames',\r\n // One entry per account owed a post-commit Firebase Auth effect, id = the userId: a status\r\n // change's sign-in half, or a failed role-claim write. Backend-only.\r\n STATUS_RECONCILE_QUEUE: 'statusReconcileQueue',\r\n // One document per login whose registration started, id = the userId: the orphan-login cleanup's\r\n // work list. Backend-only.\r\n REGISTRATION_STARTS: 'registrationStarts',\r\n // One document per scheduled pass that keeps a rolling cursor, id = its `SWEEP_STATE_NAMES` name.\r\n // Backend-only.\r\n SWEEP_STATE: 'sweepState',\r\n\r\n // Leagues, teams, membership\r\n SPORT_LEAGUES: 'sportLeagues',\r\n LEAGUE_TEAMS: 'leagueTeams',\r\n // One admin-only document per team, id = the team id: how the league reaches the team. The team\r\n // itself is publicly readable, so no contact detail lives on it (BACKEND-105); a league's contacts\r\n // are one query on `leagueId`.\r\n LEAGUE_TEAM_CONTACTS: 'leagueTeamContacts',\r\n TEAM_MEMBERSHIPS: 'teamMemberships',\r\n TEAM_INVITATIONS: 'teamInvitations',\r\n TEAM_JOIN_REQUESTS: 'teamJoinRequests',\r\n LEAGUE_FREE_AGENTS: 'leagueFreeAgents',\r\n // One document per team membership, id = the membership's id: the durable obligation to bring\r\n // that membership's open game rosters in line with it. Backend-only.\r\n MEMBERSHIP_ROSTER_SYNCS: 'membershipRosterSyncs',\r\n\r\n // Games\r\n SPORT_GAMES: 'sportGames',\r\n GAME_LOCATIONS: 'gameLocations',\r\n\r\n // Waivers and hardware\r\n WAIVER_TEMPLATES: 'waiverTemplates',\r\n SIGNED_WAIVERS: 'signedWaivers',\r\n HARDWARE_LOAN_CONTRACTS: 'hardwareLoanContracts',\r\n\r\n // Awards and derived stats\r\n AWARD_DEFINITIONS: 'awardDefinitions',\r\n SPORT_HALL_OF_FAME: 'sportHallOfFame',\r\n STATS_VALIDATION_REPORTS: 'statsValidationReports',\r\n // One logical run of a stats action: its status, its resume position, and the hold it places on\r\n // a game. Admin read; written only by the stats cores.\r\n STATS_OPERATIONS: 'statsOperations',\r\n\r\n // One document per cutover action, id = the action id: where its latest real run stands, its\r\n // last preview, and what it reported. Admin read; written only by the migration console.\r\n MIGRATION_ACTION_RUNS: 'migrationActionRuns',\r\n\r\n // One document per picture in a league, team, or landing page gallery. Public read; written only\r\n // by the picture core.\r\n GALLERY_PICTURES: 'galleryPictures',\r\n // One accepted picture upload, id = its staging id = the picture id. Read by its uploader and\r\n // admins; written only by the accept core (the upload callable and the picture carry), the\r\n // processing trigger, and the maintenance sweep's stale-upload pass; never deleted.\r\n PENDING_MEDIA: 'pendingMedia',\r\n // The durable obligation to delete a picture's files, or a deleted owner's whole gallery. No\r\n // client access; carried out by the media maintenance sweep.\r\n PICTURE_RETIREMENTS: 'pictureRetirements',\r\n\r\n // Append-only record of sensitive actions. No client access; written only by Cloud Functions.\r\n AUDIT_EVENTS: 'auditEvents',\r\n\r\n // Admin notifications, all written only by Cloud Functions. The shared cards every admin reads and\r\n // their archived history are admin read; the delivery ledger the owning callables write each\r\n // occurrence into, and each admin's archive-all job, have no client access.\r\n ACTIVE_ADMIN_NOTIFICATIONS: 'activeAdminNotifications',\r\n ADMIN_NOTIFICATION_HISTORY: 'adminNotificationHistory',\r\n NOTIFICATION_DELIVERIES: 'notificationDeliveries',\r\n NOTIFICATION_ARCHIVE_ALL_JOBS: 'notificationArchiveAllJobs',\r\n\r\n // Fixed-ID system document buckets\r\n APP_CONFIG: '_appConfig',\r\n SYSTEM_DATA: '_systemData',\r\n SERVER_DATA: '_serverData',\r\n} as const;\r\n\r\nexport type CollectionName = (typeof COLLECTIONS)[keyof typeof COLLECTIONS];\r\n\r\n/** Subcollections of `userProfiles/{userId}`. */\r\nexport const USER_PROFILE_SUBCOLLECTIONS = {\r\n // One document per sport key: pre-Q-Sports career totals folded into lifetime recalculation.\r\n HISTORICAL_STATS: 'historicalStats',\r\n // One owner-only document, id = the userId: email and contact details. The profile itself is\r\n // publicly readable, so nothing personal lives on it (BACKEND-105).\r\n PRIVATE_DATA: 'privateData',\r\n} as const;\r\n\r\n/** Subcollections of `sportGames/{gameId}`. */\r\nexport const SPORT_GAME_SUBCOLLECTIONS = {\r\n // Who participated in the game: one entry per team per person, id `buildGameRosterPlayerId`.\r\n GAME_ROSTER_PLAYERS: 'gameRosterPlayers',\r\n // One stat event per document, keyed by the event id minted at the tap.\r\n GAME_STAT_EVENTS: 'gameStatEvents',\r\n // A completed game's finalized record, in pages, id `buildStatHistoryPageId`.\r\n GAME_STAT_HISTORY: 'gameStatHistory',\r\n} as const;\r\n\r\n/** Subcollections of `waiverTemplates/{waiverTemplateId}`. */\r\nexport const WAIVER_TEMPLATE_SUBCOLLECTIONS = {\r\n // One immutable document per published wording, id `buildWaiverTemplateVersionId(version)`.\r\n WAIVER_TEMPLATE_VERSIONS: 'waiverTemplateVersions',\r\n} as const;\r\n\r\n/** Static document IDs for fixed-ID documents. */\r\nexport const SPECIAL_DOCS = {\r\n // _appConfig — public read\r\n // The app-wide operational levers: version gate, maintenance mode, registration switch, banner.\r\n APP_CONFIG: 'app',\r\n LANDING_PAGE: 'landingPage',\r\n // Public because signed-out spectators follow it for live updates.\r\n STATS_BEACON: 'statsBeacon',\r\n\r\n // _systemData — signed-in read\r\n // The admin and referee rosters — source of truth for the `admin` / `referee` custom claims.\r\n ADMIN_LIST: 'adminList',\r\n\r\n // _serverData — no client access\r\n // The migration console: the cutover marker and the lock that keeps two actions from running at\r\n // once.\r\n MIGRATION_CONSOLE: 'migrationConsole',\r\n} as const;\r\n"]}
1
+ {"version":3,"file":"collections.js","sourceRoot":"","sources":["../../src/paths/collections.ts"],"names":[],"mappings":"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","sourcesContent":["// Firestore collection, subcollection, and fixed-document name constants for Q-Sports.\n//\n// Every collection value is compound camelCase — it says what the documents are, never a single\n// bare word (guarded by __tests__/collections.test.ts). The three underscore buckets hold fixed-ID\n// system documents and are placed by who reads them; every one of them is callable-only for writes\n// (BACKEND-108). An admin-only document is server-only, read by an admin through a callable:\n// _appConfig public read\n// _systemData signed-in read\n// _serverData no client access\n\nexport const COLLECTIONS = {\n // People\n USER_PROFILES: 'userProfiles',\n PUBLIC_USERS: 'publicUsers',\n // One document per taken display name, keyed by its normalized form — the uniqueness lock.\n RESERVED_DISPLAY_NAMES: 'reservedDisplayNames',\n // One entry per account owed a post-commit Firebase Auth effect, id = the userId: a status\n // change's sign-in half, or a failed role-claim write. Backend-only.\n STATUS_RECONCILE_QUEUE: 'statusReconcileQueue',\n // One document per login whose registration started, id = the userId: the orphan-login cleanup's\n // work list. Backend-only.\n REGISTRATION_STARTS: 'registrationStarts',\n // One document per scheduled pass that keeps a rolling cursor, id = its `SWEEP_STATE_NAMES` name.\n // Backend-only.\n SWEEP_STATE: 'sweepState',\n\n // Leagues, teams, membership\n SPORT_LEAGUES: 'sportLeagues',\n LEAGUE_TEAMS: 'leagueTeams',\n // One admin-only document per team, id = the team id: how the league reaches the team. The team\n // itself is publicly readable, so no contact detail lives on it (BACKEND-105); a league's contacts\n // are one query on `leagueId`.\n LEAGUE_TEAM_CONTACTS: 'leagueTeamContacts',\n TEAM_MEMBERSHIPS: 'teamMemberships',\n TEAM_INVITATIONS: 'teamInvitations',\n TEAM_JOIN_REQUESTS: 'teamJoinRequests',\n LEAGUE_FREE_AGENTS: 'leagueFreeAgents',\n // One document per team membership, id = the membership's id: the durable obligation to bring\n // that membership's open game rosters in line with it. Backend-only.\n MEMBERSHIP_ROSTER_SYNCS: 'membershipRosterSyncs',\n\n // Games\n SPORT_GAMES: 'sportGames',\n GAME_LOCATIONS: 'gameLocations',\n\n // Waivers and hardware\n WAIVER_TEMPLATES: 'waiverTemplates',\n SIGNED_WAIVERS: 'signedWaivers',\n HARDWARE_LOAN_CONTRACTS: 'hardwareLoanContracts',\n\n // Awards and derived stats\n AWARD_DEFINITIONS: 'awardDefinitions',\n SPORT_HALL_OF_FAME: 'sportHallOfFame',\n STATS_VALIDATION_REPORTS: 'statsValidationReports',\n // One logical run of a stats action: its status, its resume position, and the hold it places on\n // a game. Admin read; written only by the stats cores.\n STATS_OPERATIONS: 'statsOperations',\n\n // One document per cutover action, id = the action id: where its latest real run stands, its\n // last preview, and what it reported. Admin read; written only by the migration console.\n MIGRATION_ACTION_RUNS: 'migrationActionRuns',\n\n // One document per picture in a league, team, or landing page gallery. Public read; written only\n // by the picture core.\n GALLERY_PICTURES: 'galleryPictures',\n // One accepted picture upload, id = its staging id = the picture id. Read by its uploader and\n // admins; written only by the accept core (the upload callable and the picture carry), the\n // processing trigger, and the maintenance sweep's stale-upload pass; never deleted.\n PENDING_MEDIA: 'pendingMedia',\n // The durable obligation to delete a picture's files, or a deleted owner's whole gallery. No\n // client access; carried out by the media maintenance sweep.\n PICTURE_RETIREMENTS: 'pictureRetirements',\n\n // Append-only record of sensitive actions. No client access; written only by Cloud Functions.\n AUDIT_EVENTS: 'auditEvents',\n\n // Admin notifications, all written only by Cloud Functions. The shared cards every admin reads and\n // their archived history are admin read; the delivery ledger the owning callables write each\n // occurrence into, and each admin's archive-all job, have no client access.\n ACTIVE_ADMIN_NOTIFICATIONS: 'activeAdminNotifications',\n ADMIN_NOTIFICATION_HISTORY: 'adminNotificationHistory',\n NOTIFICATION_DELIVERIES: 'notificationDeliveries',\n NOTIFICATION_ARCHIVE_ALL_JOBS: 'notificationArchiveAllJobs',\n\n // Fixed-ID system document buckets\n APP_CONFIG: '_appConfig',\n SYSTEM_DATA: '_systemData',\n SERVER_DATA: '_serverData',\n} as const;\n\nexport type CollectionName = (typeof COLLECTIONS)[keyof typeof COLLECTIONS];\n\n/** Subcollections of `userProfiles/{userId}`. */\nexport const USER_PROFILE_SUBCOLLECTIONS = {\n // One document per sport key: pre-Q-Sports career totals folded into lifetime recalculation.\n HISTORICAL_STATS: 'historicalStats',\n // One owner-only document, id = the userId: email and contact details. The profile itself is\n // publicly readable, so nothing personal lives on it (BACKEND-105).\n PRIVATE_DATA: 'privateData',\n} as const;\n\n/** Subcollections of `sportGames/{gameId}`. */\nexport const SPORT_GAME_SUBCOLLECTIONS = {\n // Who participated in the game: one entry per team per person, id `buildGameRosterPlayerId`.\n GAME_ROSTER_PLAYERS: 'gameRosterPlayers',\n // One stat event per document, keyed by the event id minted at the tap.\n GAME_STAT_EVENTS: 'gameStatEvents',\n // A completed game's finalized record, in pages, id `buildStatHistoryPageId`.\n GAME_STAT_HISTORY: 'gameStatHistory',\n} as const;\n\n/** Subcollections of `waiverTemplates/{waiverTemplateId}`. */\nexport const WAIVER_TEMPLATE_SUBCOLLECTIONS = {\n // One immutable document per published wording, id `buildWaiverTemplateVersionId(version)`.\n WAIVER_TEMPLATE_VERSIONS: 'waiverTemplateVersions',\n} as const;\n\n/** Static document IDs for fixed-ID documents. */\nexport const SPECIAL_DOCS = {\n // _appConfig — public read\n // The app-wide operational levers: version gate, maintenance mode, registration switch, banner.\n APP_CONFIG: 'app',\n LANDING_PAGE: 'landingPage',\n // Public because signed-out spectators follow it for live updates.\n STATS_BEACON: 'statsBeacon',\n\n // _systemData — signed-in read\n // The admin and referee rosters — source of truth for the `admin` / `referee` custom claims.\n ADMIN_LIST: 'adminList',\n\n // _serverData — no client access\n // The migration console: the cutover marker and the lock that keeps two actions from running at\n // once.\n MIGRATION_CONSOLE: 'migrationConsole',\n} as const;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"path-builders.js","sourceRoot":"","sources":["../../src/paths/path-builders.ts"],"names":[],"mappings":"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","sourcesContent":["// Document path builders — segment tuples, the one path family.\r\n//\r\n// Frontend: doc(db, ...PATH_BUILDERS.userProfile(userId))\r\n// Backend: db.doc(toPath(PATH_BUILDERS.userProfile(userId)))\r\n//\r\n// A singular name builds a document path; its plural builds the parent collection path where the\r\n// parent is a subcollection (top-level collections are in COLLECTION_REFS). A compound document ID\r\n// is assembled here through its one builder in ../ids — never at a call site.\r\n\r\nimport {\r\n COLLECTIONS,\r\n SPORT_GAME_SUBCOLLECTIONS,\r\n SPECIAL_DOCS,\r\n USER_PROFILE_SUBCOLLECTIONS,\r\n WAIVER_TEMPLATE_SUBCOLLECTIONS,\r\n} from './collections.js';\r\nimport type { SweepStateName } from '../constants/scheduled-jobs.js';\r\nimport {\r\n buildGameRosterPlayerId,\r\n buildLeagueFreeAgentId,\r\n buildTeamMembershipId,\r\n buildSignedWaiverId,\r\n} from '../ids/compound-ids.js';\r\nimport { buildWaiverTemplateVersionId } from '../ids/waiver-template-ids.js';\r\nimport type { SportKey } from '../types/sports.js';\r\nimport { toReservedDisplayNameKey } from '../utils/display-name.js';\r\n\r\nexport const PATH_BUILDERS = {\r\n // People\r\n userProfile: (userId: string): [string, string] => [COLLECTIONS.USER_PROFILES, userId],\r\n userPrivateData: (userId: string): [string, string, string, string] => [\r\n COLLECTIONS.USER_PROFILES,\r\n userId,\r\n USER_PROFILE_SUBCOLLECTIONS.PRIVATE_DATA,\r\n userId,\r\n ],\r\n historicalStat: (userId: string, sportKey: SportKey): [string, string, string, string] => [\r\n COLLECTIONS.USER_PROFILES,\r\n userId,\r\n USER_PROFILE_SUBCOLLECTIONS.HISTORICAL_STATS,\r\n sportKey,\r\n ],\r\n historicalStats: (userId: string): [string, string, string] => [\r\n COLLECTIONS.USER_PROFILES,\r\n userId,\r\n USER_PROFILE_SUBCOLLECTIONS.HISTORICAL_STATS,\r\n ],\r\n publicUser: (userId: string): [string, string] => [COLLECTIONS.PUBLIC_USERS, userId],\r\n statusReconcileQueueEntry: (userId: string): [string, string] => [COLLECTIONS.STATUS_RECONCILE_QUEUE, userId],\r\n registrationStart: (userId: string): [string, string] => [COLLECTIONS.REGISTRATION_STARTS, userId],\r\n sweepState: (name: SweepStateName): [string, string] => [COLLECTIONS.SWEEP_STATE, name],\r\n reservedDisplayName: (displayName: string): [string, string] => [\r\n COLLECTIONS.RESERVED_DISPLAY_NAMES,\r\n toReservedDisplayNameKey(displayName),\r\n ],\r\n\r\n // Leagues, teams, membership\r\n sportLeague: (leagueId: string): [string, string] => [COLLECTIONS.SPORT_LEAGUES, leagueId],\r\n leagueTeam: (teamId: string): [string, string] => [COLLECTIONS.LEAGUE_TEAMS, teamId],\r\n leagueTeamContact: (teamId: string): [string, string] => [COLLECTIONS.LEAGUE_TEAM_CONTACTS, teamId],\r\n teamMembership: (leagueId: string, teamId: string, userId: string): [string, string] => [\r\n COLLECTIONS.TEAM_MEMBERSHIPS,\r\n buildTeamMembershipId(leagueId, teamId, userId),\r\n ],\r\n membershipRosterSync: (leagueId: string, teamId: string, userId: string): [string, string] => [\r\n COLLECTIONS.MEMBERSHIP_ROSTER_SYNCS,\r\n buildTeamMembershipId(leagueId, teamId, userId),\r\n ],\r\n teamInvitation: (inviteId: string): [string, string] => [COLLECTIONS.TEAM_INVITATIONS, inviteId],\r\n teamJoinRequest: (requestId: string): [string, string] => [COLLECTIONS.TEAM_JOIN_REQUESTS, requestId],\r\n leagueFreeAgent: (leagueId: string, userId: string): [string, string] => [\r\n COLLECTIONS.LEAGUE_FREE_AGENTS,\r\n buildLeagueFreeAgentId(leagueId, userId),\r\n ],\r\n\r\n // Games\r\n sportGame: (gameId: string): [string, string] => [COLLECTIONS.SPORT_GAMES, gameId],\r\n gameRosterPlayer: (gameId: string, teamId: string, userId: string): [string, string, string, string] => [\r\n COLLECTIONS.SPORT_GAMES,\r\n gameId,\r\n SPORT_GAME_SUBCOLLECTIONS.GAME_ROSTER_PLAYERS,\r\n buildGameRosterPlayerId(teamId, userId),\r\n ],\r\n gameRosterPlayers: (gameId: string): [string, string, string] => [\r\n COLLECTIONS.SPORT_GAMES,\r\n gameId,\r\n SPORT_GAME_SUBCOLLECTIONS.GAME_ROSTER_PLAYERS,\r\n ],\r\n gameStatEvent: (gameId: string, eventId: string): [string, string, string, string] => [\r\n COLLECTIONS.SPORT_GAMES,\r\n gameId,\r\n SPORT_GAME_SUBCOLLECTIONS.GAME_STAT_EVENTS,\r\n eventId,\r\n ],\r\n gameStatEvents: (gameId: string): [string, string, string] => [\r\n COLLECTIONS.SPORT_GAMES,\r\n gameId,\r\n SPORT_GAME_SUBCOLLECTIONS.GAME_STAT_EVENTS,\r\n ],\r\n gameStatHistoryPage: (gameId: string, pageId: string): [string, string, string, string] => [\r\n COLLECTIONS.SPORT_GAMES,\r\n gameId,\r\n SPORT_GAME_SUBCOLLECTIONS.GAME_STAT_HISTORY,\r\n pageId,\r\n ],\r\n gameStatHistory: (gameId: string): [string, string, string] => [\r\n COLLECTIONS.SPORT_GAMES,\r\n gameId,\r\n SPORT_GAME_SUBCOLLECTIONS.GAME_STAT_HISTORY,\r\n ],\r\n gameLocation: (gameLocationId: string): [string, string] => [COLLECTIONS.GAME_LOCATIONS, gameLocationId],\r\n\r\n // Waivers and hardware\r\n waiverTemplate: (waiverTemplateId: string): [string, string] => [\r\n COLLECTIONS.WAIVER_TEMPLATES,\r\n waiverTemplateId,\r\n ],\r\n waiverTemplateVersion: (waiverTemplateId: string, version: number): [string, string, string, string] => [\r\n COLLECTIONS.WAIVER_TEMPLATES,\r\n waiverTemplateId,\r\n WAIVER_TEMPLATE_SUBCOLLECTIONS.WAIVER_TEMPLATE_VERSIONS,\r\n buildWaiverTemplateVersionId(version),\r\n ],\r\n waiverTemplateVersions: (waiverTemplateId: string): [string, string, string] => [\r\n COLLECTIONS.WAIVER_TEMPLATES,\r\n waiverTemplateId,\r\n WAIVER_TEMPLATE_SUBCOLLECTIONS.WAIVER_TEMPLATE_VERSIONS,\r\n ],\r\n signedWaiver: (leagueId: string, userId: string): [string, string] => [\r\n COLLECTIONS.SIGNED_WAIVERS,\r\n buildSignedWaiverId(leagueId, userId),\r\n ],\r\n hardwareLoanContract: (contractId: string): [string, string] => [\r\n COLLECTIONS.HARDWARE_LOAN_CONTRACTS,\r\n contractId,\r\n ],\r\n\r\n // Awards and derived stats\r\n awardDefinition: (awardId: string): [string, string] => [COLLECTIONS.AWARD_DEFINITIONS, awardId],\r\n sportHallOfFame: (sportKey: SportKey): [string, string] => [COLLECTIONS.SPORT_HALL_OF_FAME, sportKey],\r\n statsValidationReport: (reportId: string): [string, string] => [\r\n COLLECTIONS.STATS_VALIDATION_REPORTS,\r\n reportId,\r\n ],\r\n statsOperation: (operationId: string): [string, string] => [COLLECTIONS.STATS_OPERATIONS, operationId],\r\n migrationActionRun: (actionId: string): [string, string] => [COLLECTIONS.MIGRATION_ACTION_RUNS, actionId],\r\n\r\n galleryPicture: (pictureId: string): [string, string] => [COLLECTIONS.GALLERY_PICTURES, pictureId],\r\n pendingMedia: (pendingMediaId: string): [string, string] => [COLLECTIONS.PENDING_MEDIA, pendingMediaId],\r\n // A picture's retirement is keyed by the picture id; a whole gallery's by `buildGalleryRetirementId`.\r\n pictureRetirement: (retirementId: string): [string, string] => [\r\n COLLECTIONS.PICTURE_RETIREMENTS,\r\n retirementId,\r\n ],\r\n\r\n auditEvent: (auditEventId: string): [string, string] => [COLLECTIONS.AUDIT_EVENTS, auditEventId],\r\n\r\n // Admin notifications. A card's id is notification-core's; the others come from ../ids.\r\n activeAdminNotification: (notificationId: string): [string, string] => [\r\n COLLECTIONS.ACTIVE_ADMIN_NOTIFICATIONS,\r\n notificationId,\r\n ],\r\n adminNotificationHistoryEntry: (historyId: string): [string, string] => [\r\n COLLECTIONS.ADMIN_NOTIFICATION_HISTORY,\r\n historyId,\r\n ],\r\n notificationDelivery: (deliveryId: string): [string, string] => [COLLECTIONS.NOTIFICATION_DELIVERIES, deliveryId],\r\n notificationArchiveAllJob: (jobId: string): [string, string] => [COLLECTIONS.NOTIFICATION_ARCHIVE_ALL_JOBS, jobId],\r\n\r\n // Fixed-ID system documents\r\n landingPageConfig: (): [string, string] => [COLLECTIONS.APP_CONFIG, SPECIAL_DOCS.LANDING_PAGE],\r\n appConfig: (): [string, string] => [COLLECTIONS.APP_CONFIG, SPECIAL_DOCS.APP_CONFIG],\r\n statsBeacon: (): [string, string] => [COLLECTIONS.APP_CONFIG, SPECIAL_DOCS.STATS_BEACON],\r\n adminList: (): [string, string] => [COLLECTIONS.SYSTEM_DATA, SPECIAL_DOCS.ADMIN_LIST],\r\n migrationConsole: (): [string, string] => [COLLECTIONS.SERVER_DATA, SPECIAL_DOCS.MIGRATION_CONSOLE],\r\n} as const;\r\n"]}
1
+ {"version":3,"file":"path-builders.js","sourceRoot":"","sources":["../../src/paths/path-builders.ts"],"names":[],"mappings":"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","sourcesContent":["// Document path builders — segment tuples, the one path family.\n//\n// Frontend: doc(db, ...PATH_BUILDERS.userProfile(userId))\n// Backend: db.doc(toPath(PATH_BUILDERS.userProfile(userId)))\n//\n// A singular name builds a document path; its plural builds the parent collection path where the\n// parent is a subcollection (top-level collections are in COLLECTION_REFS). A compound document ID\n// is assembled here through its one builder in ../ids — never at a call site.\n\nimport {\n COLLECTIONS,\n SPORT_GAME_SUBCOLLECTIONS,\n SPECIAL_DOCS,\n USER_PROFILE_SUBCOLLECTIONS,\n WAIVER_TEMPLATE_SUBCOLLECTIONS,\n} from './collections.js';\nimport type { SweepStateName } from '../constants/scheduled-jobs.js';\nimport {\n buildGameRosterPlayerId,\n buildLeagueFreeAgentId,\n buildTeamMembershipId,\n buildSignedWaiverId,\n} from '../ids/compound-ids.js';\nimport { buildWaiverTemplateVersionId } from '../ids/waiver-template-ids.js';\nimport type { SportKey } from '../types/sports.js';\nimport { toReservedDisplayNameKey } from '../utils/display-name.js';\n\nexport const PATH_BUILDERS = {\n // People\n userProfile: (userId: string): [string, string] => [COLLECTIONS.USER_PROFILES, userId],\n userPrivateData: (userId: string): [string, string, string, string] => [\n COLLECTIONS.USER_PROFILES,\n userId,\n USER_PROFILE_SUBCOLLECTIONS.PRIVATE_DATA,\n userId,\n ],\n historicalStat: (userId: string, sportKey: SportKey): [string, string, string, string] => [\n COLLECTIONS.USER_PROFILES,\n userId,\n USER_PROFILE_SUBCOLLECTIONS.HISTORICAL_STATS,\n sportKey,\n ],\n historicalStats: (userId: string): [string, string, string] => [\n COLLECTIONS.USER_PROFILES,\n userId,\n USER_PROFILE_SUBCOLLECTIONS.HISTORICAL_STATS,\n ],\n publicUser: (userId: string): [string, string] => [COLLECTIONS.PUBLIC_USERS, userId],\n statusReconcileQueueEntry: (userId: string): [string, string] => [COLLECTIONS.STATUS_RECONCILE_QUEUE, userId],\n registrationStart: (userId: string): [string, string] => [COLLECTIONS.REGISTRATION_STARTS, userId],\n sweepState: (name: SweepStateName): [string, string] => [COLLECTIONS.SWEEP_STATE, name],\n reservedDisplayName: (displayName: string): [string, string] => [\n COLLECTIONS.RESERVED_DISPLAY_NAMES,\n toReservedDisplayNameKey(displayName),\n ],\n\n // Leagues, teams, membership\n sportLeague: (leagueId: string): [string, string] => [COLLECTIONS.SPORT_LEAGUES, leagueId],\n leagueTeam: (teamId: string): [string, string] => [COLLECTIONS.LEAGUE_TEAMS, teamId],\n leagueTeamContact: (teamId: string): [string, string] => [COLLECTIONS.LEAGUE_TEAM_CONTACTS, teamId],\n teamMembership: (leagueId: string, teamId: string, userId: string): [string, string] => [\n COLLECTIONS.TEAM_MEMBERSHIPS,\n buildTeamMembershipId(leagueId, teamId, userId),\n ],\n membershipRosterSync: (leagueId: string, teamId: string, userId: string): [string, string] => [\n COLLECTIONS.MEMBERSHIP_ROSTER_SYNCS,\n buildTeamMembershipId(leagueId, teamId, userId),\n ],\n teamInvitation: (inviteId: string): [string, string] => [COLLECTIONS.TEAM_INVITATIONS, inviteId],\n teamJoinRequest: (requestId: string): [string, string] => [COLLECTIONS.TEAM_JOIN_REQUESTS, requestId],\n leagueFreeAgent: (leagueId: string, userId: string): [string, string] => [\n COLLECTIONS.LEAGUE_FREE_AGENTS,\n buildLeagueFreeAgentId(leagueId, userId),\n ],\n\n // Games\n sportGame: (gameId: string): [string, string] => [COLLECTIONS.SPORT_GAMES, gameId],\n gameRosterPlayer: (gameId: string, teamId: string, userId: string): [string, string, string, string] => [\n COLLECTIONS.SPORT_GAMES,\n gameId,\n SPORT_GAME_SUBCOLLECTIONS.GAME_ROSTER_PLAYERS,\n buildGameRosterPlayerId(teamId, userId),\n ],\n gameRosterPlayers: (gameId: string): [string, string, string] => [\n COLLECTIONS.SPORT_GAMES,\n gameId,\n SPORT_GAME_SUBCOLLECTIONS.GAME_ROSTER_PLAYERS,\n ],\n gameStatEvent: (gameId: string, eventId: string): [string, string, string, string] => [\n COLLECTIONS.SPORT_GAMES,\n gameId,\n SPORT_GAME_SUBCOLLECTIONS.GAME_STAT_EVENTS,\n eventId,\n ],\n gameStatEvents: (gameId: string): [string, string, string] => [\n COLLECTIONS.SPORT_GAMES,\n gameId,\n SPORT_GAME_SUBCOLLECTIONS.GAME_STAT_EVENTS,\n ],\n gameStatHistoryPage: (gameId: string, pageId: string): [string, string, string, string] => [\n COLLECTIONS.SPORT_GAMES,\n gameId,\n SPORT_GAME_SUBCOLLECTIONS.GAME_STAT_HISTORY,\n pageId,\n ],\n gameStatHistory: (gameId: string): [string, string, string] => [\n COLLECTIONS.SPORT_GAMES,\n gameId,\n SPORT_GAME_SUBCOLLECTIONS.GAME_STAT_HISTORY,\n ],\n gameLocation: (gameLocationId: string): [string, string] => [COLLECTIONS.GAME_LOCATIONS, gameLocationId],\n\n // Waivers and hardware\n waiverTemplate: (waiverTemplateId: string): [string, string] => [\n COLLECTIONS.WAIVER_TEMPLATES,\n waiverTemplateId,\n ],\n waiverTemplateVersion: (waiverTemplateId: string, version: number): [string, string, string, string] => [\n COLLECTIONS.WAIVER_TEMPLATES,\n waiverTemplateId,\n WAIVER_TEMPLATE_SUBCOLLECTIONS.WAIVER_TEMPLATE_VERSIONS,\n buildWaiverTemplateVersionId(version),\n ],\n waiverTemplateVersions: (waiverTemplateId: string): [string, string, string] => [\n COLLECTIONS.WAIVER_TEMPLATES,\n waiverTemplateId,\n WAIVER_TEMPLATE_SUBCOLLECTIONS.WAIVER_TEMPLATE_VERSIONS,\n ],\n signedWaiver: (leagueId: string, userId: string): [string, string] => [\n COLLECTIONS.SIGNED_WAIVERS,\n buildSignedWaiverId(leagueId, userId),\n ],\n hardwareLoanContract: (contractId: string): [string, string] => [\n COLLECTIONS.HARDWARE_LOAN_CONTRACTS,\n contractId,\n ],\n\n // Awards and derived stats\n awardDefinition: (awardId: string): [string, string] => [COLLECTIONS.AWARD_DEFINITIONS, awardId],\n sportHallOfFame: (sportKey: SportKey): [string, string] => [COLLECTIONS.SPORT_HALL_OF_FAME, sportKey],\n statsValidationReport: (reportId: string): [string, string] => [\n COLLECTIONS.STATS_VALIDATION_REPORTS,\n reportId,\n ],\n statsOperation: (operationId: string): [string, string] => [COLLECTIONS.STATS_OPERATIONS, operationId],\n migrationActionRun: (actionId: string): [string, string] => [COLLECTIONS.MIGRATION_ACTION_RUNS, actionId],\n\n galleryPicture: (pictureId: string): [string, string] => [COLLECTIONS.GALLERY_PICTURES, pictureId],\n pendingMedia: (pendingMediaId: string): [string, string] => [COLLECTIONS.PENDING_MEDIA, pendingMediaId],\n // A picture's retirement is keyed by the picture id; a whole gallery's by `buildGalleryRetirementId`.\n pictureRetirement: (retirementId: string): [string, string] => [\n COLLECTIONS.PICTURE_RETIREMENTS,\n retirementId,\n ],\n\n auditEvent: (auditEventId: string): [string, string] => [COLLECTIONS.AUDIT_EVENTS, auditEventId],\n\n // Admin notifications. A card's id is notification-core's; the others come from ../ids.\n activeAdminNotification: (notificationId: string): [string, string] => [\n COLLECTIONS.ACTIVE_ADMIN_NOTIFICATIONS,\n notificationId,\n ],\n adminNotificationHistoryEntry: (historyId: string): [string, string] => [\n COLLECTIONS.ADMIN_NOTIFICATION_HISTORY,\n historyId,\n ],\n notificationDelivery: (deliveryId: string): [string, string] => [COLLECTIONS.NOTIFICATION_DELIVERIES, deliveryId],\n notificationArchiveAllJob: (jobId: string): [string, string] => [COLLECTIONS.NOTIFICATION_ARCHIVE_ALL_JOBS, jobId],\n\n // Fixed-ID system documents\n landingPageConfig: (): [string, string] => [COLLECTIONS.APP_CONFIG, SPECIAL_DOCS.LANDING_PAGE],\n appConfig: (): [string, string] => [COLLECTIONS.APP_CONFIG, SPECIAL_DOCS.APP_CONFIG],\n statsBeacon: (): [string, string] => [COLLECTIONS.APP_CONFIG, SPECIAL_DOCS.STATS_BEACON],\n adminList: (): [string, string] => [COLLECTIONS.SYSTEM_DATA, SPECIAL_DOCS.ADMIN_LIST],\n migrationConsole: (): [string, string] => [COLLECTIONS.SERVER_DATA, SPECIAL_DOCS.MIGRATION_CONSOLE],\n} as const;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/paths/utils.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,2DAA2D;AAE3D,MAAM,UAAU,MAAM,CAAC,QAA2B;IAChD,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,sDAAsD;AACtD,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAE1C,MAAM,4BAA4B,GAAG,UAAU,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAU;IAC5C,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACtD,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,4BAA4B,CAAC,IAAI,CAAC,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IACxD,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,IAAI,qBAAqB,CAAC;AACtE,CAAC","sourcesContent":["// Utility to convert path tuples to slash-delimited strings for Admin SDK.\r\n//\r\n// Usage: db.doc(toPath(PATH_BUILDERS.userProfile(userId)))\r\n\r\nexport function toPath(segments: readonly string[]): string {\r\n return segments.join('/');\r\n}\r\n\r\n// Firestore's limit on a document id, in UTF-8 bytes.\r\nexport const MAX_DOCUMENT_ID_BYTES = 1500;\r\n\r\nconst RESERVED_DOCUMENT_ID_PATTERN = /^__.*__$/;\r\n\r\n/**\r\n * Whether `id` names exactly one document under its collection: non-empty, no `/`, at most\r\n * `MAX_DOCUMENT_ID_BYTES` UTF-8 bytes, not `.` or `..`, and not an id Firestore reserves (`__…__`).\r\n * A `/` would address another document or a subcollection, and an empty id the collection itself,\r\n * so every id atom a path is built from checks this before any path exists (ARCH-106).\r\n */\r\nexport function isDocumentIdSegment(id: string): boolean {\r\n if (id.length === 0 || id.includes('/')) return false;\r\n if (id === '.' || id === '..') return false;\r\n if (RESERVED_DOCUMENT_ID_PATTERN.test(id)) return false;\r\n return new TextEncoder().encode(id).length <= MAX_DOCUMENT_ID_BYTES;\r\n}\r\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/paths/utils.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,2DAA2D;AAE3D,MAAM,UAAU,MAAM,CAAC,QAA2B;IAChD,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,sDAAsD;AACtD,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAE1C,MAAM,4BAA4B,GAAG,UAAU,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAU;IAC5C,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACtD,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,4BAA4B,CAAC,IAAI,CAAC,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IACxD,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,IAAI,qBAAqB,CAAC;AACtE,CAAC","sourcesContent":["// Utility to convert path tuples to slash-delimited strings for Admin SDK.\n//\n// Usage: db.doc(toPath(PATH_BUILDERS.userProfile(userId)))\n\nexport function toPath(segments: readonly string[]): string {\n return segments.join('/');\n}\n\n// Firestore's limit on a document id, in UTF-8 bytes.\nexport const MAX_DOCUMENT_ID_BYTES = 1500;\n\nconst RESERVED_DOCUMENT_ID_PATTERN = /^__.*__$/;\n\n/**\n * Whether `id` names exactly one document under its collection: non-empty, no `/`, at most\n * `MAX_DOCUMENT_ID_BYTES` UTF-8 bytes, not `.` or `..`, and not an id Firestore reserves (`__…__`).\n * A `/` would address another document or a subcollection, and an empty id the collection itself,\n * so every id atom a path is built from checks this before any path exists (ARCH-106).\n */\nexport function isDocumentIdSegment(id: string): boolean {\n if (id.length === 0 || id.includes('/')) return false;\n if (id === '.' || id === '..') return false;\n if (RESERVED_DOCUMENT_ID_PATTERN.test(id)) return false;\n return new TextEncoder().encode(id).length <= MAX_DOCUMENT_ID_BYTES;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"account-settings.js","sourceRoot":"","sources":["../../src/schemas/account-settings.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kGAAkG;AAClG,gGAAgG;AAChG,kFAAkF;AAElF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC;KAC9C,MAAM,CAAC;IACN,KAAK,EAAE,eAAe,CAAC,QAAQ,EAAE;IACjC,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACrC,mCAAmC;IACnC,mBAAmB,EAAE,kBAAkB,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CAC9D,CAAC;KACD,MAAM,EAAE;KACR,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,EAAE;IAC5E,OAAO,EAAE,8BAA8B;CACxC,CAAC,CAAC;AAGL,kGAAkG;AAClG,sCAAsC;AACtC,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC;KAC/C,MAAM,CAAC;IACN,KAAK,EAAE,eAAe,CAAC,QAAQ,EAAE;IACjC,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACrC,mBAAmB,EAAE,kBAAkB,CAAC,QAAQ,EAAE;IAClD,SAAS,EAAE,aAAa;CACzB,CAAC;KACD,MAAM,EAAE,CAAC","sourcesContent":["// Callable contract for the signed-in user's own settings on their owner-only\r\n// `userProfiles/{userId}/privateData/{userId}` document: the account's copy of the viewer's theme\r\n// and motion — the save theme-core's settings sync calls — and the account-only default contact\r\n// phone. The caller is always the account being changed; no user id is ever sent.\r\n\r\nimport { z } from 'zod';\r\nimport { epochMsSchema } from '../doc-schemas/atoms.js';\r\nimport { themeNameSchema } from '../doc-schemas/user-profile.js';\r\nimport { contactPhoneSchema } from './atoms.js';\r\n\r\nexport const UpdateAccountSettingsInputSchema = z\r\n .object({\r\n theme: themeNameSchema.optional(),\r\n reducedMotion: z.boolean().optional(),\r\n // `null` removes the saved number.\r\n defaultContactPhone: contactPhoneSchema.nullable().optional(),\r\n })\r\n .strict()\r\n .refine((input) => Object.values(input).some((value) => value !== undefined), {\r\n message: 'Change at least one setting.',\r\n });\r\nexport type UpdateAccountSettingsInput = z.infer<typeof UpdateAccountSettingsInputSchema>;\r\n\r\n// Every setting as committed, `null` where the account has nothing saved — the shape the settings\r\n// sync reads the account's values in.\r\nexport const UpdateAccountSettingsResultSchema = z\r\n .object({\r\n theme: themeNameSchema.nullable(),\r\n reducedMotion: z.boolean().nullable(),\r\n defaultContactPhone: contactPhoneSchema.nullable(),\r\n updatedAt: epochMsSchema,\r\n })\r\n .strict();\r\nexport type UpdateAccountSettingsResult = z.infer<typeof UpdateAccountSettingsResultSchema>;\r\n"]}
1
+ {"version":3,"file":"account-settings.js","sourceRoot":"","sources":["../../src/schemas/account-settings.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kGAAkG;AAClG,gGAAgG;AAChG,kFAAkF;AAElF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC;KAC9C,MAAM,CAAC;IACN,KAAK,EAAE,eAAe,CAAC,QAAQ,EAAE;IACjC,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACrC,mCAAmC;IACnC,mBAAmB,EAAE,kBAAkB,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CAC9D,CAAC;KACD,MAAM,EAAE;KACR,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,EAAE;IAC5E,OAAO,EAAE,8BAA8B;CACxC,CAAC,CAAC;AAGL,kGAAkG;AAClG,sCAAsC;AACtC,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC;KAC/C,MAAM,CAAC;IACN,KAAK,EAAE,eAAe,CAAC,QAAQ,EAAE;IACjC,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACrC,mBAAmB,EAAE,kBAAkB,CAAC,QAAQ,EAAE;IAClD,SAAS,EAAE,aAAa;CACzB,CAAC;KACD,MAAM,EAAE,CAAC","sourcesContent":["// Callable contract for the signed-in user's own settings on their owner-only\n// `userProfiles/{userId}/privateData/{userId}` document: the account's copy of the viewer's theme\n// and motion — the save theme-core's settings sync calls — and the account-only default contact\n// phone. The caller is always the account being changed; no user id is ever sent.\n\nimport { z } from 'zod';\nimport { epochMsSchema } from '../doc-schemas/atoms.js';\nimport { themeNameSchema } from '../doc-schemas/user-profile.js';\nimport { contactPhoneSchema } from './atoms.js';\n\nexport const UpdateAccountSettingsInputSchema = z\n .object({\n theme: themeNameSchema.optional(),\n reducedMotion: z.boolean().optional(),\n // `null` removes the saved number.\n defaultContactPhone: contactPhoneSchema.nullable().optional(),\n })\n .strict()\n .refine((input) => Object.values(input).some((value) => value !== undefined), {\n message: 'Change at least one setting.',\n });\nexport type UpdateAccountSettingsInput = z.infer<typeof UpdateAccountSettingsInputSchema>;\n\n// Every setting as committed, `null` where the account has nothing saved — the shape the settings\n// sync reads the account's values in.\nexport const UpdateAccountSettingsResultSchema = z\n .object({\n theme: themeNameSchema.nullable(),\n reducedMotion: z.boolean().nullable(),\n defaultContactPhone: contactPhoneSchema.nullable(),\n updatedAt: epochMsSchema,\n })\n .strict();\nexport type UpdateAccountSettingsResult = z.infer<typeof UpdateAccountSettingsResultSchema>;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"atoms.js","sourceRoot":"","sources":["../../src/schemas/atoms.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,sGAAsG;AACtG,aAAa;AAEb,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,oCAAoC,EACpC,sCAAsC,EACtC,sBAAsB,GACvB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAEnF,OAAO,EACL,WAAW,EACX,aAAa,EACb,YAAY,EACZ,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,cAAc,EACd,cAAc,EACd,YAAY,GACb,MAAM,yBAAyB,CAAC;AAEjC,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AAC9D,MAAM,CAAC,MAAM,uBAAuB,GAAG,uBAAuB,CAAC;AAE/D,mGAAmG;AACnG,2BAA2B;AAC3B,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAC,yBAAyB,CAAC,CAAC;AAC5E,MAAM,CAAC,MAAM,cAAc,GAAG,eAAe,CAAC,sBAAsB,CAAC,CAAC;AACtE,kGAAkG;AAClG,+BAA+B;AAC/B,MAAM,CAAC,MAAM,4BAA4B,GAAG,eAAe,CAAC,sCAAsC,CAAC,CAAC;AACpG,+FAA+F;AAC/F,MAAM,CAAC,MAAM,2BAA2B,GAAG,eAAe,CAAC,oCAAoC,CAAC,CAAC;AACjG,kEAAkE;AAClE,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC,0BAA0B,CAAC,CAAC","sourcesContent":["// Atoms for callable wire contracts. Enums, id atoms, the count, and the repair reason are the\r\n// document atoms — one declaration, re-exported here so a callable schema file imports its atoms from\r\n// one place.\r\n\r\nimport {\r\n CONTACT_PHONE_INPUT_FORMAT,\r\n DISPLAY_NAME_INPUT_FORMAT,\r\n TEAM_INVITATION_MESSAGE_INPUT_FORMAT,\r\n TEAM_JOIN_REQUEST_MESSAGE_INPUT_FORMAT,\r\n TEAM_NAME_INPUT_FORMAT,\r\n} from '../input-formats/index.js';\r\n\r\nimport { documentIdSegmentSchema, textFieldSchema } from '../doc-schemas/atoms.js';\r\n\r\nexport {\r\n countSchema,\r\n epochMsSchema,\r\n gameIdSchema,\r\n gameRosterPlayerIdSchema,\r\n statEventIdSchema,\r\n leagueIdSchema,\r\n leagueModeSchema,\r\n repairReasonSchema,\r\n sportKeySchema,\r\n textFieldSchema,\r\n systemRoleSchema,\r\n teamIdSchema,\r\n teamIconSchema,\r\n teamRoleSchema,\r\n teamTypeSchema,\r\n userIdSchema,\r\n} from '../doc-schemas/atoms.js';\r\n\r\nexport const teamInvitationIdSchema = documentIdSegmentSchema;\r\nexport const teamJoinRequestIdSchema = documentIdSegmentSchema;\r\n\r\n// A display name and a team name, each built from its field's one declaration, so the form and the\r\n// wire run the same check.\r\nexport const displayNameSchema = textFieldSchema(DISPLAY_NAME_INPUT_FORMAT);\r\nexport const teamNameSchema = textFieldSchema(TEAM_NAME_INPUT_FORMAT);\r\n// A player's message with a join request, built from the field's one declaration, so the form and\r\n// the wire run the same check.\r\nexport const teamJoinRequestMessageSchema = textFieldSchema(TEAM_JOIN_REQUEST_MESSAGE_INPUT_FORMAT);\r\n// A captain's note on an invitation is optional — an empty note is stored as the empty string.\r\nexport const teamInvitationMessageSchema = textFieldSchema(TEAM_INVITATION_MESSAGE_INPUT_FORMAT);\r\n// A team's contact phone, built from its field's one declaration.\r\nexport const contactPhoneSchema = textFieldSchema(CONTACT_PHONE_INPUT_FORMAT);\r\n"]}
1
+ {"version":3,"file":"atoms.js","sourceRoot":"","sources":["../../src/schemas/atoms.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,sGAAsG;AACtG,aAAa;AAEb,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,oCAAoC,EACpC,sCAAsC,EACtC,sBAAsB,GACvB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAEnF,OAAO,EACL,WAAW,EACX,aAAa,EACb,YAAY,EACZ,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,cAAc,EACd,cAAc,EACd,YAAY,GACb,MAAM,yBAAyB,CAAC;AAEjC,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AAC9D,MAAM,CAAC,MAAM,uBAAuB,GAAG,uBAAuB,CAAC;AAE/D,mGAAmG;AACnG,2BAA2B;AAC3B,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAC,yBAAyB,CAAC,CAAC;AAC5E,MAAM,CAAC,MAAM,cAAc,GAAG,eAAe,CAAC,sBAAsB,CAAC,CAAC;AACtE,kGAAkG;AAClG,+BAA+B;AAC/B,MAAM,CAAC,MAAM,4BAA4B,GAAG,eAAe,CAAC,sCAAsC,CAAC,CAAC;AACpG,+FAA+F;AAC/F,MAAM,CAAC,MAAM,2BAA2B,GAAG,eAAe,CAAC,oCAAoC,CAAC,CAAC;AACjG,kEAAkE;AAClE,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC,0BAA0B,CAAC,CAAC","sourcesContent":["// Atoms for callable wire contracts. Enums, id atoms, the count, and the repair reason are the\n// document atoms — one declaration, re-exported here so a callable schema file imports its atoms from\n// one place.\n\nimport {\n CONTACT_PHONE_INPUT_FORMAT,\n DISPLAY_NAME_INPUT_FORMAT,\n TEAM_INVITATION_MESSAGE_INPUT_FORMAT,\n TEAM_JOIN_REQUEST_MESSAGE_INPUT_FORMAT,\n TEAM_NAME_INPUT_FORMAT,\n} from '../input-formats/index.js';\n\nimport { documentIdSegmentSchema, textFieldSchema } from '../doc-schemas/atoms.js';\n\nexport {\n countSchema,\n epochMsSchema,\n gameIdSchema,\n gameRosterPlayerIdSchema,\n statEventIdSchema,\n leagueIdSchema,\n leagueModeSchema,\n repairReasonSchema,\n sportKeySchema,\n textFieldSchema,\n systemRoleSchema,\n teamIdSchema,\n teamIconSchema,\n teamRoleSchema,\n teamTypeSchema,\n userIdSchema,\n} from '../doc-schemas/atoms.js';\n\nexport const teamInvitationIdSchema = documentIdSegmentSchema;\nexport const teamJoinRequestIdSchema = documentIdSegmentSchema;\n\n// A display name and a team name, each built from its field's one declaration, so the form and the\n// wire run the same check.\nexport const displayNameSchema = textFieldSchema(DISPLAY_NAME_INPUT_FORMAT);\nexport const teamNameSchema = textFieldSchema(TEAM_NAME_INPUT_FORMAT);\n// A player's message with a join request, built from the field's one declaration, so the form and\n// the wire run the same check.\nexport const teamJoinRequestMessageSchema = textFieldSchema(TEAM_JOIN_REQUEST_MESSAGE_INPUT_FORMAT);\n// A captain's note on an invitation is optional — an empty note is stored as the empty string.\nexport const teamInvitationMessageSchema = textFieldSchema(TEAM_INVITATION_MESSAGE_INPUT_FORMAT);\n// A team's contact phone, built from its field's one declaration.\nexport const contactPhoneSchema = textFieldSchema(CONTACT_PHONE_INPUT_FORMAT);\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"awards.js","sourceRoot":"","sources":["../../src/schemas/awards.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for the award catalog, award grants, and the badges an account features.\r\n//\r\n// An award is created by its first badge's publication (the `award-badge` upload, ./uploads.ts), so\r\n// no callable here creates one. Grants and revokes share one input — four named lists, never an\r\n// action discriminator (BACKEND-002) — like the role roster's.\r\n\r\nimport { z } from 'zod';\r\nimport { MAX_AWARD_GRANT_TARGETS } from '../constants/business.js';\r\nimport { awardIdSchema } from '../doc-schemas/catalogs.js';\r\nimport { AWARD_GRANT_SKIP_REASON_KEYS } from '../types/unions.js';\r\nimport { leagueIdSchema, teamIdSchema, userIdSchema } from './atoms.js';\r\n\r\nconst targetList = <T extends z.ZodTypeAny>(atom: T) => z.array(atom).max(MAX_AWARD_GRANT_TARGETS).optional();\r\n\r\n// An admin grants an award to accounts — named directly, or as every active real member of a team\r\n// or of a league — and revokes it from accounts. Recipients are resolved on the server, deduplicated,\r\n// and bounded by MAX_AWARD_GRANT_RECIPIENTS; ghosts hold no account and are skipped.\r\nexport const AdminUpdateAwardGrantsInputSchema = z\r\n .object({\r\n awardId: awardIdSchema,\r\n grantUserIds: targetList(userIdSchema),\r\n grantTeamIds: targetList(teamIdSchema),\r\n grantLeagueIds: targetList(leagueIdSchema),\r\n revokeUserIds: targetList(userIdSchema),\r\n })\r\n .strict()\r\n .refine(\r\n (input) =>\r\n [input.grantUserIds, input.grantTeamIds, input.grantLeagueIds, input.revokeUserIds].some(\r\n (list) => list !== undefined && list.length > 0,\r\n ),\r\n { message: 'Name someone to grant the award to or revoke it from.' },\r\n )\r\n .refine(\r\n (input) => !(input.grantUserIds ?? []).some((userId) => (input.revokeUserIds ?? []).includes(userId)),\r\n { message: 'An account cannot be granted and revoked the award in one change.', path: ['revokeUserIds'] },\r\n );\r\nexport type AdminUpdateAwardGrantsInput = z.infer<typeof AdminUpdateAwardGrantsInputSchema>;\r\n\r\nexport const AwardGrantSkipSchema = z\r\n .object({ userId: userIdSchema, reason: z.enum(AWARD_GRANT_SKIP_REASON_KEYS) })\r\n .strict();\r\nexport type AwardGrantSkip = z.infer<typeof AwardGrantSkipSchema>;\r\n\r\n// What the change did for each account it reached: granted now, already held, revoked now, not held\r\n// to begin with, or skipped with its reason. A retried call reports the accounts its first call\r\n// changed as already held or not held, and writes nothing again.\r\nexport const AdminUpdateAwardGrantsResultSchema = z\r\n .object({\r\n awardId: awardIdSchema,\r\n granted: z.array(userIdSchema),\r\n alreadyHeld: z.array(userIdSchema),\r\n revoked: z.array(userIdSchema),\r\n notHeld: z.array(userIdSchema),\r\n skipped: z.array(AwardGrantSkipSchema),\r\n })\r\n .strict();\r\nexport type AdminUpdateAwardGrantsResult = z.infer<typeof AdminUpdateAwardGrantsResultSchema>;\r\n\r\n// An admin deletes an award nobody holds. Its badge's files are retired with it.\r\nexport const AdminDeleteAwardDefinitionInputSchema = z.object({ awardId: awardIdSchema }).strict();\r\nexport type AdminDeleteAwardDefinitionInput = z.infer<typeof AdminDeleteAwardDefinitionInputSchema>;\r\n\r\n// `deleted` is false when the award was already gone: nothing was written.\r\nexport const AdminDeleteAwardDefinitionResultSchema = z\r\n .object({ awardId: awardIdSchema, deleted: z.boolean() })\r\n .strict();\r\nexport type AdminDeleteAwardDefinitionResult = z.infer<typeof AdminDeleteAwardDefinitionResultSchema>;\r\n\r\n// The signed-in account chooses which of its own awards to show beside its name: a primary and a\r\n// secondary badge, each an award it holds, or `null` for none. No user id is ever sent.\r\nexport const UpdateFeaturedAwardsInputSchema = z\r\n .object({ primaryAwardId: awardIdSchema.nullable(), secondaryAwardId: awardIdSchema.nullable() })\r\n .strict()\r\n .refine(\r\n (input) => input.primaryAwardId === null || input.primaryAwardId !== input.secondaryAwardId,\r\n { message: 'Choose two different awards.', path: ['secondaryAwardId'] },\r\n );\r\nexport type UpdateFeaturedAwardsInput = z.infer<typeof UpdateFeaturedAwardsInputSchema>;\r\n\r\nexport const UpdateFeaturedAwardsResultSchema = z\r\n .object({\r\n userId: userIdSchema,\r\n primaryAwardId: awardIdSchema.nullable(),\r\n secondaryAwardId: awardIdSchema.nullable(),\r\n changed: z.boolean(),\r\n })\r\n .strict();\r\nexport type UpdateFeaturedAwardsResult = z.infer<typeof UpdateFeaturedAwardsResultSchema>;\r\n"]}
1
+ {"version":3,"file":"awards.js","sourceRoot":"","sources":["../../src/schemas/awards.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for the award catalog, award grants, and the badges an account features.\n//\n// An award is created by its first badge's publication (the `award-badge` upload, ./uploads.ts), so\n// no callable here creates one. Grants and revokes share one input — four named lists, never an\n// action discriminator (BACKEND-002) — like the role roster's.\n\nimport { z } from 'zod';\nimport { MAX_AWARD_GRANT_TARGETS } from '../constants/business.js';\nimport { awardIdSchema } from '../doc-schemas/catalogs.js';\nimport { AWARD_GRANT_SKIP_REASON_KEYS } from '../types/unions.js';\nimport { leagueIdSchema, teamIdSchema, userIdSchema } from './atoms.js';\n\nconst targetList = <T extends z.ZodTypeAny>(atom: T) => z.array(atom).max(MAX_AWARD_GRANT_TARGETS).optional();\n\n// An admin grants an award to accounts — named directly, or as every active real member of a team\n// or of a league — and revokes it from accounts. Recipients are resolved on the server, deduplicated,\n// and bounded by MAX_AWARD_GRANT_RECIPIENTS; ghosts hold no account and are skipped.\nexport const AdminUpdateAwardGrantsInputSchema = z\n .object({\n awardId: awardIdSchema,\n grantUserIds: targetList(userIdSchema),\n grantTeamIds: targetList(teamIdSchema),\n grantLeagueIds: targetList(leagueIdSchema),\n revokeUserIds: targetList(userIdSchema),\n })\n .strict()\n .refine(\n (input) =>\n [input.grantUserIds, input.grantTeamIds, input.grantLeagueIds, input.revokeUserIds].some(\n (list) => list !== undefined && list.length > 0,\n ),\n { message: 'Name someone to grant the award to or revoke it from.' },\n )\n .refine(\n (input) => !(input.grantUserIds ?? []).some((userId) => (input.revokeUserIds ?? []).includes(userId)),\n { message: 'An account cannot be granted and revoked the award in one change.', path: ['revokeUserIds'] },\n );\nexport type AdminUpdateAwardGrantsInput = z.infer<typeof AdminUpdateAwardGrantsInputSchema>;\n\nexport const AwardGrantSkipSchema = z\n .object({ userId: userIdSchema, reason: z.enum(AWARD_GRANT_SKIP_REASON_KEYS) })\n .strict();\nexport type AwardGrantSkip = z.infer<typeof AwardGrantSkipSchema>;\n\n// What the change did for each account it reached: granted now, already held, revoked now, not held\n// to begin with, or skipped with its reason. A retried call reports the accounts its first call\n// changed as already held or not held, and writes nothing again.\nexport const AdminUpdateAwardGrantsResultSchema = z\n .object({\n awardId: awardIdSchema,\n granted: z.array(userIdSchema),\n alreadyHeld: z.array(userIdSchema),\n revoked: z.array(userIdSchema),\n notHeld: z.array(userIdSchema),\n skipped: z.array(AwardGrantSkipSchema),\n })\n .strict();\nexport type AdminUpdateAwardGrantsResult = z.infer<typeof AdminUpdateAwardGrantsResultSchema>;\n\n// An admin deletes an award nobody holds. Its badge's files are retired with it.\nexport const AdminDeleteAwardDefinitionInputSchema = z.object({ awardId: awardIdSchema }).strict();\nexport type AdminDeleteAwardDefinitionInput = z.infer<typeof AdminDeleteAwardDefinitionInputSchema>;\n\n// `deleted` is false when the award was already gone: nothing was written.\nexport const AdminDeleteAwardDefinitionResultSchema = z\n .object({ awardId: awardIdSchema, deleted: z.boolean() })\n .strict();\nexport type AdminDeleteAwardDefinitionResult = z.infer<typeof AdminDeleteAwardDefinitionResultSchema>;\n\n// The signed-in account chooses which of its own awards to show beside its name: a primary and a\n// secondary badge, each an award it holds, or `null` for none. No user id is ever sent.\nexport const UpdateFeaturedAwardsInputSchema = z\n .object({ primaryAwardId: awardIdSchema.nullable(), secondaryAwardId: awardIdSchema.nullable() })\n .strict()\n .refine(\n (input) => input.primaryAwardId === null || input.primaryAwardId !== input.secondaryAwardId,\n { message: 'Choose two different awards.', path: ['secondaryAwardId'] },\n );\nexport type UpdateFeaturedAwardsInput = z.infer<typeof UpdateFeaturedAwardsInputSchema>;\n\nexport const UpdateFeaturedAwardsResultSchema = z\n .object({\n userId: userIdSchema,\n primaryAwardId: awardIdSchema.nullable(),\n secondaryAwardId: awardIdSchema.nullable(),\n changed: z.boolean(),\n })\n .strict();\nexport type UpdateFeaturedAwardsResult = z.infer<typeof UpdateFeaturedAwardsResultSchema>;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"hardware-loan-contracts.js","sourceRoot":"","sources":["../../src/schemas/hardware-loan-contracts.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,mGAAmG;AACnG,oEAAoE;AAEpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;AAE7E,sFAAsF;AACtF,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC;KACxD,MAAM,CAAC;IACN,aAAa,EAAE,YAAY;IAC3B,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC;CAC1F,CAAC;KACD,MAAM,EAAE;KACR,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,eAAe,CAAC,MAAM,EAAE;IACvF,OAAO,EAAE,sBAAsB;IAC/B,IAAI,EAAE,CAAC,iBAAiB,CAAC;CAC1B,CAAC,CAAC;AAGL,MAAM,CAAC,MAAM,2CAA2C,GAAG,CAAC;KACzD,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,CAAC;KACpD,MAAM,EAAE,CAAC;AAGZ,qGAAqG;AACrG,uCAAuC;AACvC,MAAM,CAAC,MAAM,8CAA8C,GAAG,CAAC;KAC5D,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;KAC1F,MAAM,EAAE,CAAC;AAGZ,uGAAuG;AACvG,MAAM,CAAC,MAAM,+CAA+C,GAAG,CAAC;KAC7D,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;KACzG,MAAM,EAAE,CAAC;AAGZ,8EAA8E;AAC9E,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC;KACxD,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,CAAC;KACpD,MAAM,EAAE,CAAC;AAGZ,kFAAkF;AAClF,MAAM,CAAC,MAAM,2CAA2C,GAAG,CAAC;KACzD,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;KACrG,MAAM,EAAE,CAAC;AAGZ,qGAAqG;AACrG,iBAAiB;AACjB,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC;KACxD,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,CAAC;KACpD,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,2CAA2C,GAAG,CAAC;KACzD,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;KAC1E,MAAM,EAAE,CAAC;AAGZ,oGAAoG;AACpG,2DAA2D;AAC3D,MAAM,CAAC,MAAM,+CAA+C,GAAG,CAAC;KAC7D,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,CAAC;KACpD,MAAM,EAAE,CAAC","sourcesContent":["// Callable contracts for hardware loan contracts: an admin creates a loan for a referee, the referee\r\n// signs the agreement, an admin records the equipment returned or deletes a contract never signed,\r\n// and the signature is read back through a callable — never by URL.\r\n\r\nimport { z } from 'zod';\r\nimport { HARDWARE_CATALOG, HARDWARE_CATALOG_ITEM_IDS } from '../constants/business.js';\r\nimport { epochMsSchema, hardwareLoanContractIdSchema } from '../doc-schemas/atoms.js';\r\nimport { userIdSchema } from './atoms.js';\r\nimport { stagingUploadPathSchema } from './uploads.js';\r\n\r\nexport const hardwareCatalogItemIdSchema = z.enum(HARDWARE_CATALOG_ITEM_IDS);\r\n\r\n// The referee must be on the referee roster; each item is a catalog item, named once.\r\nexport const AdminCreateHardwareLoanContractInputSchema = z\r\n .object({\r\n refereeUserId: userIdSchema,\r\n hardwareItemIds: z.array(hardwareCatalogItemIdSchema).min(1).max(HARDWARE_CATALOG.length),\r\n })\r\n .strict()\r\n .refine((input) => new Set(input.hardwareItemIds).size === input.hardwareItemIds.length, {\r\n message: 'Name each item once.',\r\n path: ['hardwareItemIds'],\r\n });\r\nexport type AdminCreateHardwareLoanContractInput = z.infer<typeof AdminCreateHardwareLoanContractInputSchema>;\r\n\r\nexport const AdminCreateHardwareLoanContractResultSchema = z\r\n .object({ contractId: hardwareLoanContractIdSchema })\r\n .strict();\r\nexport type AdminCreateHardwareLoanContractResult = z.infer<typeof AdminCreateHardwareLoanContractResultSchema>;\r\n\r\n// The contract's referee signs it: the drawn PNG staged at their own staging path. The signer is the\r\n// caller — never named in the payload.\r\nexport const SubmitHardwareLoanContractSignatureInputSchema = z\r\n .object({ contractId: hardwareLoanContractIdSchema, storagePath: stagingUploadPathSchema })\r\n .strict();\r\nexport type SubmitHardwareLoanContractSignatureInput = z.infer<typeof SubmitHardwareLoanContractSignatureInputSchema>;\r\n\r\n// `alreadySigned` when this very signing was recorded before: a retry, answered without copying again.\r\nexport const SubmitHardwareLoanContractSignatureResultSchema = z\r\n .object({ contractId: hardwareLoanContractIdSchema, loanedAt: epochMsSchema, alreadySigned: z.boolean() })\r\n .strict();\r\nexport type SubmitHardwareLoanContractSignatureResult = z.infer<typeof SubmitHardwareLoanContractSignatureResultSchema>;\r\n\r\n// An admin records a loaned contract's equipment back. The signature is kept.\r\nexport const AdminReturnHardwareLoanContractInputSchema = z\r\n .object({ contractId: hardwareLoanContractIdSchema })\r\n .strict();\r\nexport type AdminReturnHardwareLoanContractInput = z.infer<typeof AdminReturnHardwareLoanContractInputSchema>;\r\n\r\n// `changed` is false when the contract was already returned: nothing was written.\r\nexport const AdminReturnHardwareLoanContractResultSchema = z\r\n .object({ contractId: hardwareLoanContractIdSchema, returnedAt: epochMsSchema, changed: z.boolean() })\r\n .strict();\r\nexport type AdminReturnHardwareLoanContractResult = z.infer<typeof AdminReturnHardwareLoanContractResultSchema>;\r\n\r\n// An admin deletes a contract the referee has not signed. A signed contract is a legal record and is\r\n// never deleted.\r\nexport const AdminDeleteHardwareLoanContractInputSchema = z\r\n .object({ contractId: hardwareLoanContractIdSchema })\r\n .strict();\r\nexport type AdminDeleteHardwareLoanContractInput = z.infer<typeof AdminDeleteHardwareLoanContractInputSchema>;\r\n\r\nexport const AdminDeleteHardwareLoanContractResultSchema = z\r\n .object({ contractId: hardwareLoanContractIdSchema, deleted: z.boolean() })\r\n .strict();\r\nexport type AdminDeleteHardwareLoanContractResult = z.infer<typeof AdminDeleteHardwareLoanContractResultSchema>;\r\n\r\n// A contract's signature, read by its referee (the member entry) or an admin (the admin entry). The\r\n// answer is `SignatureFileResultSchema`, as a waiver's is.\r\nexport const GetHardwareLoanContractSignatureFileInputSchema = z\r\n .object({ contractId: hardwareLoanContractIdSchema })\r\n .strict();\r\nexport type GetHardwareLoanContractSignatureFileInput = z.infer<typeof GetHardwareLoanContractSignatureFileInputSchema>;\r\n"]}
1
+ {"version":3,"file":"hardware-loan-contracts.js","sourceRoot":"","sources":["../../src/schemas/hardware-loan-contracts.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,mGAAmG;AACnG,oEAAoE;AAEpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;AAE7E,sFAAsF;AACtF,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC;KACxD,MAAM,CAAC;IACN,aAAa,EAAE,YAAY;IAC3B,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC;CAC1F,CAAC;KACD,MAAM,EAAE;KACR,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,eAAe,CAAC,MAAM,EAAE;IACvF,OAAO,EAAE,sBAAsB;IAC/B,IAAI,EAAE,CAAC,iBAAiB,CAAC;CAC1B,CAAC,CAAC;AAGL,MAAM,CAAC,MAAM,2CAA2C,GAAG,CAAC;KACzD,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,CAAC;KACpD,MAAM,EAAE,CAAC;AAGZ,qGAAqG;AACrG,uCAAuC;AACvC,MAAM,CAAC,MAAM,8CAA8C,GAAG,CAAC;KAC5D,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;KAC1F,MAAM,EAAE,CAAC;AAGZ,uGAAuG;AACvG,MAAM,CAAC,MAAM,+CAA+C,GAAG,CAAC;KAC7D,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;KACzG,MAAM,EAAE,CAAC;AAGZ,8EAA8E;AAC9E,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC;KACxD,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,CAAC;KACpD,MAAM,EAAE,CAAC;AAGZ,kFAAkF;AAClF,MAAM,CAAC,MAAM,2CAA2C,GAAG,CAAC;KACzD,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;KACrG,MAAM,EAAE,CAAC;AAGZ,qGAAqG;AACrG,iBAAiB;AACjB,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC;KACxD,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,CAAC;KACpD,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,2CAA2C,GAAG,CAAC;KACzD,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;KAC1E,MAAM,EAAE,CAAC;AAGZ,oGAAoG;AACpG,2DAA2D;AAC3D,MAAM,CAAC,MAAM,+CAA+C,GAAG,CAAC;KAC7D,MAAM,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,CAAC;KACpD,MAAM,EAAE,CAAC","sourcesContent":["// Callable contracts for hardware loan contracts: an admin creates a loan for a referee, the referee\n// signs the agreement, an admin records the equipment returned or deletes a contract never signed,\n// and the signature is read back through a callable — never by URL.\n\nimport { z } from 'zod';\nimport { HARDWARE_CATALOG, HARDWARE_CATALOG_ITEM_IDS } from '../constants/business.js';\nimport { epochMsSchema, hardwareLoanContractIdSchema } from '../doc-schemas/atoms.js';\nimport { userIdSchema } from './atoms.js';\nimport { stagingUploadPathSchema } from './uploads.js';\n\nexport const hardwareCatalogItemIdSchema = z.enum(HARDWARE_CATALOG_ITEM_IDS);\n\n// The referee must be on the referee roster; each item is a catalog item, named once.\nexport const AdminCreateHardwareLoanContractInputSchema = z\n .object({\n refereeUserId: userIdSchema,\n hardwareItemIds: z.array(hardwareCatalogItemIdSchema).min(1).max(HARDWARE_CATALOG.length),\n })\n .strict()\n .refine((input) => new Set(input.hardwareItemIds).size === input.hardwareItemIds.length, {\n message: 'Name each item once.',\n path: ['hardwareItemIds'],\n });\nexport type AdminCreateHardwareLoanContractInput = z.infer<typeof AdminCreateHardwareLoanContractInputSchema>;\n\nexport const AdminCreateHardwareLoanContractResultSchema = z\n .object({ contractId: hardwareLoanContractIdSchema })\n .strict();\nexport type AdminCreateHardwareLoanContractResult = z.infer<typeof AdminCreateHardwareLoanContractResultSchema>;\n\n// The contract's referee signs it: the drawn PNG staged at their own staging path. The signer is the\n// caller — never named in the payload.\nexport const SubmitHardwareLoanContractSignatureInputSchema = z\n .object({ contractId: hardwareLoanContractIdSchema, storagePath: stagingUploadPathSchema })\n .strict();\nexport type SubmitHardwareLoanContractSignatureInput = z.infer<typeof SubmitHardwareLoanContractSignatureInputSchema>;\n\n// `alreadySigned` when this very signing was recorded before: a retry, answered without copying again.\nexport const SubmitHardwareLoanContractSignatureResultSchema = z\n .object({ contractId: hardwareLoanContractIdSchema, loanedAt: epochMsSchema, alreadySigned: z.boolean() })\n .strict();\nexport type SubmitHardwareLoanContractSignatureResult = z.infer<typeof SubmitHardwareLoanContractSignatureResultSchema>;\n\n// An admin records a loaned contract's equipment back. The signature is kept.\nexport const AdminReturnHardwareLoanContractInputSchema = z\n .object({ contractId: hardwareLoanContractIdSchema })\n .strict();\nexport type AdminReturnHardwareLoanContractInput = z.infer<typeof AdminReturnHardwareLoanContractInputSchema>;\n\n// `changed` is false when the contract was already returned: nothing was written.\nexport const AdminReturnHardwareLoanContractResultSchema = z\n .object({ contractId: hardwareLoanContractIdSchema, returnedAt: epochMsSchema, changed: z.boolean() })\n .strict();\nexport type AdminReturnHardwareLoanContractResult = z.infer<typeof AdminReturnHardwareLoanContractResultSchema>;\n\n// An admin deletes a contract the referee has not signed. A signed contract is a legal record and is\n// never deleted.\nexport const AdminDeleteHardwareLoanContractInputSchema = z\n .object({ contractId: hardwareLoanContractIdSchema })\n .strict();\nexport type AdminDeleteHardwareLoanContractInput = z.infer<typeof AdminDeleteHardwareLoanContractInputSchema>;\n\nexport const AdminDeleteHardwareLoanContractResultSchema = z\n .object({ contractId: hardwareLoanContractIdSchema, deleted: z.boolean() })\n .strict();\nexport type AdminDeleteHardwareLoanContractResult = z.infer<typeof AdminDeleteHardwareLoanContractResultSchema>;\n\n// A contract's signature, read by its referee (the member entry) or an admin (the admin entry). The\n// answer is `SignatureFileResultSchema`, as a waiver's is.\nexport const GetHardwareLoanContractSignatureFileInputSchema = z\n .object({ contractId: hardwareLoanContractIdSchema })\n .strict();\nexport type GetHardwareLoanContractSignatureFileInput = z.infer<typeof GetHardwareLoanContractSignatureFileInputSchema>;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"schedules.js","sourceRoot":"","sources":["../../src/schemas/schedules.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for a league's schedule: a week created with its games, a week's shared fields\r\n// edited, a week deleted with its games; one game added to a week, edited — moved, rescheduled, or\r\n// its teams replaced — or deleted. Every one is admin authority, and the acting admin is\r\n// `request.auth.uid`, never an input field (ARCH-106). Venue labels, calendar days, the sport, and\r\n// every stat field are derived by the server, never sent.\r\n\r\nimport { z } from 'zod';\r\nimport { MAX_SCHEDULE_WEEK_GAMES } from '../constants/business.js';\r\nimport { textFieldSchema } from '../doc-schemas/atoms.js';\r\nimport { SCHEDULE_WEEK_TITLE_INPUT_FORMAT } from '../input-formats/index.js';\r\nimport {\r\n countSchema,\r\n epochMsSchema,\r\n gameIdSchema,\r\n leagueIdSchema,\r\n scheduleWeekIdSchema,\r\n statsOperationIdSchema,\r\n teamIdSchema,\r\n} from '../doc-schemas/atoms.js';\r\nimport { gameLocationIdSchema } from '../doc-schemas/game-location.js';\r\nimport { isByeTeamId } from '../ids/minted-ids.js';\r\nimport { SCHEDULE_WEEK_FIELD_KEYS, SPORT_GAME_SCHEDULE_FIELD_KEYS } from '../types/schedules.js';\r\nimport { gameLocationSubLocationSchema } from './game-locations.js';\r\n\r\nexport const scheduleWeekTitleSchema = textFieldSchema(SCHEDULE_WEEK_TITLE_INPUT_FORMAT);\r\n\r\n// A game's two team slots, by position: team one, then team two. A slot names a team of the league\r\n// or BYE_TEAM_ID; a game has at least one real team, and never one team twice.\r\nexport const scheduleGameTeamsSchema = z\r\n .tuple([teamIdSchema, teamIdSchema])\r\n .refine(([first, second]) => !(isByeTeamId(first) && isByeTeamId(second)), 'A game needs at least one team.')\r\n .refine(([first, second]) => first !== second, 'A game needs two different teams.');\r\nexport type ScheduleGameTeams = z.infer<typeof scheduleGameTeamsSchema>;\r\n\r\n// Where and when one game is played. The venue is named by id, and the server writes the label the\r\n// schedule shows from the venue's own name and the chosen court.\r\nconst scheduleGameShape = {\r\n teams: scheduleGameTeamsSchema,\r\n startTime: epochMsSchema,\r\n gameLocationId: gameLocationIdSchema,\r\n subLocation: gameLocationSubLocationSchema.optional(),\r\n};\r\n\r\nexport const ScheduleGameInputSchema = z.object(scheduleGameShape).strict();\r\nexport type ScheduleGameInput = z.infer<typeof ScheduleGameInputSchema>;\r\n\r\nexport const sportGameScheduleFieldSchema = z.enum(SPORT_GAME_SCHEDULE_FIELD_KEYS);\r\nexport const scheduleWeekFieldSchema = z.enum(SCHEDULE_WEEK_FIELD_KEYS);\r\n\r\n// A new week and its games, saved together. `weekStartDate` is the week's first day as the admin's\r\n// form reads it; the week's venue is the default each game's form starts from, and its name is the\r\n// week's `weekLocation`.\r\nexport const AdminCreateScheduleWeekInputSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n weekTitle: scheduleWeekTitleSchema,\r\n weekStartDate: epochMsSchema,\r\n weekGameLocationId: gameLocationIdSchema,\r\n games: z.array(ScheduleGameInputSchema).min(1).max(MAX_SCHEDULE_WEEK_GAMES),\r\n })\r\n .strict();\r\nexport type AdminCreateScheduleWeekInput = z.infer<typeof AdminCreateScheduleWeekInputSchema>;\r\nexport const AdminCreateScheduleWeekResultSchema = z\r\n .object({ leagueId: leagueIdSchema, weekId: scheduleWeekIdSchema, gameIds: z.array(gameIdSchema) })\r\n .strict();\r\nexport type AdminCreateScheduleWeekResult = z.infer<typeof AdminCreateScheduleWeekResultSchema>;\r\n\r\n// Only the week's shared fields the admin changed: a field left out keeps what each game holds, so\r\n// two admins editing different fields of one week never write each other's loaded values back\r\n// (BACKEND-116). The venue is named by id, and the week shows its name.\r\nexport const AdminUpdateScheduleWeekInputSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n weekId: scheduleWeekIdSchema,\r\n weekTitle: scheduleWeekTitleSchema.optional(),\r\n weekStartDate: epochMsSchema.optional(),\r\n weekGameLocationId: gameLocationIdSchema.optional(),\r\n })\r\n .strict()\r\n .refine(\r\n (input) => input.weekTitle !== undefined || input.weekStartDate !== undefined || input.weekGameLocationId !== undefined,\r\n 'Name at least one field to change.',\r\n );\r\nexport type AdminUpdateScheduleWeekInput = z.infer<typeof AdminUpdateScheduleWeekInputSchema>;\r\nexport const AdminUpdateScheduleWeekResultSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n weekId: scheduleWeekIdSchema,\r\n changedFields: z.array(scheduleWeekFieldSchema),\r\n gamesUpdated: countSchema,\r\n })\r\n .strict();\r\nexport type AdminUpdateScheduleWeekResult = z.infer<typeof AdminUpdateScheduleWeekResultSchema>;\r\n\r\n// A whole week and every game in it. A game with events takes more than one step to delete, so a\r\n// call that runs out of time answers `complete: false` with the games still standing, and running\r\n// it again continues. A week with no game left answers complete.\r\nexport const AdminDeleteScheduleWeekInputSchema = z\r\n .object({ leagueId: leagueIdSchema, weekId: scheduleWeekIdSchema })\r\n .strict();\r\nexport type AdminDeleteScheduleWeekInput = z.infer<typeof AdminDeleteScheduleWeekInputSchema>;\r\nexport const AdminDeleteScheduleWeekResultSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n weekId: scheduleWeekIdSchema,\r\n deletedGameIds: z.array(gameIdSchema),\r\n remainingGameIds: z.array(gameIdSchema),\r\n complete: z.boolean(),\r\n })\r\n .strict();\r\nexport type AdminDeleteScheduleWeekResult = z.infer<typeof AdminDeleteScheduleWeekResultSchema>;\r\n\r\n// One game added to a saved week, which gives it the week's shared fields.\r\nexport const AdminCreateSportGameInputSchema = z\r\n .object({ leagueId: leagueIdSchema, weekId: scheduleWeekIdSchema, ...scheduleGameShape })\r\n .strict();\r\nexport type AdminCreateSportGameInput = z.infer<typeof AdminCreateSportGameInputSchema>;\r\nexport const AdminCreateSportGameResultSchema = z\r\n .object({ leagueId: leagueIdSchema, weekId: scheduleWeekIdSchema, gameId: gameIdSchema })\r\n .strict();\r\nexport type AdminCreateSportGameResult = z.infer<typeof AdminCreateSportGameResultSchema>;\r\n\r\n// One game's schedule, whole: its week (a reschedule into another saved week), its teams, its start\r\n// time, and its venue. `expectedUpdatedAt` is the game's `updatedAt` as the admin loaded it, so a\r\n// stale form never writes its old values over a newer change. A game that names no venue may keep\r\n// its stored label by naming none; a court is named only with its venue.\r\nexport const AdminUpdateSportGameInputSchema = z\r\n .object({\r\n gameId: gameIdSchema,\r\n expectedUpdatedAt: epochMsSchema,\r\n weekId: scheduleWeekIdSchema,\r\n teams: scheduleGameTeamsSchema,\r\n startTime: epochMsSchema,\r\n gameLocationId: gameLocationIdSchema.optional(),\r\n subLocation: gameLocationSubLocationSchema.optional(),\r\n })\r\n .strict()\r\n .refine((input) => input.subLocation === undefined || input.gameLocationId !== undefined, {\r\n message: 'A court is chosen within a venue.',\r\n path: ['subLocation'],\r\n });\r\nexport type AdminUpdateSportGameInput = z.infer<typeof AdminUpdateSportGameInputSchema>;\r\nexport const AdminUpdateSportGameResultSchema = z\r\n .object({\r\n gameId: gameIdSchema,\r\n changedFields: z.array(sportGameScheduleFieldSchema),\r\n updatedAt: epochMsSchema,\r\n })\r\n .strict();\r\nexport type AdminUpdateSportGameResult = z.infer<typeof AdminUpdateSportGameResultSchema>;\r\n\r\n// One game, with its events and roster. The server derives the deletion's operation id from the\r\n// game (`buildGameDeletionOperationId`), so a retry of a finished delete is acknowledged and a retry\r\n// of an interrupted one continues it; the caller names only the game.\r\nexport const AdminDeleteSportGameInputSchema = z.object({ gameId: gameIdSchema }).strict();\r\nexport type AdminDeleteSportGameInput = z.infer<typeof AdminDeleteSportGameInputSchema>;\r\nexport const AdminDeleteSportGameResultSchema = z\r\n .object({ gameId: gameIdSchema, operationId: statsOperationIdSchema, complete: z.boolean() })\r\n .strict();\r\nexport type AdminDeleteSportGameResult = z.infer<typeof AdminDeleteSportGameResultSchema>;\r\n"]}
1
+ {"version":3,"file":"schedules.js","sourceRoot":"","sources":["../../src/schemas/schedules.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for a league's schedule: a week created with its games, a week's shared fields\n// edited, a week deleted with its games; one game added to a week, edited — moved, rescheduled, or\n// its teams replaced — or deleted. Every one is admin authority, and the acting admin is\n// `request.auth.uid`, never an input field (ARCH-106). Venue labels, calendar days, the sport, and\n// every stat field are derived by the server, never sent.\n\nimport { z } from 'zod';\nimport { MAX_SCHEDULE_WEEK_GAMES } from '../constants/business.js';\nimport { textFieldSchema } from '../doc-schemas/atoms.js';\nimport { SCHEDULE_WEEK_TITLE_INPUT_FORMAT } from '../input-formats/index.js';\nimport {\n countSchema,\n epochMsSchema,\n gameIdSchema,\n leagueIdSchema,\n scheduleWeekIdSchema,\n statsOperationIdSchema,\n teamIdSchema,\n} from '../doc-schemas/atoms.js';\nimport { gameLocationIdSchema } from '../doc-schemas/game-location.js';\nimport { isByeTeamId } from '../ids/minted-ids.js';\nimport { SCHEDULE_WEEK_FIELD_KEYS, SPORT_GAME_SCHEDULE_FIELD_KEYS } from '../types/schedules.js';\nimport { gameLocationSubLocationSchema } from './game-locations.js';\n\nexport const scheduleWeekTitleSchema = textFieldSchema(SCHEDULE_WEEK_TITLE_INPUT_FORMAT);\n\n// A game's two team slots, by position: team one, then team two. A slot names a team of the league\n// or BYE_TEAM_ID; a game has at least one real team, and never one team twice.\nexport const scheduleGameTeamsSchema = z\n .tuple([teamIdSchema, teamIdSchema])\n .refine(([first, second]) => !(isByeTeamId(first) && isByeTeamId(second)), 'A game needs at least one team.')\n .refine(([first, second]) => first !== second, 'A game needs two different teams.');\nexport type ScheduleGameTeams = z.infer<typeof scheduleGameTeamsSchema>;\n\n// Where and when one game is played. The venue is named by id, and the server writes the label the\n// schedule shows from the venue's own name and the chosen court.\nconst scheduleGameShape = {\n teams: scheduleGameTeamsSchema,\n startTime: epochMsSchema,\n gameLocationId: gameLocationIdSchema,\n subLocation: gameLocationSubLocationSchema.optional(),\n};\n\nexport const ScheduleGameInputSchema = z.object(scheduleGameShape).strict();\nexport type ScheduleGameInput = z.infer<typeof ScheduleGameInputSchema>;\n\nexport const sportGameScheduleFieldSchema = z.enum(SPORT_GAME_SCHEDULE_FIELD_KEYS);\nexport const scheduleWeekFieldSchema = z.enum(SCHEDULE_WEEK_FIELD_KEYS);\n\n// A new week and its games, saved together. `weekStartDate` is the week's first day as the admin's\n// form reads it; the week's venue is the default each game's form starts from, and its name is the\n// week's `weekLocation`.\nexport const AdminCreateScheduleWeekInputSchema = z\n .object({\n leagueId: leagueIdSchema,\n weekTitle: scheduleWeekTitleSchema,\n weekStartDate: epochMsSchema,\n weekGameLocationId: gameLocationIdSchema,\n games: z.array(ScheduleGameInputSchema).min(1).max(MAX_SCHEDULE_WEEK_GAMES),\n })\n .strict();\nexport type AdminCreateScheduleWeekInput = z.infer<typeof AdminCreateScheduleWeekInputSchema>;\nexport const AdminCreateScheduleWeekResultSchema = z\n .object({ leagueId: leagueIdSchema, weekId: scheduleWeekIdSchema, gameIds: z.array(gameIdSchema) })\n .strict();\nexport type AdminCreateScheduleWeekResult = z.infer<typeof AdminCreateScheduleWeekResultSchema>;\n\n// Only the week's shared fields the admin changed: a field left out keeps what each game holds, so\n// two admins editing different fields of one week never write each other's loaded values back\n// (BACKEND-116). The venue is named by id, and the week shows its name.\nexport const AdminUpdateScheduleWeekInputSchema = z\n .object({\n leagueId: leagueIdSchema,\n weekId: scheduleWeekIdSchema,\n weekTitle: scheduleWeekTitleSchema.optional(),\n weekStartDate: epochMsSchema.optional(),\n weekGameLocationId: gameLocationIdSchema.optional(),\n })\n .strict()\n .refine(\n (input) => input.weekTitle !== undefined || input.weekStartDate !== undefined || input.weekGameLocationId !== undefined,\n 'Name at least one field to change.',\n );\nexport type AdminUpdateScheduleWeekInput = z.infer<typeof AdminUpdateScheduleWeekInputSchema>;\nexport const AdminUpdateScheduleWeekResultSchema = z\n .object({\n leagueId: leagueIdSchema,\n weekId: scheduleWeekIdSchema,\n changedFields: z.array(scheduleWeekFieldSchema),\n gamesUpdated: countSchema,\n })\n .strict();\nexport type AdminUpdateScheduleWeekResult = z.infer<typeof AdminUpdateScheduleWeekResultSchema>;\n\n// A whole week and every game in it. A game with events takes more than one step to delete, so a\n// call that runs out of time answers `complete: false` with the games still standing, and running\n// it again continues. A week with no game left answers complete.\nexport const AdminDeleteScheduleWeekInputSchema = z\n .object({ leagueId: leagueIdSchema, weekId: scheduleWeekIdSchema })\n .strict();\nexport type AdminDeleteScheduleWeekInput = z.infer<typeof AdminDeleteScheduleWeekInputSchema>;\nexport const AdminDeleteScheduleWeekResultSchema = z\n .object({\n leagueId: leagueIdSchema,\n weekId: scheduleWeekIdSchema,\n deletedGameIds: z.array(gameIdSchema),\n remainingGameIds: z.array(gameIdSchema),\n complete: z.boolean(),\n })\n .strict();\nexport type AdminDeleteScheduleWeekResult = z.infer<typeof AdminDeleteScheduleWeekResultSchema>;\n\n// One game added to a saved week, which gives it the week's shared fields.\nexport const AdminCreateSportGameInputSchema = z\n .object({ leagueId: leagueIdSchema, weekId: scheduleWeekIdSchema, ...scheduleGameShape })\n .strict();\nexport type AdminCreateSportGameInput = z.infer<typeof AdminCreateSportGameInputSchema>;\nexport const AdminCreateSportGameResultSchema = z\n .object({ leagueId: leagueIdSchema, weekId: scheduleWeekIdSchema, gameId: gameIdSchema })\n .strict();\nexport type AdminCreateSportGameResult = z.infer<typeof AdminCreateSportGameResultSchema>;\n\n// One game's schedule, whole: its week (a reschedule into another saved week), its teams, its start\n// time, and its venue. `expectedUpdatedAt` is the game's `updatedAt` as the admin loaded it, so a\n// stale form never writes its old values over a newer change. A game that names no venue may keep\n// its stored label by naming none; a court is named only with its venue.\nexport const AdminUpdateSportGameInputSchema = z\n .object({\n gameId: gameIdSchema,\n expectedUpdatedAt: epochMsSchema,\n weekId: scheduleWeekIdSchema,\n teams: scheduleGameTeamsSchema,\n startTime: epochMsSchema,\n gameLocationId: gameLocationIdSchema.optional(),\n subLocation: gameLocationSubLocationSchema.optional(),\n })\n .strict()\n .refine((input) => input.subLocation === undefined || input.gameLocationId !== undefined, {\n message: 'A court is chosen within a venue.',\n path: ['subLocation'],\n });\nexport type AdminUpdateSportGameInput = z.infer<typeof AdminUpdateSportGameInputSchema>;\nexport const AdminUpdateSportGameResultSchema = z\n .object({\n gameId: gameIdSchema,\n changedFields: z.array(sportGameScheduleFieldSchema),\n updatedAt: epochMsSchema,\n })\n .strict();\nexport type AdminUpdateSportGameResult = z.infer<typeof AdminUpdateSportGameResultSchema>;\n\n// One game, with its events and roster. The server derives the deletion's operation id from the\n// game (`buildGameDeletionOperationId`), so a retry of a finished delete is acknowledged and a retry\n// of an interrupted one continues it; the caller names only the game.\nexport const AdminDeleteSportGameInputSchema = z.object({ gameId: gameIdSchema }).strict();\nexport type AdminDeleteSportGameInput = z.infer<typeof AdminDeleteSportGameInputSchema>;\nexport const AdminDeleteSportGameResultSchema = z\n .object({ gameId: gameIdSchema, operationId: statsOperationIdSchema, complete: z.boolean() })\n .strict();\nexport type AdminDeleteSportGameResult = z.infer<typeof AdminDeleteSportGameResultSchema>;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"scoring.js","sourceRoot":"","sources":["../../src/schemas/scoring.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for live scoring: recording stat events, marking a roster entry absent, a\r\n// scorer's memo, and the jump-ball possession arrow. Each action is two entries over one core — the\r\n// member entry for a captain or co-captain of one of the game's two teams, and the admin entry for\r\n// an admin or referee — which share one input and one result.\r\n\r\nimport { z } from 'zod';\r\nimport { MAX_STAT_EVENTS_PER_WRITE } from '../constants/sports.js';\r\nimport { isSportStatEventId } from '../ids/stat-event-ids.js';\r\nimport { GAME_MEMO_INPUT_FORMAT } from '../input-formats/index.js';\r\nimport {\r\n BasketballAssistableShotEventSchema,\r\n BasketballBulkEditEventSchema,\r\n BasketballOnePointEventSchema,\r\n BasketballPlayerTallyEventSchema,\r\n BasketballTimeoutEventSchema,\r\n CurlingBlankEndEventSchema,\r\n CurlingRoundScoreEventSchema,\r\n FootballBulkEditEventSchema,\r\n FootballScoreEventSchema,\r\n StatCorrectionEventSchema,\r\n StatVoidEventSchema,\r\n} from '../doc-schemas/game-stats.js';\r\nimport {\r\n RECORDED_STAT_EVENT_OUTCOME_KEYS,\r\n STAT_EVENT_RECORDER_FIELD_KEYS,\r\n STAT_EVENT_REFUSAL_KEYS,\r\n STAT_EVENT_SNAPSHOT_FIELD_KEYS,\r\n} from '../types/stats.js';\r\nimport type { StatEventRecorderField, StatEventSnapshotField } from '../types/stats.js';\r\nimport {\r\n countSchema,\r\n gameIdSchema,\r\n gameRosterPlayerIdSchema,\r\n statEventIdSchema,\r\n teamIdSchema,\r\n textFieldSchema,\r\n userIdSchema,\r\n} from './atoms.js';\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Recording stat events\r\n// ---------------------------------------------------------------------------------------------\r\n\r\ntype ServerDerivedField = StatEventRecorderField | StatEventSnapshotField;\r\nconst SERVER_DERIVED_FIELDS: ReadonlySet<string> = new Set([\r\n ...STAT_EVENT_RECORDER_FIELD_KEYS,\r\n ...STAT_EVENT_SNAPSHOT_FIELD_KEYS,\r\n]);\r\n\r\n/**\r\n * A stored event's fields as its caller sends them: without the sequence and recorder facts the\r\n * writing core derives (ARCH-106), and without a name snapshot, which only a copied event carries.\r\n * Built from the stored event's own declaration, so the wire and the document cannot drift.\r\n */\r\nfunction callerShape<Shape extends z.ZodRawShape, Omitted extends keyof Shape = never>(\r\n shape: Shape,\r\n omitted: readonly Omitted[] = [],\r\n): Omit<Shape, ServerDerivedField | Omitted> {\r\n const dropped = new Set<PropertyKey>([...SERVER_DERIVED_FIELDS, ...omitted]);\r\n return Object.fromEntries(Object.entries(shape).filter(([field]) => !dropped.has(field))) as Omit<\r\n Shape,\r\n ServerDerivedField | Omitted\r\n >;\r\n}\r\n\r\n// A sport event's id as its caller sends it — the id minted at the tap, or, as a void's target, one a\r\n// copied event kept. It becomes a document path, so it is held to the shape a sport event id has.\r\nexport const sportStatEventIdSchema = statEventIdSchema.refine(isSportStatEventId, 'Not a stat event id.');\r\n\r\nconst sportEventId = { eventId: sportStatEventIdSchema };\r\n\r\n/**\r\n * One event of a scoring write, as the tap minted it: a sport event with its id and `recordedAt`, or\r\n * a void naming its target, whose own id the core derives. A bulk edit carries `previousValue`, the\r\n * value the form showed, so a stale form is refused. A correction parses so the core can answer it\r\n * with its refusal: only the game-reconcile core appends one.\r\n */\r\nexport const StatEventSubmissionSchema = z.discriminatedUnion('type', [\r\n z.strictObject({ ...callerShape(BasketballOnePointEventSchema.shape), ...sportEventId }),\r\n z.strictObject({ ...callerShape(BasketballAssistableShotEventSchema.shape), ...sportEventId }),\r\n z.strictObject({ ...callerShape(BasketballPlayerTallyEventSchema.shape), ...sportEventId }),\r\n z.strictObject({ ...callerShape(BasketballTimeoutEventSchema.shape), ...sportEventId }),\r\n z.strictObject({ ...callerShape(BasketballBulkEditEventSchema.shape), ...sportEventId, previousValue: countSchema }),\r\n z.strictObject({ ...callerShape(CurlingRoundScoreEventSchema.shape), ...sportEventId }),\r\n z.strictObject({ ...callerShape(CurlingBlankEndEventSchema.shape), ...sportEventId }),\r\n z.strictObject({ ...callerShape(FootballScoreEventSchema.shape), ...sportEventId }),\r\n z.strictObject({ ...callerShape(FootballBulkEditEventSchema.shape), ...sportEventId }),\r\n z.strictObject({ ...callerShape(StatVoidEventSchema.shape, ['eventId']), targetEventId: sportStatEventIdSchema }),\r\n z.strictObject(callerShape(StatCorrectionEventSchema.shape)),\r\n]);\r\nexport type StatEventSubmission = z.infer<typeof StatEventSubmissionSchema>;\r\n\r\n// A queue drain, a bulk-entry submission, or an undo: one ordered batch, applied whole or not at all.\r\nexport const RecordGameStatEventsInputSchema = z\r\n .object({\r\n gameId: gameIdSchema,\r\n events: z.array(StatEventSubmissionSchema).min(1).max(MAX_STAT_EVENTS_PER_WRITE),\r\n })\r\n .strict();\r\nexport type RecordGameStatEventsInput = z.infer<typeof RecordGameStatEventsInputSchema>;\r\n\r\n// Each event sent, in order: stored now, or found already stored by an earlier send.\r\nexport const RecordedStatEventSchema = z\r\n .object({\r\n eventId: statEventIdSchema,\r\n outcome: z.enum(RECORDED_STAT_EVENT_OUTCOME_KEYS),\r\n sequence: z.number().int().positive(),\r\n })\r\n .strict();\r\nexport type RecordedStatEvent = z.infer<typeof RecordedStatEventSchema>;\r\n\r\nexport const RecordGameStatEventsResultSchema = z\r\n .object({\r\n gameId: gameIdSchema,\r\n events: z.array(RecordedStatEventSchema),\r\n })\r\n .strict();\r\nexport type RecordGameStatEventsResult = z.infer<typeof RecordGameStatEventsResultSchema>;\r\n\r\n// What a refused scoring write names in its error details: why, and the first event it refused. No\r\n// event of the batch was stored, and the scorekeeper's failed list shows the refusal's copy beside\r\n// that event.\r\nexport const StatEventRefusalDetailsSchema = z\r\n .object({\r\n refusal: z.enum(STAT_EVENT_REFUSAL_KEYS),\r\n eventId: statEventIdSchema,\r\n })\r\n .strict();\r\nexport type StatEventRefusalDetails = z.infer<typeof StatEventRefusalDetailsSchema>;\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// Absence — per roster entry, so a person on both teams can be absent on one side only\r\n// ---------------------------------------------------------------------------------------------\r\n\r\nexport const UpdateGameAbsentPlayersInputSchema = z\r\n .object({\r\n gameId: gameIdSchema,\r\n gameRosterPlayerId: gameRosterPlayerIdSchema,\r\n absent: z.boolean(),\r\n })\r\n .strict();\r\nexport type UpdateGameAbsentPlayersInput = z.infer<typeof UpdateGameAbsentPlayersInputSchema>;\r\n\r\n// `changed` is false when the entry was already marked that way; nothing was written.\r\nexport const UpdateGameAbsentPlayersResultSchema = z\r\n .object({\r\n gameId: gameIdSchema,\r\n gameRosterPlayerId: gameRosterPlayerIdSchema,\r\n absent: z.boolean(),\r\n changed: z.boolean(),\r\n })\r\n .strict();\r\nexport type UpdateGameAbsentPlayersResult = z.infer<typeof UpdateGameAbsentPlayersResultSchema>;\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// The memo — a scorer's note on one person in a live game (\"red shirt\", \"#9\")\r\n// ---------------------------------------------------------------------------------------------\r\n\r\n// Built from the memo's one declaration, so the memo form and the callable accept exactly the same\r\n// text: trimmed, one line, empty allowed — an empty memo clears the person's note.\r\nexport const gameMemoSchema = textFieldSchema(GAME_MEMO_INPUT_FORMAT);\r\n\r\nexport const UpdateGameMemoInputSchema = z\r\n .object({\r\n gameId: gameIdSchema,\r\n userId: userIdSchema,\r\n memo: gameMemoSchema,\r\n })\r\n .strict();\r\nexport type UpdateGameMemoInput = z.infer<typeof UpdateGameMemoInputSchema>;\r\n\r\nexport const UpdateGameMemoResultSchema = z\r\n .object({\r\n gameId: gameIdSchema,\r\n userId: userIdSchema,\r\n memo: z.string(),\r\n changed: z.boolean(),\r\n })\r\n .strict();\r\nexport type UpdateGameMemoResult = z.infer<typeof UpdateGameMemoResultSchema>;\r\n\r\n// ---------------------------------------------------------------------------------------------\r\n// The jump-ball possession arrow — set to a team, so a retried call lands where the first did\r\n// ---------------------------------------------------------------------------------------------\r\n\r\nexport const UpdateGameJumpBallInputSchema = z\r\n .object({\r\n gameId: gameIdSchema,\r\n teamId: teamIdSchema,\r\n })\r\n .strict();\r\nexport type UpdateGameJumpBallInput = z.infer<typeof UpdateGameJumpBallInputSchema>;\r\n\r\nexport const UpdateGameJumpBallResultSchema = z\r\n .object({\r\n gameId: gameIdSchema,\r\n teamId: teamIdSchema,\r\n changed: z.boolean(),\r\n })\r\n .strict();\r\nexport type UpdateGameJumpBallResult = z.infer<typeof UpdateGameJumpBallResultSchema>;\r\n"]}
1
+ {"version":3,"file":"scoring.js","sourceRoot":"","sources":["../../src/schemas/scoring.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for live scoring: recording stat events, marking a roster entry absent, a\n// scorer's memo, and the jump-ball possession arrow. Each action is two entries over one core — the\n// member entry for a captain or co-captain of one of the game's two teams, and the admin entry for\n// an admin or referee — which share one input and one result.\n\nimport { z } from 'zod';\nimport { MAX_STAT_EVENTS_PER_WRITE } from '../constants/sports.js';\nimport { isSportStatEventId } from '../ids/stat-event-ids.js';\nimport { GAME_MEMO_INPUT_FORMAT } from '../input-formats/index.js';\nimport {\n BasketballAssistableShotEventSchema,\n BasketballBulkEditEventSchema,\n BasketballOnePointEventSchema,\n BasketballPlayerTallyEventSchema,\n BasketballTimeoutEventSchema,\n CurlingBlankEndEventSchema,\n CurlingRoundScoreEventSchema,\n FootballBulkEditEventSchema,\n FootballScoreEventSchema,\n StatCorrectionEventSchema,\n StatVoidEventSchema,\n} from '../doc-schemas/game-stats.js';\nimport {\n RECORDED_STAT_EVENT_OUTCOME_KEYS,\n STAT_EVENT_RECORDER_FIELD_KEYS,\n STAT_EVENT_REFUSAL_KEYS,\n STAT_EVENT_SNAPSHOT_FIELD_KEYS,\n} from '../types/stats.js';\nimport type { StatEventRecorderField, StatEventSnapshotField } from '../types/stats.js';\nimport {\n countSchema,\n gameIdSchema,\n gameRosterPlayerIdSchema,\n statEventIdSchema,\n teamIdSchema,\n textFieldSchema,\n userIdSchema,\n} from './atoms.js';\n\n// ---------------------------------------------------------------------------------------------\n// Recording stat events\n// ---------------------------------------------------------------------------------------------\n\ntype ServerDerivedField = StatEventRecorderField | StatEventSnapshotField;\nconst SERVER_DERIVED_FIELDS: ReadonlySet<string> = new Set([\n ...STAT_EVENT_RECORDER_FIELD_KEYS,\n ...STAT_EVENT_SNAPSHOT_FIELD_KEYS,\n]);\n\n/**\n * A stored event's fields as its caller sends them: without the sequence and recorder facts the\n * writing core derives (ARCH-106), and without a name snapshot, which only a copied event carries.\n * Built from the stored event's own declaration, so the wire and the document cannot drift.\n */\nfunction callerShape<Shape extends z.ZodRawShape, Omitted extends keyof Shape = never>(\n shape: Shape,\n omitted: readonly Omitted[] = [],\n): Omit<Shape, ServerDerivedField | Omitted> {\n const dropped = new Set<PropertyKey>([...SERVER_DERIVED_FIELDS, ...omitted]);\n return Object.fromEntries(Object.entries(shape).filter(([field]) => !dropped.has(field))) as Omit<\n Shape,\n ServerDerivedField | Omitted\n >;\n}\n\n// A sport event's id as its caller sends it — the id minted at the tap, or, as a void's target, one a\n// copied event kept. It becomes a document path, so it is held to the shape a sport event id has.\nexport const sportStatEventIdSchema = statEventIdSchema.refine(isSportStatEventId, 'Not a stat event id.');\n\nconst sportEventId = { eventId: sportStatEventIdSchema };\n\n/**\n * One event of a scoring write, as the tap minted it: a sport event with its id and `recordedAt`, or\n * a void naming its target, whose own id the core derives. A bulk edit carries `previousValue`, the\n * value the form showed, so a stale form is refused. A correction parses so the core can answer it\n * with its refusal: only the game-reconcile core appends one.\n */\nexport const StatEventSubmissionSchema = z.discriminatedUnion('type', [\n z.strictObject({ ...callerShape(BasketballOnePointEventSchema.shape), ...sportEventId }),\n z.strictObject({ ...callerShape(BasketballAssistableShotEventSchema.shape), ...sportEventId }),\n z.strictObject({ ...callerShape(BasketballPlayerTallyEventSchema.shape), ...sportEventId }),\n z.strictObject({ ...callerShape(BasketballTimeoutEventSchema.shape), ...sportEventId }),\n z.strictObject({ ...callerShape(BasketballBulkEditEventSchema.shape), ...sportEventId, previousValue: countSchema }),\n z.strictObject({ ...callerShape(CurlingRoundScoreEventSchema.shape), ...sportEventId }),\n z.strictObject({ ...callerShape(CurlingBlankEndEventSchema.shape), ...sportEventId }),\n z.strictObject({ ...callerShape(FootballScoreEventSchema.shape), ...sportEventId }),\n z.strictObject({ ...callerShape(FootballBulkEditEventSchema.shape), ...sportEventId }),\n z.strictObject({ ...callerShape(StatVoidEventSchema.shape, ['eventId']), targetEventId: sportStatEventIdSchema }),\n z.strictObject(callerShape(StatCorrectionEventSchema.shape)),\n]);\nexport type StatEventSubmission = z.infer<typeof StatEventSubmissionSchema>;\n\n// A queue drain, a bulk-entry submission, or an undo: one ordered batch, applied whole or not at all.\nexport const RecordGameStatEventsInputSchema = z\n .object({\n gameId: gameIdSchema,\n events: z.array(StatEventSubmissionSchema).min(1).max(MAX_STAT_EVENTS_PER_WRITE),\n })\n .strict();\nexport type RecordGameStatEventsInput = z.infer<typeof RecordGameStatEventsInputSchema>;\n\n// Each event sent, in order: stored now, or found already stored by an earlier send.\nexport const RecordedStatEventSchema = z\n .object({\n eventId: statEventIdSchema,\n outcome: z.enum(RECORDED_STAT_EVENT_OUTCOME_KEYS),\n sequence: z.number().int().positive(),\n })\n .strict();\nexport type RecordedStatEvent = z.infer<typeof RecordedStatEventSchema>;\n\nexport const RecordGameStatEventsResultSchema = z\n .object({\n gameId: gameIdSchema,\n events: z.array(RecordedStatEventSchema),\n })\n .strict();\nexport type RecordGameStatEventsResult = z.infer<typeof RecordGameStatEventsResultSchema>;\n\n// What a refused scoring write names in its error details: why, and the first event it refused. No\n// event of the batch was stored, and the scorekeeper's failed list shows the refusal's copy beside\n// that event.\nexport const StatEventRefusalDetailsSchema = z\n .object({\n refusal: z.enum(STAT_EVENT_REFUSAL_KEYS),\n eventId: statEventIdSchema,\n })\n .strict();\nexport type StatEventRefusalDetails = z.infer<typeof StatEventRefusalDetailsSchema>;\n\n// ---------------------------------------------------------------------------------------------\n// Absence — per roster entry, so a person on both teams can be absent on one side only\n// ---------------------------------------------------------------------------------------------\n\nexport const UpdateGameAbsentPlayersInputSchema = z\n .object({\n gameId: gameIdSchema,\n gameRosterPlayerId: gameRosterPlayerIdSchema,\n absent: z.boolean(),\n })\n .strict();\nexport type UpdateGameAbsentPlayersInput = z.infer<typeof UpdateGameAbsentPlayersInputSchema>;\n\n// `changed` is false when the entry was already marked that way; nothing was written.\nexport const UpdateGameAbsentPlayersResultSchema = z\n .object({\n gameId: gameIdSchema,\n gameRosterPlayerId: gameRosterPlayerIdSchema,\n absent: z.boolean(),\n changed: z.boolean(),\n })\n .strict();\nexport type UpdateGameAbsentPlayersResult = z.infer<typeof UpdateGameAbsentPlayersResultSchema>;\n\n// ---------------------------------------------------------------------------------------------\n// The memo — a scorer's note on one person in a live game (\"red shirt\", \"#9\")\n// ---------------------------------------------------------------------------------------------\n\n// Built from the memo's one declaration, so the memo form and the callable accept exactly the same\n// text: trimmed, one line, empty allowed — an empty memo clears the person's note.\nexport const gameMemoSchema = textFieldSchema(GAME_MEMO_INPUT_FORMAT);\n\nexport const UpdateGameMemoInputSchema = z\n .object({\n gameId: gameIdSchema,\n userId: userIdSchema,\n memo: gameMemoSchema,\n })\n .strict();\nexport type UpdateGameMemoInput = z.infer<typeof UpdateGameMemoInputSchema>;\n\nexport const UpdateGameMemoResultSchema = z\n .object({\n gameId: gameIdSchema,\n userId: userIdSchema,\n memo: z.string(),\n changed: z.boolean(),\n })\n .strict();\nexport type UpdateGameMemoResult = z.infer<typeof UpdateGameMemoResultSchema>;\n\n// ---------------------------------------------------------------------------------------------\n// The jump-ball possession arrow — set to a team, so a retried call lands where the first did\n// ---------------------------------------------------------------------------------------------\n\nexport const UpdateGameJumpBallInputSchema = z\n .object({\n gameId: gameIdSchema,\n teamId: teamIdSchema,\n })\n .strict();\nexport type UpdateGameJumpBallInput = z.infer<typeof UpdateGameJumpBallInputSchema>;\n\nexport const UpdateGameJumpBallResultSchema = z\n .object({\n gameId: gameIdSchema,\n teamId: teamIdSchema,\n changed: z.boolean(),\n })\n .strict();\nexport type UpdateGameJumpBallResult = z.infer<typeof UpdateGameJumpBallResultSchema>;\n"]}