Skip to content

feat(young): expose second-classroom events across all interfaces - #997

Merged
tiankaima-copilot merged 3 commits into
mainfrom
feat/young-events
Sep 2, 2026
Merged

feat(young): expose second-classroom events across all interfaces#997
tiankaima-copilot merged 3 commits into
mainfrom
feat/young-events

Conversation

@tiankaima-copilot

@tiankaima-copilot tiankaima-copilot commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Import 第二课堂 signup events from young.ustc.edu.cn (cached in the life-ustc/static snapshot) into the server database, and expose them on every interface.

  • Static import: src/static-loader/young-plan.ts reads young_mobile_item_enrolment_list_result_records from the static snapshot; skipped when the snapshot has no young-events metadata.
  • Prisma: new YoungEvent model + migration; dev seed adds one active and one ended event.
  • Service layer: src/features/young/server/young-event-service.ts (list / detail / categories), shared by all transports.
  • REST: GET /api/catalog/young-events (+/[youngId]) with regenerated OpenAPI spec.
  • GraphQL: catalog.youngEvents / catalog.youngEvent + registered ops catalog.young_event.list.v1 / catalog.young_event.get.v1; SDL snapshot updated.
  • MCP: catalog_young_event_list / catalog_young_event_get (anonymous scope); compact dispatcher guards against the course-compaction heuristic mangling young events.
  • Web: /catalog/young-events list (search, signup-status filter, pagination) and /[youngId] detail pages, zh/en i18n, nav entries, sitemap (active events only).
  • Poster images: GET /api/catalog/young-events/[youngId]/image — lazy cache-aside proxy into R2 (R2_PUBLICATIONS, keys young-events/images/<pic path>, immutable cache headers, ETag/304). The stored imageUrl is the platform's raw relative pic path; on miss the Worker fetches https://young.ustc.edu.cn/login/<pic> once and persists it via waitUntil. All interfaces expose the local proxy path as imageUrl.

Verification

  • Unit: 405 files / 2536 tests pass (incl. new loader + service tests)
  • MCP integration: 4/4; REST Playwright contracts: 7/7; e2e browser specs: 7/7
  • tsc (all three typecheck configs), svelte-check, GraphQL SDL snapshot all clean
  • Real static snapshot dry-run: 2556 events imported

Screenshots

Captured against real data imported from the life-ustc/static snapshot (2556 events; detail page: 东野圭吾作品读书心得征集), desktop 1280px.

The detail poster is served through the new R2-backed proxy route (verified end-to-end: first hit fetches origin ~1s, second hit serves from R2 in ~10ms).

/catalog/young-events — 列表(zh / en)

第二课堂列表
Second Classroom list

/catalog/young-events/[youngId] — 详情(zh / en)

第二课堂详情
Second Classroom detail

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 1, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
life-ustc 7bf9eb1 Sep 02 2026, 03:51 AM

Import young.ustc.edu.cn signup events from the static snapshot into a new
YoungEvent model, then surface them through REST (/api/catalog/young-events),
GraphQL (catalog.youngEvents/youngEvent), MCP (catalog_young_event_*), and the
web catalog (/catalog/young-events) with zh/en i18n, navigation, and sitemap
entries.
imageUrl stored from the static snapshot is a raw young.ustc.edu.cn pic
path, so rendering it directly hotlinks (and breaks, since the path is
relative). Add GET /api/catalog/young-events/[youngId]/image: serve from
R2_PUBLICATIONS under young-events/images/ with immutable cache headers;
on miss fetch https://young.ustc.edu.cn/login/<pic>, persist via waitUntil,
and stream to the client. The service now exposes the local proxy path as
imageUrl across REST/GraphQL/MCP/web.
…buse

Only persist image/* payloads (an upstream error page would otherwise
become immutable same-origin content), cap origin reads at 10 MB, and add
short CDN caching to 404/502 image responses to absorb repeat misses.
Also return youngId in the MCP found payload for consistency with the
not-found shape.
@tiankaima-copilot
tiankaima-copilot merged commit 9c22931 into main Sep 2, 2026
15 of 16 checks passed
@tiankaima-copilot
tiankaima-copilot deleted the feat/young-events branch September 2, 2026 03:57
tiankaima-copilot added a commit that referenced this pull request Sep 2, 2026
…ops (#1003)

catalog.young_event.list.v1 and catalog.young_event.get.v1 raised the
registered operation count from 47 to 49; the main-only MCP integration
job caught the stale assertion after #997 merged.

Co-authored-by: TianKai Ma <tiankaima@163.com>
github-actions Bot pushed a commit that referenced this pull request Sep 2, 2026
# [1.103.0](v1.102.1...v1.103.0) (2026-09-02)

### Bug Fixes

* **graphql:** update MCP operation manifest count after young events ops ([#1003](#1003)) ([6450a9a](6450a9a)), closes [#997](#997)

### Features

* **young:** expose second-classroom events across all interfaces ([#997](#997)) ([9c22931](9c22931))
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.103.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants