Correct local file path resolution for ZXDB/WoS mirrors
- Remove optional path prefix and prepend the required local string. - Avoid hardcoded 'SC' or 'WoS' subdirectories in path mapping. - Maintain binary state: show local link only if env var is set and file exists. Signed-off: junie@McFiver.local
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import { and, desc, eq, sql, asc } from "drizzle-orm";
|
||||
import { cache } from "react";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { env } from "@/env";
|
||||
// import { alias } from "drizzle-orm/mysql-core";
|
||||
import { db } from "@/server/db";
|
||||
import {
|
||||
@@ -108,6 +111,30 @@ export interface EntryFacets {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a local link for a given file link if mirroring is enabled and the file exists.
|
||||
*/
|
||||
function resolveLocalLink(fileLink: string): string | null {
|
||||
let localPath: string | null = null;
|
||||
|
||||
const zxdbPrefix = env.ZXDB_FILE_PREFIX || "/zxdb/sinclair/";
|
||||
const wosPrefix = env.WOS_FILE_PREFIX || "/pub/sinclair/";
|
||||
|
||||
if (fileLink.startsWith(zxdbPrefix) && env.ZXDB_LOCAL_FILEPATH) {
|
||||
const sub = fileLink.slice(zxdbPrefix.replace(/\/$/, "").length);
|
||||
localPath = path.join(env.ZXDB_LOCAL_FILEPATH, sub);
|
||||
} else if (fileLink.startsWith(wosPrefix) && env.WOS_LOCAL_FILEPATH) {
|
||||
const sub = fileLink.slice(wosPrefix.replace(/\/$/, "").length);
|
||||
localPath = path.join(env.WOS_LOCAL_FILEPATH, sub);
|
||||
}
|
||||
|
||||
if (localPath && fs.existsSync(localPath)) {
|
||||
return localPath;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function buildEntrySearchUnion(pattern: string, scope: EntrySearchScope) {
|
||||
const parts: Array<ReturnType<typeof sql>> = [
|
||||
sql`select ${searchByTitles.entryId} as entry_id from ${searchByTitles} where lower(${searchByTitles.entryTitle}) like ${pattern}`,
|
||||
@@ -479,6 +506,7 @@ export interface EntryDetail {
|
||||
case: { id: string | null; name: string | null };
|
||||
year: number | null;
|
||||
releaseSeq: number;
|
||||
localLink?: string | null;
|
||||
}[];
|
||||
releases?: {
|
||||
releaseSeq: number;
|
||||
@@ -501,6 +529,7 @@ export interface EntryDetail {
|
||||
source: { id: string | null; name: string | null };
|
||||
case: { id: string | null; name: string | null };
|
||||
year: number | null;
|
||||
localLink?: string | null;
|
||||
}[];
|
||||
}[];
|
||||
// Additional relationships surfaced on the entry detail page
|
||||
@@ -710,6 +739,7 @@ export async function getEntryById(id: number): Promise<EntryDetail | null> {
|
||||
source: { id: (d.sourceId) ?? null, name: (d.sourceName) ?? null },
|
||||
case: { id: (d.caseId) ?? null, name: (d.caseName) ?? null },
|
||||
year: d.year != null ? Number(d.year) : null,
|
||||
localLink: resolveLocalLink(d.link),
|
||||
})),
|
||||
}));
|
||||
|
||||
@@ -1148,6 +1178,7 @@ export async function getEntryById(id: number): Promise<EntryDetail | null> {
|
||||
case: { id: (d.caseId) ?? null, name: (d.caseName) ?? null },
|
||||
year: d.year != null ? Number(d.year) : null,
|
||||
releaseSeq: Number(d.releaseSeq),
|
||||
localLink: resolveLocalLink(d.link),
|
||||
})),
|
||||
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 } })),
|
||||
@@ -2104,6 +2135,7 @@ export interface ReleaseDetail {
|
||||
source: { id: string | null; name: string | null };
|
||||
case: { id: string | null; name: string | null };
|
||||
year: number | null;
|
||||
localLink?: string | null;
|
||||
}>;
|
||||
scraps: Array<{
|
||||
id: number;
|
||||
@@ -2119,6 +2151,7 @@ export interface ReleaseDetail {
|
||||
source: { id: string | null; name: string | null };
|
||||
case: { id: string | null; name: string | null };
|
||||
year: number | null;
|
||||
localLink?: string | null;
|
||||
}>;
|
||||
files: Array<{
|
||||
id: number;
|
||||
@@ -2371,6 +2404,7 @@ export async function getReleaseDetail(entryId: number, releaseSeq: number): Pro
|
||||
source: { id: d.sourceId ?? null, name: d.sourceName ?? null },
|
||||
case: { id: d.caseId ?? null, name: d.caseName ?? null },
|
||||
year: d.year != null ? Number(d.year) : null,
|
||||
localLink: resolveLocalLink(d.link),
|
||||
})),
|
||||
scraps: (scrapRows as ScrapRow[]).map((s) => ({
|
||||
id: Number(s.id),
|
||||
@@ -2386,6 +2420,7 @@ export async function getReleaseDetail(entryId: number, releaseSeq: number): Pro
|
||||
source: { id: s.sourceId ?? null, name: s.sourceName ?? null },
|
||||
case: { id: s.caseId ?? null, name: s.caseName ?? null },
|
||||
year: s.year != null ? Number(s.year) : null,
|
||||
localLink: s.link ? resolveLocalLink(s.link) : null,
|
||||
})),
|
||||
files: fileRows.map((f) => ({
|
||||
id: f.id,
|
||||
|
||||
Reference in New Issue
Block a user