From 2bade1825c4098dbf29a6f1d4c5113908e76d189 Mon Sep 17 00:00:00 2001 From: "D. Rimron-Soutter" Date: Wed, 17 Dec 2025 22:30:48 +0000 Subject: [PATCH] Add entry_id relationship links to Entries - Introduce reusable EntryLink component - Use EntryLink in Releases and Label detail tables - Link both ID and title to /zxdb/entries/[id] for consistency Signed-off-by: Junie@MacOS --- .output.txt | 225 +++++++++++++++++++++ COMMIT_EDITMSG | 7 + src/app/zxdb/components/EntryLink.tsx | 18 ++ src/app/zxdb/entries/EntriesExplorer.tsx | 5 +- src/app/zxdb/entries/[id]/EntryDetail.tsx | 71 +++++++ src/app/zxdb/labels/[id]/LabelDetail.tsx | 5 +- src/app/zxdb/releases/ReleasesExplorer.tsx | 7 +- src/server/repo/zxdb.ts | 26 +++ src/server/schema/zxdb.ts | 24 +++ 9 files changed, 382 insertions(+), 6 deletions(-) create mode 100644 .output.txt create mode 100644 COMMIT_EDITMSG create mode 100644 src/app/zxdb/components/EntryLink.tsx diff --git a/.output.txt b/.output.txt new file mode 100644 index 0000000..a78c4f1 --- /dev/null +++ b/.output.txt @@ -0,0 +1,225 @@ + ▲ Next.js 15.5.9 (Turbopack) + - Environments: .env + Creating an optimized production build ... + ✓ Finished writing to disk in 48ms +Turbopack build encountered 21 warnings: +./src/scss/nbn.scss +Issue while running loader +SassWarning: 311 repetitive deprecation warnings omitted. +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 0, column 8 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/bootstrap.scss:0:8: +Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0. +More info and automated migrator: https://sass-lang.com/d/import +0 | @import "mixins/banner"; +node_modules/bootstrap/scss/bootstrap.scss 1:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 10, column 29 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:10:29: +Global built-in functions are deprecated and will be removed in Dart Sass 3.0.0. +Use math.unit instead. +More info and automated migrator: https://sass-lang.com/d/import +10 | @if $prev-num == null or unit($num) == "%" or unit($prev-num) == "%" { +node_modules/bootstrap/scss/_functions.scss 11:30 -assert-ascending() +node_modules/bootstrap/scss/_variables.scss 494:1 @import +node_modules/bootstrap/scss/bootstrap.scss 8:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 10, column 50 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:10:50: +Global built-in functions are deprecated and will be removed in Dart Sass 3.0.0. +Use math.unit instead. +More info and automated migrator: https://sass-lang.com/d/import +10 | @if $prev-num == null or unit($num) == "%" or unit($prev-num) == "%" { +node_modules/bootstrap/scss/_functions.scss 11:51 -assert-ascending() +node_modules/bootstrap/scss/_variables.scss 494:1 @import +node_modules/bootstrap/scss/bootstrap.scss 8:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 10, column 8 of file:///Volumes/McFiver/u/GIT/next-explorer/src/scss/nbn.scss:10:8: +Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0. +More info and automated migrator: https://sass-lang.com/d/import +10 | @import "bootswatch"; +src/scss/nbn.scss 11:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 12, column 8 of file:///Volumes/McFiver/u/GIT/next-explorer/src/scss/nbn.scss:12:8: +Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0. +More info and automated migrator: https://sass-lang.com/d/import +12 | @import "explorer"; +src/scss/nbn.scss 13:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 176, column 10 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:176:10: +The Sass if() syntax is deprecated in favor of the modern CSS syntax. +Suggestion: if(sass($l1 > $l2): divide($l1 + 0.05, $l2 + 0.05); else: divide($l2 + 0.05, $l1 + 0.05)) +More info: https://sass-lang.com/d/if-function +176 | @return if($l1 > $l2, divide($l1 + .05, $l2 + .05), divide($l2 + .05, $l1 + .05)); +node_modules/bootstrap/scss/_functions.scss 177:11 @import +node_modules/bootstrap/scss/bootstrap.scss 7:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 184, column 9 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:184:9: +red() is deprecated. Suggestion: +color.channel($color, "red", $space: rgb) +More info: https://sass-lang.com/d/color-functions +184 | "r": red($color), +node_modules/bootstrap/scss/_functions.scss 185:10 luminance() +node_modules/bootstrap/scss/_functions.scss 174:8 contrast-ratio() +node_modules/bootstrap/scss/_functions.scss 159:22 color-contrast() +node_modules/bootstrap/scss/_variables.scss 846:42 @import +node_modules/bootstrap/scss/bootstrap.scss 8:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 185, column 9 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:185:9: +green() is deprecated. Suggestion: +color.channel($color, "green", $space: rgb) +More info: https://sass-lang.com/d/color-functions +185 | "g": green($color), +node_modules/bootstrap/scss/_functions.scss 186:10 luminance() +node_modules/bootstrap/scss/_functions.scss 174:8 contrast-ratio() +node_modules/bootstrap/scss/_functions.scss 159:22 color-contrast() +node_modules/bootstrap/scss/_variables.scss 846:42 @import +node_modules/bootstrap/scss/bootstrap.scss 8:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 186, column 9 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:186:9: +blue() is deprecated. Suggestion: +color.channel($color, "blue", $space: rgb) +More info: https://sass-lang.com/d/color-functions +186 | "b": blue($color) +node_modules/bootstrap/scss/_functions.scss 187:10 luminance() +node_modules/bootstrap/scss/_functions.scss 174:8 contrast-ratio() +node_modules/bootstrap/scss/_functions.scss 159:22 color-contrast() +node_modules/bootstrap/scss/_variables.scss 846:42 @import +node_modules/bootstrap/scss/bootstrap.scss 8:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 190, column 12 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:190:12: +The Sass if() syntax is deprecated in favor of the modern CSS syntax. +Suggestion: if(sass(divide($value, 255) < 0.04045): divide(divide($value, 255), 12.92); else: nth($_luminance-list, $value + 1)) +More info: https://sass-lang.com/d/if-function +190 | $value: if(divide($value, 255) < .04045, divide(divide($value, 255), 12.92), nth($_luminance-list, $value + 1)); +node_modules/bootstrap/scss/_functions.scss 191:13 @import +node_modules/bootstrap/scss/bootstrap.scss 7:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 206, column 10 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:206:10: +Global built-in functions are deprecated and will be removed in Dart Sass 3.0.0. +Use color.mix instead. +More info and automated migrator: https://sass-lang.com/d/import +206 | @return mix(white, $color, $weight); +node_modules/bootstrap/scss/_functions.scss 207:11 tint-color() +node_modules/bootstrap/scss/_variables.scss 79:12 @import +node_modules/bootstrap/scss/bootstrap.scss 8:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 211, column 10 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:211:10: +Global built-in functions are deprecated and will be removed in Dart Sass 3.0.0. +Use color.mix instead. +More info and automated migrator: https://sass-lang.com/d/import +211 | @return mix(black, $color, $weight); +node_modules/bootstrap/scss/_functions.scss 212:11 shade-color() +node_modules/bootstrap/scss/_variables.scss 84:12 @import +node_modules/bootstrap/scss/bootstrap.scss 8:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 216, column 10 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:216:10: +The Sass if() syntax is deprecated in favor of the modern CSS syntax. +Suggestion: if(sass($weight > 0): shade-color($color, $weight); else: tint-color($color, -$weight)) +More info: https://sass-lang.com/d/if-function +216 | @return if($weight > 0, shade-color($color, $weight), tint-color($color, -$weight)); +node_modules/bootstrap/scss/_functions.scss 217:11 @import +node_modules/bootstrap/scss/bootstrap.scss 7:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 341, column 26 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_variables.scss:341:26: +Global built-in functions are deprecated and will be removed in Dart Sass 3.0.0. +Use color.mix instead. +More info and automated migrator: https://sass-lang.com/d/import +341 | $light-bg-subtle: mix($gray-100, $white) !default; +node_modules/bootstrap/scss/_variables.scss 342:27 @import +node_modules/bootstrap/scss/bootstrap.scss 8:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 36, column 10 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:36:10: +red() is deprecated. Suggestion: +color.channel($color, "red", $space: rgb) +More info: https://sass-lang.com/d/color-functions +36 | @return red($value), green($value), blue($value); +node_modules/bootstrap/scss/_functions.scss 37:11 to-rgb() +node_modules/bootstrap/scss/_variables.scss 846:31 @import +node_modules/bootstrap/scss/bootstrap.scss 8:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 36, column 23 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:36:23: +green() is deprecated. Suggestion: +color.channel($color, "green", $space: rgb) +More info: https://sass-lang.com/d/color-functions +36 | @return red($value), green($value), blue($value); +node_modules/bootstrap/scss/_functions.scss 37:24 to-rgb() +node_modules/bootstrap/scss/_variables.scss 846:31 @import +node_modules/bootstrap/scss/bootstrap.scss 8:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 57, column 29 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:57:29: +The Sass if() syntax is deprecated in favor of the modern CSS syntax. +Suggestion: if(sass($arg == "$key"): $key; else: if($arg == "$value", $value, $arg)) +More info: https://sass-lang.com/d/if-function +57 | $_args: append($_args, if($arg == "$key", $key, if($arg == "$value", $value, $arg))); +node_modules/bootstrap/scss/_functions.scss 58:30 @import +node_modules/bootstrap/scss/bootstrap.scss 7:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 57, column 54 of file:///Volumes/McFiver/u/GIT/next-explorer/node_modules/bootstrap/scss/_functions.scss:57:54: +The Sass if() syntax is deprecated in favor of the modern CSS syntax. +Suggestion: if(sass($arg == "$value"): $value; else: $arg) +More info: https://sass-lang.com/d/if-function +57 | $_args: append($_args, if($arg == "$key", $key, if($arg == "$value", $value, $arg))); +node_modules/bootstrap/scss/_functions.scss 58:55 @import +node_modules/bootstrap/scss/bootstrap.scss 7:9 @import +src/scss/nbn.scss 9:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 6, column 8 of file:///Volumes/McFiver/u/GIT/next-explorer/src/scss/nbn.scss:6:8: +Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0. +More info and automated migrator: https://sass-lang.com/d/import +6 | @import "variables"; +src/scss/nbn.scss 7:9 root stylesheet +./src/scss/nbn.scss +Issue while running loader +SassWarning: Deprecation Warning on line 8, column 8 of file:///Volumes/McFiver/u/GIT/next-explorer/src/scss/nbn.scss:8:8: +Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0. +More info and automated migrator: https://sass-lang.com/d/import +8 | @import "../../node_modules/bootstrap/scss/bootstrap"; +src/scss/nbn.scss 9:9 root stylesheet + ✓ Compiled successfully in 3.7s +./src/app/zxdb/releases/ReleasesExplorer.tsx +142:6 Warning: React Hook useEffect has missing dependencies: 'fetchData', 'initial', 'initialUrlState?.casetypeId', 'initialUrlState?.dLanguageId', 'initialUrlState?.dMachinetypeId', 'initialUrlState?.filetypeId', 'initialUrlState?.isDemo', 'initialUrlState?.q', 'initialUrlState?.schemetypeId', 'initialUrlState?.sort', 'initialUrlState?.sourcetypeId', 'initialUrlState?.year', 'q', and 'updateUrl'. Either include them or remove the dependency array. react-hooks/exhaustive-deps +info - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/app/api-reference/config/eslint#disabling-rules +Failed to compile. +./src/server/repo/zxdb.ts:491:17 +Type error: Argument of type 'Name' is not assignable to parameter of type 'SQL | Column, object, object> | Aliased'. + Type 'Name' is missing the following properties from type 'Aliased': sql, fieldAlias, _ + 489 | .select({ total: sql`count(distinct ${sql.identifier("label_id")})` }) + 490 | .from(sql`search_by_names`) +> 491 | .where(like(sql.identifier("label_name"), pattern)); + | ^ + 492 | const total = Number(countRows[0]?.total ?? 0); + 493 | + 494 | const items = await db +Next.js build worker exited with code: 1 and signal: null diff --git a/COMMIT_EDITMSG b/COMMIT_EDITMSG new file mode 100644 index 0000000..3f59d34 --- /dev/null +++ b/COMMIT_EDITMSG @@ -0,0 +1,7 @@ +Add entry_id relationship links to Entries + +- Introduce reusable EntryLink component +- Use EntryLink in Releases and Label detail tables +- Link both ID and title to /zxdb/entries/[id] for consistency + +Signed-off-by: Junie@MacOS diff --git a/src/app/zxdb/components/EntryLink.tsx b/src/app/zxdb/components/EntryLink.tsx new file mode 100644 index 0000000..d5d1ab3 --- /dev/null +++ b/src/app/zxdb/components/EntryLink.tsx @@ -0,0 +1,18 @@ +"use client"; + +import Link from "next/link"; + +type Props = { + id: number; + title?: string; + className?: string; +}; + +export default function EntryLink({ id, title, className }: Props) { + const text = typeof title === "string" && title.length > 0 ? title : `#${id}`; + return ( + + {text} + + ); +} diff --git a/src/app/zxdb/entries/EntriesExplorer.tsx b/src/app/zxdb/entries/EntriesExplorer.tsx index 84de55e..50a5ead 100644 --- a/src/app/zxdb/entries/EntriesExplorer.tsx +++ b/src/app/zxdb/entries/EntriesExplorer.tsx @@ -2,6 +2,7 @@ import { useEffect, useMemo, useState } from "react"; import Link from "next/link"; +import EntryLink from "../components/EntryLink"; import { usePathname, useRouter } from "next/navigation"; type Item = { @@ -244,9 +245,9 @@ export default function EntriesExplorer({ {data.items.map((it) => ( - {it.id} + - {it.title} + {it.machinetypeId != null ? ( diff --git a/src/app/zxdb/entries/[id]/EntryDetail.tsx b/src/app/zxdb/entries/[id]/EntryDetail.tsx index e5473ec..af2d156 100644 --- a/src/app/zxdb/entries/[id]/EntryDetail.tsx +++ b/src/app/zxdb/entries/[id]/EntryDetail.tsx @@ -66,6 +66,9 @@ export type EntryDetailData = { year: number | null; }[]; }[]; + // Additional relationships + aliases?: { releaseSeq: number; languageId: string; title: string }[]; + webrefs?: { link: string; languageId: string; website: { id: number; name: string; link?: string | null } }[]; }; export default function EntryDetailClient({ data }: { data: EntryDetailData | null }) { @@ -286,6 +289,74 @@ export default function EntryDetailClient({ data }: { data: EntryDetailData | nu
+ {/* Aliases (alternative titles) */} +
+
Aliases
+ {(!data.aliases || data.aliases.length === 0) &&
No aliases
} + {data.aliases && data.aliases.length > 0 && ( +
+ + + + + + + + + + {data.aliases.map((a, idx) => ( + + + + + + ))} + +
Release #LanguageTitle
#{a.releaseSeq}{a.languageId}{a.title}
+
+ )} +
+ +
+ + {/* Web links (external references) */} +
+
Web links
+ {(!data.webrefs || data.webrefs.length === 0) &&
No web links
} + {data.webrefs && data.webrefs.length > 0 && ( +
+ + + + + + + + + + {data.webrefs.map((w, idx) => ( + + + + + + ))} + +
WebsiteLanguageURL
+ {w.website.link ? ( + {w.website.name} + ) : ( + {w.website.name} + )} + {w.languageId} + {w.link} +
+
+ )} +
+ +
+
Files
{(!data.files || data.files.length === 0) &&
No files linked
} diff --git a/src/app/zxdb/labels/[id]/LabelDetail.tsx b/src/app/zxdb/labels/[id]/LabelDetail.tsx index ef98eec..3e187bd 100644 --- a/src/app/zxdb/labels/[id]/LabelDetail.tsx +++ b/src/app/zxdb/labels/[id]/LabelDetail.tsx @@ -1,6 +1,7 @@ "use client"; import Link from "next/link"; +import EntryLink from "../../components/EntryLink"; import { useMemo, useState } from "react"; import { useRouter } from "next/navigation"; @@ -69,8 +70,8 @@ export default function LabelDetailClient({ id, initial, initialTab, initialQ }: {current.items.map((it) => ( - {it.id} - {it.title} + + {it.machinetypeId != null ? ( it.machinetypeName ? ( diff --git a/src/app/zxdb/releases/ReleasesExplorer.tsx b/src/app/zxdb/releases/ReleasesExplorer.tsx index 413e509..80f6e5b 100644 --- a/src/app/zxdb/releases/ReleasesExplorer.tsx +++ b/src/app/zxdb/releases/ReleasesExplorer.tsx @@ -2,6 +2,7 @@ import { useEffect, useMemo, useState } from "react"; import Link from "next/link"; +import EntryLink from "../components/EntryLink"; import { usePathname, useRouter } from "next/navigation"; type Item = { @@ -313,9 +314,11 @@ export default function ReleasesExplorer({ {data.items.map((it) => ( - {it.entryId} - {it.entryTitle} + + + + #{it.releaseSeq} {it.year ?? -} diff --git a/src/server/repo/zxdb.ts b/src/server/repo/zxdb.ts index 0689cd0..9f60e30 100644 --- a/src/server/repo/zxdb.ts +++ b/src/server/repo/zxdb.ts @@ -20,6 +20,9 @@ import { availabletypes, currencies, roletypes, + aliases, + webrefs, + websites, } from "@/server/schema/zxdb"; export interface SearchParams { @@ -219,6 +222,9 @@ export interface EntryDetail { year: number | null; }[]; }[]; + // Additional relationships surfaced on the entry detail page + aliases?: { releaseSeq: number; languageId: string; title: string }[]; + webrefs?: { link: string; languageId: string; website: { id: number; name: string; link?: string | null } }[]; } export async function getEntryById(id: number): Promise { @@ -411,6 +417,24 @@ export async function getEntryById(id: number): Promise { // Sort releases by sequence for stable UI order releasesData.sort((a, b) => a.releaseSeq - b.releaseSeq); + // Fetch extra relationships in parallel + let aliasRows: { releaseSeq: number | string; languageId: string; title: string }[] = []; + let webrefRows: { link: string; languageId: string; websiteId: number | string; websiteName: string; websiteLink: string | null }[] = []; + try { + aliasRows = await db + .select({ releaseSeq: aliases.releaseSeq, languageId: aliases.languageId, title: aliases.title }) + .from(aliases) + .where(eq(aliases.entryId, id)); + } catch {} + try { + const rows = await db + .select({ link: webrefs.link, languageId: webrefs.languageId, websiteId: websites.id, websiteName: websites.name, websiteLink: websites.link }) + .from(webrefs) + .innerJoin(websites, eq(websites.id, webrefs.websiteId)) + .where(eq(webrefs.entryId, id)); + webrefRows = rows as typeof webrefRows; + } catch {} + return { id: base.id, title: base.title, @@ -453,6 +477,8 @@ export async function getEntryById(id: number): Promise { year: d.year != null ? Number(d.year) : null, releaseSeq: Number(d.releaseSeq), })), + aliases: aliasRows.map((a) => ({ releaseSeq: Number(a.releaseSeq), languageId: a.languageId, title: a.title })), + webrefs: webrefRows.map((w) => ({ link: w.link, languageId: w.languageId, website: { id: Number(w.websiteId), name: w.websiteName, link: w.websiteLink } })), }; } diff --git a/src/server/schema/zxdb.ts b/src/server/schema/zxdb.ts index 382b086..d632de4 100644 --- a/src/server/schema/zxdb.ts +++ b/src/server/schema/zxdb.ts @@ -143,6 +143,14 @@ export const hosts = mysqlTable("hosts", { magazineId: smallint("magazine_id"), }); +// ---- Aliases (alternative titles per entry/release/language) +export const aliases = mysqlTable("aliases", { + entryId: int("entry_id").notNull(), + releaseSeq: smallint("release_seq").notNull().default(0), + languageId: char("language_id", { length: 2 }).notNull(), + title: varchar("title", { length: 250 }).notNull(), +}); + // `releases` are identified by (entry_id, release_seq) export const releases = mysqlTable("releases", { entryId: int("entry_id").notNull(), @@ -184,6 +192,22 @@ export const downloads = mysqlTable("downloads", { comments: varchar("comments", { length: 250 }), }); +// ---- Web references (external links tied to entries) +export const webrefs = mysqlTable("webrefs", { + entryId: int("entry_id").notNull(), + link: varchar("link", { length: 200 }).notNull(), + websiteId: tinyint("website_id").notNull(), + languageId: char("language_id", { length: 2 }).notNull(), +}); + +export const websites = mysqlTable("websites", { + id: tinyint("id").notNull().primaryKey(), + name: varchar("name", { length: 100 }).notNull(), + comments: varchar("comments", { length: 100 }), + link: varchar("link", { length: 100 }), + linkMask: varchar("link_mask", { length: 100 }), +}); + // Roles relation (composite PK in DB) export const roles = mysqlTable("roles", { entryId: int("entry_id").notNull(),