feat: data-driven page.server.ts with config merge logic (#36) #43

Merged
forgejo_admin merged 1 commit from 36-data-driven-page-server into main 2026-04-04 22:58:55 +00:00
Contributor

Summary

Loads t.contract_config and p.contract_overrides from the database in +page.server.ts, merges team defaults with player overrides via a pure function, and passes the merged config to the page for data-driven rendering.

Changes

  • src/lib/contract-config.ts (NEW) — Pure mergeContractConfig() function with full TypeScript interfaces (ContractConfig, ContractOverrides, MergedConfig, Tournament, Practice, PaymentSchedule, ContractSections). Implements all merge rules: monthly_fee cascade, tournament filtering by ID, practice/payment replacement, section shallow merge, note passthrough.
  • src/lib/types.ts — Re-exports all config types from contract-config.ts. Adds contract_config and contract_overrides fields to the Player interface.
  • src/routes/contract/[token]/+page.server.ts — Updated SQL SELECT to include t.contract_config and p.contract_overrides. Calls mergeContractConfig() and passes config to the page. Backwards compatible: null config triggers hardcoded fallback.
  • tests/contract-config.test.ts (NEW) — 16 unit tests covering: null team config, no overrides passthrough, monthly_fee cascade (player > override > team default > 200), tournament filtering, practice/payment replacement, section shallow merge, note passthrough, combined overrides.

Test Plan

  • npm test — 30 tests pass (16 new + 14 existing)
  • npm run check — no new errors (12 pre-existing errors in db.ts/minio.ts/sign endpoint are unrelated)
  • Verify null contract_config returns null config (hardcoded fallback)
  • Verify tournament filtering with subset of IDs

Review Checklist

  • Tests pass (npm test — 30/30)
  • Type check passes (no new errors from npm run check)
  • No unrelated file changes
  • Backwards compatible — null config triggers hardcoded fallback
  • Pure function is testable in isolation
  • None
  • Forgejo issue: #36
  • Parent issue: #34 (data-driven contract rendering system)
  • Depends on: basketball-api #319 (contract_config column), basketball-api #321 (contract_overrides column)

Closes #36

## Summary Loads `t.contract_config` and `p.contract_overrides` from the database in `+page.server.ts`, merges team defaults with player overrides via a pure function, and passes the merged config to the page for data-driven rendering. ## Changes - **`src/lib/contract-config.ts`** (NEW) — Pure `mergeContractConfig()` function with full TypeScript interfaces (`ContractConfig`, `ContractOverrides`, `MergedConfig`, `Tournament`, `Practice`, `PaymentSchedule`, `ContractSections`). Implements all merge rules: monthly_fee cascade, tournament filtering by ID, practice/payment replacement, section shallow merge, note passthrough. - **`src/lib/types.ts`** — Re-exports all config types from `contract-config.ts`. Adds `contract_config` and `contract_overrides` fields to the `Player` interface. - **`src/routes/contract/[token]/+page.server.ts`** — Updated SQL SELECT to include `t.contract_config` and `p.contract_overrides`. Calls `mergeContractConfig()` and passes `config` to the page. Backwards compatible: null config triggers hardcoded fallback. - **`tests/contract-config.test.ts`** (NEW) — 16 unit tests covering: null team config, no overrides passthrough, monthly_fee cascade (player > override > team default > 200), tournament filtering, practice/payment replacement, section shallow merge, note passthrough, combined overrides. ## Test Plan - `npm test` — 30 tests pass (16 new + 14 existing) - `npm run check` — no new errors (12 pre-existing errors in db.ts/minio.ts/sign endpoint are unrelated) - Verify null contract_config returns null config (hardcoded fallback) - Verify tournament filtering with subset of IDs ## Review Checklist - [x] Tests pass (`npm test` — 30/30) - [x] Type check passes (no new errors from `npm run check`) - [x] No unrelated file changes - [x] Backwards compatible — null config triggers hardcoded fallback - [x] Pure function is testable in isolation ## Related Notes - None ## Related - Forgejo issue: #36 - Parent issue: #34 (data-driven contract rendering system) - Depends on: basketball-api #319 (contract_config column), basketball-api #321 (contract_overrides column) Closes #36
Load t.contract_config and p.contract_overrides from the database,
merge team defaults with player overrides via a pure function, and
pass the merged config to the page for data-driven rendering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Contributor

QA Review

Scope Check

  • 4 files changed (2 new, 2 modified) -- matches issue #36 file targets exactly
  • No files touched outside scope (db.ts, minio.ts, validation.ts, sign endpoint all untouched)

Code Quality

contract-config.ts -- Clean pure function. All merge rules from the spec are implemented correctly:

  • monthly_fee cascade: player column > override > team default > 200
  • tournaments: filter by ID set
  • practices/payments: full replacement
  • sections: shallow merge (spread operator, override wins)
  • note: from override only
  • null teamConfig returns null (hardcoded fallback path)

types.ts -- Re-exports are clean. import() type syntax for the two new Player fields avoids circular dependency issues.

+page.server.ts -- SQL updated correctly. t.contract_config added from teams table. Merge called with correct argument order. config passed to page return.

Nit

  • p.contract_overrides is explicitly selected in the SQL, but p.* already includes all player columns. Not a bug -- Postgres handles it fine and it documents intent. No action needed.

Tests

  • 16 unit tests covering all merge rules, edge cases (null config, empty overrides, combined overrides, nonexistent tournament IDs)
  • 30/30 tests pass
  • npm run check has no new errors (12 pre-existing in db.ts/minio.ts/sign)

SOP Compliance

  • Branch naming: 36-data-driven-page-server -- correct format
  • PR body: all required sections present
  • Closes #36 present
  • No secrets or env files committed

VERDICT: APPROVED

## QA Review ### Scope Check - 4 files changed (2 new, 2 modified) -- matches issue #36 file targets exactly - No files touched outside scope (db.ts, minio.ts, validation.ts, sign endpoint all untouched) ### Code Quality **contract-config.ts** -- Clean pure function. All merge rules from the spec are implemented correctly: - monthly_fee cascade: player column > override > team default > 200 - tournaments: filter by ID set - practices/payments: full replacement - sections: shallow merge (spread operator, override wins) - note: from override only - null teamConfig returns null (hardcoded fallback path) **types.ts** -- Re-exports are clean. `import()` type syntax for the two new Player fields avoids circular dependency issues. **+page.server.ts** -- SQL updated correctly. `t.contract_config` added from teams table. Merge called with correct argument order. `config` passed to page return. ### Nit - `p.contract_overrides` is explicitly selected in the SQL, but `p.*` already includes all player columns. Not a bug -- Postgres handles it fine and it documents intent. No action needed. ### Tests - 16 unit tests covering all merge rules, edge cases (null config, empty overrides, combined overrides, nonexistent tournament IDs) - 30/30 tests pass - `npm run check` has no new errors (12 pre-existing in db.ts/minio.ts/sign) ### SOP Compliance - Branch naming: `36-data-driven-page-server` -- correct format - PR body: all required sections present - `Closes #36` present - No secrets or env files committed **VERDICT: APPROVED**
forgejo_admin deleted branch 36-data-driven-page-server 2026-04-04 22:58:55 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ldraney/westside-contracts!43
No description provided.