New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@wral/hsot-score-report

Package Overview
Dependencies
Maintainers
7
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@wral/hsot-score-report

Lit web component for the HighSchoolOT "Report a Score" page: an anonymous form, driven by an api-forms document, that e-mails the HSOT desk through the HSOT stage of api-forms. Purely an e-mail — a person reads every report before a score is entered.

latest
Source
npmnpm
Version
0.1.4
Version published
Maintainers
7
Created
Source

@wral/hsot-score-report

Lit web component for the HighSchoolOT "Report a Score" page. An anonymous form — sport, where the game stands, both teams with scores, and optionally the game date, time, who is reporting and a note — that replaces the legacy Diesel form at /content/page/12766776/ and keeps its model.

It is purely an e-mail. The report goes to the HSOT stage of api-forms, which e-mails the HSOT desk. A person reads every report before a score is entered, because reports are sometimes wrong or fake. Nothing here writes to a game; the api-hsot calls this component makes are reads.

Self-contained on purpose: no runtime dependency on web-components.hsot-data. Those components link to this page (the box score's "Report a score for this game", the scoreboard's "report a score", via their report-href template); the page itself is mounted by templates.hsot-web.data-page at /report-a-score/.

Usage

From the CDN (self-contained, registers the element):

<script type="module"
	src="https://web-components.cdn.highschoolot.com/hsot-score-report/v0/define.standalone.js"></script>
<hsot-score-report
	api="https://api.highschoolot.com/hsot/v1/public"
	forms-api="https://api.highschoolot.com/forms"></hsot-score-report>

From npm:

import '@wral/hsot-score-report/define';   // registers hsot-score-report
// or
import { HsotScoreReport } from '@wral/hsot-score-report';

Attributes and properties

NameKindDefaultPurpose
forms-apiattributehttps://api.highschoolot.com/formsThe HSOT api-forms stage: the form document and the anonymous submit
form-idattributehsot-scoreThe form document to render and submit
apiattributehttps://api.highschoolot.com/hsot/v1/publicapi-hsot's public read surface: pre-fill from a game, school typeahead
game-idattribute—Pre-fill from the game on record; also read from ?game= in the page URL
game-href, section-hrefattributes/{sport}/game/{id}/, /{sport}/{view}/Link templates for the pre-fill banner's box score and the done view's "back to scores"
promo-image, promo-href, promo-altattributes—Sponsor banner across the top of the view (image required; unlinked without an href)
slot="rail"light-DOM children—Right rail (300px column at 1200px and up, stacked below on smaller screens)
formsClientproperty—Any object with getListing (or listForms), createAnonSession, putRequest (see src/lib/forms-client.mjs); wins over forms-api
clientproperty—Any object with getGame, getTeam, getSchool, searchSchools (see src/lib/hsot-client.mjs); wins over api

Styling: design tokens are read as var(--color-…, fallback) with the HSOT style-guide literals as fallbacks (mirroring hsot-data's styles.mjs), so the component renders correctly with no token stylesheet on the page.

How it works

The fields come from the form document. On load the component fetches the hsot-score document from the forms stage — the HSOT content stage holds only this form, so the stage's public listing is the fetch — and, when a game-id is present, the game with its teams and schools from api-hsot. The document opens with a choice of the 26 gendered sports; each option leads to a collect node holding that sport's period family (quarters, halves, innings, or final-only) — the quarters and halves nodes also carry an optional "time left in the period" text field, which the component shows only for those sports — then the shared team, score and detail fields. src/lib/score-report.mjs walks it, so the select options, the field limits, the request path and the confirmation copy all come from the seeded document (seed/form-hsot-score.json in api-forms, copied to src/demo/fixtures/), and the server validates against the same document.

The listing also says what the stage allows. GET /v1/forms carries anonymous: { enabled, humanCheck } (api-forms DEV-1270). When enabled is false the page says score reporting is unavailable at load rather than at submit; when humanCheck names a proof-of-human provider, the page says the same, because this component renders no captcha widget — adding one is the next step if a stage ever turns a provider on. A stage from before the block sends nothing, which reads as enabled.

Client-side validation mirrors the server: required fields, whole-number scores from 0 to 999, lengths from the document, a real calendar date, a 24-hour time. The team inputs are free text with a typeahead against api-hsot's school search; picking a school also records its id (homeSchoolId / awaySchoolId), and typing over it drops the id.

Submit is api-forms' anonymous flow (DEV-1270):

  • Mint a uuid requestId once per report and keep it across retries.
  • POST /v1/anon/sessions with { formId, requestId } → a session token, cached until shortly before it expires.
  • PUT /v1/requests/{requestId} with the token and keyed string answers for the walked path (text/select/textarea kinds only — api-forms has no numeric field, so scores travel as strings). The response carries the RI-… reference and the confirmation copy the done view shows.

The HSOT stage keeps no record. Its ANON_SAVE_CONTENT is false (api-forms DEV-1270; the listing advertises it as anonymous.saveContent), so a report is validated and e-mailed with nothing written to the HSOT content stage — the desk e-mail is the only copy, and a person reads it before any score is entered. Two consequences the component relies on: a failed desk e-mail comes back as a 502 (shown as a retryable banner) rather than a saved record with routing.state: failed, and a retry sends a fresh e-mail rather than replaying a stored submission. The done view's routing.state: failed copy remains for a stage that does save records.

A 401 re-mints the session once and retries. A 409 (the document changed) refetches it and asks the visitor to check their answers. Everything else is a banner by kind: unreachable, throttled (the server's message), a refused field, "temporarily unavailable" (anonymous submission off on the stage, or the form not published there), or a commit error that is safe to retry. A second click while a send is in flight is ignored, and the request id never changes across retries.

Development

Requires Node 18+.

npm install
npm run dev     # harness on http://localhost:5175
npm test        # node --test over src/lib
npm run lint
npm run build   # dist/index.mjs + dist/define.mjs (lit external)
                # and dist/define.standalone.js (self-contained, for <script src>)

The harness (index.html) mounts the component against the in-memory demo client (src/demo/demo-client.mjs), which stands in for both backends: #/game_015 pre-fills from a final, #/game_016 from a scheduled game, ?rail turns on the promo and right rail, ?demofail=1 makes the first commit fail as a network error, ?anonoff=1 shows the stage-has-anonymous-off state. Submits are logged to the console.

Release

Push a vX.Y.Z tag: the pipeline tests, builds, publishes to npm, and uploads dist/ to the HSOT components CDN at /hsot-score-report/vX.Y.Z/ (immutable) plus the rolling aliases /hsot-score-report/vX/, /vX.Y/ and /latest/ (5-minute TTL). Pages pin the major alias (/hsot-score-report/v0/). Repo variables: NPM_TOKEN, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION, S3_BUCKET (the bucket behind web-components.cdn.highschoolot.com), S3_PREFIX=hsot-score-report, AWS_DISTRIBUTION_ID.

Before the page works on a stage

The component itself needs nothing deployed; the HSOT api-forms stage does:

  • An api-forms-hsot lambda with CONTENT_API at the HSOT content stage, a service JWT with email:send, ANON_SUBMIT_ENABLED plus a signing secret, FORMS_EMAIL_LIST_OVERRIDE set to the desk's Sailthru list, and a verified sender — and a /forms resource in the gateway stage that api.highschoolot.com fronts.
  • The score form seeded there: node scripts/seed-forms.mjs hsot-score in api-forms, pointed at the HSOT content stage.

Until then the page says score reporting is temporarily unavailable.

FAQs

Package last updated on 16 Sep 2026

Related posts