Files
explorer/AGENTS.md
D. Rimron-Soutter 3fe6f980c6 feat: integrate ZXDB with Drizzle + deep explorer UI; fix Next 15 dynamic params; align ZXDB schema columns
End-to-end ZXDB integration with environment validation, Drizzle ORM MySQL
setup, typed repositories, Zod-validated API endpoints, and a deep, cross‑
linked Explorer UI under `/zxdb`. Also update dynamic route pages to the
Next.js 15 async `params` API and align ZXDB lookup table columns (`text` vs
`name`).

Summary
- Add t3.gg-style Zod environment validation and typed `env` access
- Wire Drizzle ORM to ZXDB (mysql2 pool, singleton) and minimal schemas
- Implement repositories for search, entry details, label browsing, and
  category listings (genres, languages, machinetypes)
- Expose a set of Next.js API routes with strict Zod validation
- Build the ZXDB Explorer UI with search, filters, sorting, deep links, and
  entity pages (entries, labels, genres, languages, machinetypes)
- Fix Next 15 “sync-dynamic-apis” warning by awaiting dynamic `params`
- Correct ZXDB lookup model columns to use `text` (aliased as `name`)

Details
Env & DB
- example.env: document `ZXDB_URL` with readonly role notes
- src/env.ts: Zod schema validates `ZXDB_URL` as `mysql://…`; fails fast on
  invalid env
- src/server/db.ts: create mysql2 pool from `ZXDB_URL`; export Drizzle instance
- drizzle.config.ts: drizzle-kit configuration (schema path, mysql2 driver)

Schema (Drizzle)
- src/server/schema/zxdb.ts:
  - entries: id, title, is_xrated, machinetype_id, language_id, genretype_id
  - helper tables: search_by_titles, search_by_names, search_by_authors,
    search_by_publishers
  - relations: authors, publishers
  - lookups: labels, languages, machinetypes, genretypes
  - map lookup display columns from DB `text` to model property `name`

Repository
- src/server/repo/zxdb.ts:
  - searchEntries: title search via helper table with filters (genre, language,
    machine), sorting (title, id_desc), and pagination
  - getEntryById: join lookups and aggregate authors/publishers
  - Label flows: searchLabels (helper table), getLabelById, getLabelAuthoredEntries,
    getLabelPublishedEntries
  - Category lists: listGenres, listLanguages, listMachinetypes
  - Category pages: entriesByGenre, entriesByLanguage, entriesByMachinetype

API (Node runtime, Zod validation)
- GET /api/zxdb/search: search entries with filters and sorting
- GET /api/zxdb/entries/[id]: fetch entry detail
- GET /api/zxdb/labels/search, GET /api/zxdb/labels/[id]: label search and detail
- GET /api/zxdb/genres, /api/zxdb/genres/[id]
- GET /api/zxdb/languages, /api/zxdb/languages/[id]
- GET /api/zxdb/machinetypes, /api/zxdb/machinetypes/[id]

UI (App Router)
- /zxdb: Explorer page with search box, filters (genre, language, machine), sort,
  paginated results & links to entries; quick browse links to hubs
- /zxdb/entries/[id]: entry detail client component shows title, badges
  (genre/lang/machine), authors and publishers with cross-links
- /zxdb/labels (+ /[id]): search & label detail with "Authored" and "Published"
  tabs, paginated lists linking to entries
- /zxdb/genres, /zxdb/languages, /zxdb/machinetypes and their /[id] detail pages
  listing paginated entries and deep links
- Navbar: add ZXDB link

Next 15 dynamic routes
- Convert Server Component dynamic pages to await `params` before accessing
  properties:
  - /zxdb/entries/[id]/page.tsx
  - /zxdb/labels/[id]/page.tsx
  - /zxdb/genres/[id]/page.tsx
  - /zxdb/languages/[id]/page.tsx
  - /registers/[hex]/page.tsx (Registers section)
- /api/zxdb/entries/[id]/route.ts: await `ctx.params` before validation

ZXDB schema column alignment
- languages, machinetypes, genretypes tables use `text` for display columns;
  models now map to `name` to preserve API/UI contracts and avoid MySQL 1054
  errors in joins (e.g., entry detail endpoint).

Notes
- Ensure ZXDB helper tables are created (ZXDB/scripts/ZXDB_help_search.sql)
  — required for fast title/name searches and author/publisher lookups.
- Pagination defaults to 20 (max 100). No `select *` used in queries.
- API responses are `cache: no-store` for now; can be tuned later.

Deferred (future work)
- Facet counts in the Explorer sidebar
- Breadcrumbs and additional a11y polish
- Media assets and download links per release

Signed-off-by: Junie@lucy.xalior.com

