// Product version — Task 1 of docs/superpowers/plans/2026-08-01-launch.md,
// per docs/superpowers/specs/2026-08-01-launch-design.md ("Version + update
// channel"). The ROOT package.json's "version" field is the single source
// of truth for the product's version — a release bump types "1.1.0" in
// exactly one place, never duplicated into server/web/site package.json
// files or a hardcoded string in code.
//
// Read via fs + a path resolved from this file's own location
// (import.meta.url), the same trick src/index.ts uses to find the repo-root
// .env regardless of the process's cwd — NOT an ESM JSON import
// (`import pkg from "../../package.json" with { type: "json" }`). That
// import-attribute syntax works on recent Node, but this file needs to
// behave identically under tsx (dev/npm run app), vitest (tests), and a
// plain `node` production run without depending on all three agreeing on
// JSON-import-attribute support — a plain readFileSync has no such
// ambiguity.

import { readFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

const serverSrcDir = path.dirname(fileURLToPath(import.meta.url));
// server/src/version.ts -> ../../package.json = repo root's package.json.
const rootPackageJsonPath = path.resolve(serverSrcDir, "../../package.json");

let cachedVersion: string | null = null;

/** The product version, read once (and cached — package.json cannot change
 *  underneath a running process) from the root package.json's "version"
 *  field. Falls back to "0.0.0" only if that field is somehow missing,
 *  rather than throwing and taking the whole app down over a version
 *  string. */
export function getVersion(): string {
  if (cachedVersion !== null) return cachedVersion;
  const raw = readFileSync(rootPackageJsonPath, "utf8");
  const pkg = JSON.parse(raw) as { version?: unknown };
  cachedVersion = typeof pkg.version === "string" && pkg.version.trim() !== "" ? pkg.version : "0.0.0";
  return cachedVersion;
}
