mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-06 07:12:12 +03:00
fix(auto-update): skip synthetic Next.js standalone package.json without name field in resolveProjectRoot (#8956) (#9354)
A Next.js standalone build writes a synthetic .build/next/package.json
({"type":"commonjs"}) that lacks a "name" field. The resolveProjectRoot()
walk-up was stopping at this marker instead of continuing to the real repo
root, making PROJECT_ROOT point at .build/next where no .git exists, which
caused the source-mode validation to report "Not a git repository."
Fix: only accept a package.json as a project-root marker when its parsed
content has a non-empty "name" field. Keep .git as a hard marker.
Add isValidPackageMarker() helper for testability.
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
5e344a3a99
commit
9e3126828e
1
changelog.d/fixes/8956-fix.plan.md
Normal file
1
changelog.d/fixes/8956-fix.plan.md
Normal file
@@ -0,0 +1 @@
|
||||
- fix(auto-update): skip synthetic Next.js standalone package.json without `name` field in resolveProjectRoot (#8956)
|
||||
@@ -1,5 +1,5 @@
|
||||
import { execFile, spawn } from "node:child_process";
|
||||
import { closeSync, mkdirSync, openSync, existsSync } from "node:fs";
|
||||
import { closeSync, mkdirSync, openSync, existsSync, readFileSync } from "node:fs";
|
||||
import { access } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
@@ -7,15 +7,36 @@ import { homedir } from "node:os";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
/**
|
||||
* Check whether a directory's package.json is a valid project-root marker by
|
||||
* requiring a non-empty `name` field. The Next.js standalone build writes a
|
||||
* synthetic `.build/next/package.json` = `{"type":"commonjs"}` that should not
|
||||
* be mistaken for the real project root.
|
||||
*
|
||||
* Swallows read / parse errors (missing file, invalid JSON) and returns false
|
||||
* so the walk-up continues.
|
||||
*
|
||||
* @internal — exported for testability.
|
||||
*/
|
||||
export function isValidPackageMarker(dir: string): boolean {
|
||||
try {
|
||||
const content = readFileSync(path.join(dir, "package.json"), "utf-8");
|
||||
const pkg = JSON.parse(content);
|
||||
return typeof pkg.name === "string" && pkg.name.length > 0;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal — exported for testability. */
|
||||
export function resolveProjectRoot(
|
||||
fallback: string,
|
||||
startDir: string = typeof __dirname !== "undefined" ? __dirname : process.cwd()
|
||||
): string {
|
||||
const markers = ["package.json", ".git"] as const;
|
||||
let dir = path.resolve(startDir);
|
||||
while (true) {
|
||||
if (markers.some((m) => existsSync(path.join(dir, m)))) return dir;
|
||||
if (existsSync(path.join(dir, ".git"))) return dir;
|
||||
if (existsSync(path.join(dir, "package.json")) && isValidPackageMarker(dir)) return dir;
|
||||
const parent = path.dirname(dir);
|
||||
if (parent === dir) break;
|
||||
dir = parent;
|
||||
|
||||
@@ -404,7 +404,7 @@ test("resolveProjectRoot walks up from start dir to nearest package.json or .git
|
||||
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-root-"));
|
||||
const subDir = path.join(tempRoot, "sub", "deep");
|
||||
fs.mkdirSync(subDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(tempRoot, "package.json"), "{}");
|
||||
fs.writeFileSync(path.join(tempRoot, "package.json"), JSON.stringify({ name: "omniroute" }));
|
||||
|
||||
try {
|
||||
// Walking up from a deep subdir that does not have markers must find the real root.
|
||||
|
||||
Reference in New Issue
Block a user