Handle missing ZXDB releases/downloads schema gracefully

Prevent runtime crashes when `releases`, `downloads`, or related lookup tables
(`releasetypes`, `schemetypes`, `sourcetypes`, `casetypes`) are absent in the
connected ZXDB MySQL database.

- Repo: gate releases/downloads queries behind a schema capability check using
  `information_schema.tables`; if missing, skip queries and return empty arrays.
- Keeps entry detail page functional on legacy/minimal DB exports while fully
  utilizing rich data when available.

Refs: runtime error "Table 'zxdb.releasetypes' doesn't exist"

Signed-off-by: Junie@quinn
This commit is contained in:
2025-12-16 18:41:14 +00:00
parent f507d51c61
commit 285c7da87c
5 changed files with 434 additions and 1 deletions

View File

@@ -1,4 +1,4 @@
import { mysqlTable, int, varchar, tinyint, char } from "drizzle-orm/mysql-core";
import { mysqlTable, int, varchar, tinyint, char, smallint } from "drizzle-orm/mysql-core";
// Minimal subset needed for browsing/searching
export const entries = mysqlTable("entries", {
@@ -79,3 +79,91 @@ export const genretypes = mysqlTable("genretypes", {
// Column name in DB is `text`
name: varchar("text", { length: 50 }).notNull(),
});
// ----- Files and Filetypes (for downloads/assets) -----
export const filetypes = mysqlTable("filetypes", {
id: tinyint("id").notNull().primaryKey(),
// Column name in DB is `text`
name: varchar("text", { length: 50 }).notNull(),
});
export const files = mysqlTable("files", {
id: int("id").notNull().primaryKey(),
labelId: int("label_id"),
issueId: int("issue_id"),
toolId: int("tool_id"),
fileLink: varchar("file_link", { length: 250 }).notNull(),
fileDate: varchar("file_date", { length: 50 }),
fileSize: int("file_size"),
fileMd5: varchar("file_md5", { length: 32 }),
filetypeId: tinyint("filetype_id").notNull(),
comments: varchar("comments", { length: 250 }),
});
// ----- Releases / Downloads (linked assets per release) -----
// Lookups used by releases/downloads
export const releasetypes = mysqlTable("releasetypes", {
id: char("id", { length: 1 }).notNull().primaryKey(),
// column name in DB is `text`
name: varchar("text", { length: 50 }).notNull(),
});
export const schemetypes = mysqlTable("schemetypes", {
id: char("id", { length: 2 }).notNull().primaryKey(),
name: varchar("text", { length: 50 }).notNull(),
});
export const sourcetypes = mysqlTable("sourcetypes", {
id: char("id", { length: 1 }).notNull().primaryKey(),
name: varchar("text", { length: 50 }).notNull(),
});
export const casetypes = mysqlTable("casetypes", {
id: char("id", { length: 1 }).notNull().primaryKey(),
name: varchar("text", { length: 50 }).notNull(),
});
export const hosts = mysqlTable("hosts", {
id: tinyint("id").notNull().primaryKey(),
title: varchar("title", { length: 150 }).notNull(),
link: varchar("link", { length: 150 }).notNull(),
admin: varchar("admin", { length: 150 }).notNull(),
magazineId: smallint("magazine_id"),
});
// `releases` are identified by (entry_id, release_seq)
export const releases = mysqlTable("releases", {
entryId: int("entry_id").notNull(),
releaseSeq: smallint("release_seq").notNull(),
releasetypeId: char("releasetype_id", { length: 1 }),
languageId: char("language_id", { length: 2 }),
machinetypeId: tinyint("machinetype_id"),
labelId: int("label_id"), // developer
publisherId: int("publisher_label_id"),
releaseYear: smallint("release_year"),
comments: varchar("comments", { length: 250 }),
});
// Downloads are linked to a release via (entry_id, release_seq)
export const downloads = mysqlTable("downloads", {
id: int("id").notNull().primaryKey(),
entryId: int("entry_id").notNull(),
releaseSeq: smallint("release_seq").notNull().default(0),
fileLink: varchar("file_link", { length: 250 }).notNull(),
fileDate: varchar("file_date", { length: 50 }),
fileSize: int("file_size"),
fileMd5: varchar("file_md5", { length: 32 }),
filetypeId: tinyint("filetype_id").notNull(),
scrBorder: tinyint("scr_border").notNull().default(7),
languageId: char("language_id", { length: 2 }),
isDemo: tinyint("is_demo").notNull(),
schemetypeId: char("schemetype_id", { length: 2 }),
machinetypeId: tinyint("machinetype_id"),
fileCode: varchar("file_code", { length: 50 }),
fileBarcode: varchar("file_barcode", { length: 50 }),
fileDl: varchar("file_dl", { length: 150 }),
casetypeId: char("casetype_id", { length: 1 }),
sourcetypeId: char("sourcetype_id", { length: 1 }),
releaseYear: smallint("release_year"),
comments: varchar("comments", { length: 250 }),
});