Fix production build: npm registry flakiness, stray package-lock.json dir, TS error

- registry.npmjs.org was intermittently ETIMEDOUT mid-download from this
  host; switched to registry.npmmirror.com (also raised npm's own retry
  budget as a second line of defense).
- frontend/package-lock.json on disk was actually an empty directory
  (untracked, root-owned — a stray artifact, likely from an old bad
  bind-mount), which broke `COPY . .` once npm install got past it.
- documents/page.tsx had a real type error (selectedItem.file narrowing
  didn't survive into the .map() closure) that `next dev` never
  surfaced but `next build`'s stricter check does — fixed by hoisting
  the narrowed array into selectedFiles once instead of re-narrowing
  selectedItem.file at each use.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gh2UXUQUVBWroWEnn1FLFG
This commit is contained in:
ogrechkoandClaude Sonnet 5 committed 2026-09-03 05:18:49 +00:00
1 parent 2cb2bc0729
commit ea6c43f5af
2 files changed
+14 -6

No files matched your search

+8 -1
View File
@@ -9,7 +9,14 @@ WORKDIR /app
ENV NODE_OPTIONS=--dns-result-order=ipv4first ENV NODE_OPTIONS=--dns-result-order=ipv4first
COPY package.json package-lock.json* ./ COPY package.json package-lock.json* ./
RUN npm install # registry.npmjs.org itself is unreliable from this host (mid-download
# stalls even with aggressive npm retries) — route through npmmirror.com
# instead, which is consistently reachable from this network.
RUN npm config set registry https://registry.npmmirror.com && \
npm config set fetch-retries 8 && \
npm config set fetch-retry-mintimeout 20000 && \
npm config set fetch-retry-maxtimeout 120000 && \
npm install
COPY . . COPY . .
RUN npm run build RUN npm run build
+6 -5
View File
@@ -47,6 +47,7 @@ export default async function DocumentsPage({
// Логика определения конкретного файла для отображения // Логика определения конкретного файла для отображения
let fileForLink: string | null = null; let fileForLink: string | null = null;
let previewUrl: string | null = null; let previewUrl: string | null = null;
const selectedFiles: string[] | null = Array.isArray(selectedItem?.file) ? selectedItem.file : null;
if (selectedItem?.file) { if (selectedItem?.file) {
if (Array.isArray(selectedItem.file)) { if (Array.isArray(selectedItem.file)) {
@@ -125,16 +126,16 @@ export default async function DocumentsPage({
<h2>{selectedItem?.title ?? "Документ не выбран"}</h2> <h2>{selectedItem?.title ?? "Документ не выбран"}</h2>
{/* Вывод списка кнопок, если файлов несколько */} {/* Вывод списка кнопок, если файлов несколько */}
{selectedItem?.file && Array.isArray(selectedItem.file) && selectedItem.file.length > 1 && ( {selectedFiles && selectedFiles.length > 1 && (
<div style={{ display: "flex", gap: "8px", flexWrap: "wrap", marginTop: "12px" }}> <div style={{ display: "flex", gap: "8px", flexWrap: "wrap", marginTop: "12px" }}>
{selectedItem.file.map((fileName, idx) => { {selectedFiles.map((fileName, idx) => {
const validCurrentIndex = selectedIndex < selectedItem.file.length ? selectedIndex : 0; const validCurrentIndex = selectedIndex < selectedFiles.length ? selectedIndex : 0;
const isActive = validCurrentIndex === idx; const isActive = validCurrentIndex === idx;
return ( return (
<Link <Link
key={fileName} key={fileName}
href={`/documents?doc=${selectedItem.id}&fileIndex=${idx}`} href={`/documents?doc=${selectedItem?.id}&fileIndex=${idx}`}
className={`documents-link documents-link--button ${ className={`documents-link documents-link--button ${
isActive ? "documents-link--active" : "" isActive ? "documents-link--active" : ""
}`} }`}