Signed-off-by: Junie@lucy.xalior.com
2025-12-12 14:41:19 +00:00

5.0 KiB
Raw Blame History

AGENT.md

This document provides an overview of the Next Explorer project, its structure, and its implementation details.

Project Overview

Next Explorer is a web application for browsing and exploring the registers of the Spectrum Next computer. It is built with Next.js (App Router), React, and TypeScript.

The application reads register data from data/nextreg.txt, parses it on the server, and displays it in a user-friendly interface. Users can search for specific registers and view their details, including per-register notes and source snippets.

Project Structure

The project is a Next.js application with the following structure:


next-explorer/
├── eslint.config.mjs
├── next.config.ts
├── package.json
├── pnpm-lock.yaml
├── tsconfig.json
├── data/
│   ├── nextreg.txt
│   ├── custom_parsers.txt
│   └── wikilinks.txt
├── node_modules/...
├── public/...
└── src/
├── middleware.js
├── app/
│   ├── layout.tsx
│   ├── page.module.css
│   ├── page.tsx
│   └── registers/
│       ├── page.tsx
│       ├── RegisterBrowser.tsx
│       ├── RegisterDetail.tsx
│       └── [hex]/
│           └── page.tsx
├── components/
│   ├── Navbar.tsx
│   └── ThemeDropdown.tsx
├── scss/
│   ├── _bootswatch.scss
│   ├── _explorer.scss
│   ├── _variables.scss
│   └── nbn.scss
├── services/
│   └── register.service.ts
└── utils/
├── register_parser.ts
└── register_parsers/
├── reg_default.ts
└── reg_f0.ts
  • data/: Contains the raw input data for the Spectrum Next explorer.
    • nextreg.txt: Main register definition file.
    • custom_parsers.txt, wikilinks.txt: Auxiliary configuration/data used by the parser.
  • src/app/: Next.js App Router entrypoint.
    • layout.tsx: Root layout for all routes.
    • page.tsx: Application home page.
    • registers/: Routes and components for the register explorer.
      • page.tsx: Server Component that loads and lists all registers.
      • RegisterBrowser.tsx: Client Component implementing search/filter and listing.
      • RegisterDetail.tsx: Client Component that renders a single registers details, including modes, notes, and source modal.
      • [hex]/page.tsx: Dynamic route that renders details for a specific register by hex address.
  • src/components/: Shared UI components such as Navbar and ThemeDropdown.
  • src/services/register.service.ts: Service layer responsible for loading and caching parsed register data.
  • src/utils/register_parser.ts & src/utils/register_parsers/: Parsing logic for nextreg.txt, including mode/bitfield handling and any register-specific parsing extensions.

Implementation Details

Comment what the code does, not what the agent has done. The documentation's purpose is the state of the application today, not a log of actions taken.

Data Parsing

  • getRegisters() in src/services/register.service.ts:

    • Reads data/nextreg.txt from disk.
    • Uses parseNextReg() from src/utils/register_parser.ts to convert the raw text into an array of Register objects.
    • Returns the in-memory representation of all registers (and can be extended to cache results across calls).
  • parseNextReg() and related helpers in register_parser.ts:

    • Parse the custom nextreg.txt format into structured data:
      • Register addresses (hex/dec).
      • Names, notes, and descriptive text.
      • Per-mode read/write/common bitfield views.
      • Optional source lines and external links (e.g. wiki URLs).
    • Delegate special-case parsing to functions in src/utils/register_parsers/ (e.g. reg_default.ts, reg_f0.ts) when needed.

React / Next.js Patterns

  • Server Components:

    • src/app/registers/page.tsx and src/app/registers/[hex]/page.tsx are Server Components.
    • They call getRegisters() on the server and pass the resulting data down to client components as props.
  • Client Components:

    • RegisterBrowser.tsx:
      • Marked with 'use client'.
      • Uses React state to manage search input and filtered results.
      • Renders a list or grid of registers.
    • RegisterDetail.tsx:
      • Marked with 'use client'.
      • Renders a single register with tabs for different access modes.
      • Uses a modal to show the original source lines for the register.
  • Dynamic Routing:

    • src/app/registers/[hex]/page.tsx:
      • Resolves the [hex] URL segment.
      • Looks up the corresponding register by hex_address.
      • Calls notFound() when no matching register exists.

Working Patterns***

  • git branching:
    • Do not create new branches
  • git commits:
    • Create COMMIT_EDITMSG file, await any user edits, then commit using that commit note, and then delete the COMMIT_EDITMSG file.
  • git commit messages:
    • Use imperative mood (e.g., "Add feature X", "Fix bug Y").
    • Include relevant issue numbers if applicable.
    • Sign-off commit message as Junie@