cameras/next.config.ts
Michael Mainguy 10d08e3b87 Name cameras here, and rename them on the camera
Both of your cameras call themselves "I91ET", so the slimmed dashboard
showed two identical names.

- A nickname kept in the registry now wins wherever a camera is named:
  cards, camera page, live view and its window title, pop-outs and the
  recordings list. It survives a rescan, and clearing it falls back to
  the camera's own name, then its model.
- Rename on the camera page also writes the camera's own name and
  location over ONVIF SetScopes, so everything else on the network sees
  them. Since SetScopes replaces every configurable scope, the others are
  read and sent back untouched; the result is re-read from the camera and
  reported as applied or adjusted, and the change is audited.
- cameraName() lives in a client-safe module, because the registry is
  server-only and the dashboard names cameras in the browser.
- NEXT_DIST_DIR lets a build run while dev servers hold .next.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 07:42:28 -05:00

48 lines
2.2 KiB
TypeScript

import { realpathSync } from "node:fs";
import path from "node:path";
import type { NextConfig } from "next";
/**
* While onvif is linked to a local checkout outside this project (e.g. the fork, installed
* with `npm install ../onvif --no-save`), Turbopack only resolves files inside its root, so
* the root must contain both (Next docs, 03-api-reference/08-turbopack.md "Root directory").
* Returns undefined for a normal install, leaving the auto-detected root alone.
*/
function linkedPackagesRoot(project: string, packages: string[]): string | undefined {
let root = project;
for (const name of packages) {
let target: string;
try {
target = realpathSync(path.join(project, "node_modules", name));
} catch {
continue;
}
while (path.relative(root, target).startsWith("..")) root = path.dirname(root);
}
return root === project ? undefined : root;
}
const project = process.cwd();
const turbopackRoot = linkedPackagesRoot(project, ["onvif"]);
const nextConfig: NextConfig = {
// A build and a dev server sharing .next fight over it; NEXT_DIST_DIR lets a build run
// to one side while someone is working.
...(process.env.NEXT_DIST_DIR && { distDir: process.env.NEXT_DIST_DIR }),
// What gets published: a minimal server plus only the files it needs, so installing the
// package doesn't drag in Next and React (vrek iss-ej4ahga).
output: "standalone",
// Runtime data and the downloaded MediaMTX binary are not part of the app.
outputFileTracingExcludes: { "/*": ["bin/**/*", ".data/**/*", "node_modules/@img/**/*", "node_modules/sharp/**/*"] },
// next/image is unused, and leaving it on pulls sharp's platform binaries (tens of MB).
images: { unoptimized: true },
// onvif uses Node's dgram/os modules; load it with native require instead of bundling.
// onvif is bundled rather than listed in serverExternalPackages. Externalizing it made
// Turbopack emit require("onvif-<hash>") — a name that exists nowhere — because the
// dependency comes from a git URL, which broke the published package (vrek iss-9zcawn7).
// Bundled, discovery (dgram) and camera reads work from an installed copy.
...(turbopackRoot && { turbopack: { root: turbopackRoot } }),
};
export default nextConfig;