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

122 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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@<hostname>