diff --git a/packages/nextjs/src/config/util.ts b/packages/nextjs/src/config/util.ts index 4ec25dbf0e94..5f0990ac6829 100644 --- a/packages/nextjs/src/config/util.ts +++ b/packages/nextjs/src/config/util.ts @@ -22,12 +22,25 @@ export function getNextjsVersion(): string | undefined { return undefined; } +// Anchored at this package so `next` (a peer dependency) still resolves when the process cwd is not +// the Next.js project root, e.g. custom servers or monorepos started from the repo root. +let sdkRequire: NodeJS.Require; +/*! rollup-include-cjs-only */ +sdkRequire = createRequire(__filename); +/*! rollup-include-cjs-only-end */ +/*! rollup-include-esm-only */ +sdkRequire = createRequire(import.meta.url); +/*! rollup-include-esm-only-end */ + function resolveNextjsPackageJson(): string | undefined { - try { - return createRequire(`${process.cwd()}/`).resolve('next/package.json'); - } catch { - return undefined; + for (const nodeRequire of [createRequire(`${process.cwd()}/`), sdkRequire]) { + try { + return nodeRequire.resolve('next/package.json'); + } catch { + // try next + } } + return undefined; } /** diff --git a/packages/nextjs/test/config/util.test.ts b/packages/nextjs/test/config/util.test.ts index 01b5e59af28e..62632d4bc7aa 100644 --- a/packages/nextjs/test/config/util.test.ts +++ b/packages/nextjs/test/config/util.test.ts @@ -1,7 +1,25 @@ -import { afterEach, beforeEach, describe, expect, it } from 'vitest'; +import * as os from 'os'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import * as util from '../../src/config/util'; describe('util', () => { + describe('getNextjsVersion', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('returns the installed Next.js version', () => { + expect(util.getNextjsVersion()).toMatch(/^\d+\.\d+\.\d+/); + }); + + it('returns the installed Next.js version when cwd is not the project root', () => { + const expected = util.getNextjsVersion(); + vi.spyOn(process, 'cwd').mockReturnValue(os.tmpdir()); + + expect(util.getNextjsVersion()).toBe(expected); + }); + }); + describe('supportsProductionCompileHook', () => { describe('supported versions', () => { it('returns true for Next.js 15.4.1', () => {