mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
[scripts] Write pnpm overrides for pnpm projects in pack/patch helpers (#94747)
This commit is contained in:
@@ -157,6 +157,7 @@
|
||||
"@types/html-validator": "5.0.3",
|
||||
"@types/http-proxy": "1.17.17",
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/js-yaml": "4.0.9",
|
||||
"@types/node": "20.17.6",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "19.2.10",
|
||||
@@ -226,6 +227,7 @@
|
||||
"jest-extended": "4.0.2",
|
||||
"jest-junit": "16.0.0",
|
||||
"jest-snapshot": "30.0.0-alpha.6",
|
||||
"js-yaml": "4.2.0",
|
||||
"json5": "2.2.3",
|
||||
"kleur": "^4.1.0",
|
||||
"ky": "0.19.1",
|
||||
|
||||
Generated
+6
@@ -216,6 +216,9 @@ importers:
|
||||
'@types/jest':
|
||||
specifier: 29.5.5
|
||||
version: 29.5.5
|
||||
'@types/js-yaml':
|
||||
specifier: 4.0.9
|
||||
version: 4.0.9
|
||||
'@types/node':
|
||||
specifier: 20.17.6
|
||||
version: 20.17.6(patch_hash=9c31d25336aea4076b3cb942c35e59fd160c540947f01ea455a060367153f9fd)
|
||||
@@ -423,6 +426,9 @@ importers:
|
||||
jest-snapshot:
|
||||
specifier: 30.0.0-alpha.6
|
||||
version: 30.0.0-alpha.6
|
||||
js-yaml:
|
||||
specifier: 4.2.0
|
||||
version: 4.2.0
|
||||
json5:
|
||||
specifier: 2.2.3
|
||||
version: 2.2.3
|
||||
|
||||
@@ -22,6 +22,7 @@ export interface PackageJson {
|
||||
peerDependencies?: Record<string, string>
|
||||
overrides?: Record<string, string>
|
||||
resolutions?: Record<string, string>
|
||||
pnpm?: { overrides?: Record<string, string>; [key: string]: unknown }
|
||||
workspaces?: string[] | { packages: string[] }
|
||||
[key: string]: unknown
|
||||
}
|
||||
@@ -37,9 +38,26 @@ export default async function patchPackageJson(
|
||||
): Promise<string> {
|
||||
try {
|
||||
const packageJsonPath = await findPackageJsonPath(targetProjectPath)
|
||||
const workspaceRoot = path.dirname(packageJsonPath)
|
||||
const packageJsonValue = await readJsonValue(packageJsonPath)
|
||||
await patchWorkspacePackageJsonMap(paths, packageJsonValue)
|
||||
const overrides = await patchWorkspacePackageJsonMap(
|
||||
paths,
|
||||
packageJsonValue
|
||||
)
|
||||
await writeJsonValue(packageJsonPath, packageJsonValue)
|
||||
// Also mirror overrides into pnpm-workspace.yaml so pnpm v11+ picks them
|
||||
// up. We don't try to detect the pnpm version — pnpm v10 reads
|
||||
// `pnpm.overrides` (written above) and pnpm v11+ reads
|
||||
// `pnpm-workspace.yaml#overrides`. To avoid dropping a pnpm-workspace.yaml
|
||||
// into non-pnpm projects, we only write the file if it already exists or
|
||||
// if a `pnpm-lock.yaml` indicates this is a pnpm project. See
|
||||
// https://pnpm.io/settings and https://github.com/pnpm/pnpm/issues/11536.
|
||||
if (await shouldWritePnpmWorkspace(workspaceRoot)) {
|
||||
await mergePnpmWorkspaceOverrides(
|
||||
workspaceRoot,
|
||||
Object.fromEntries(overrides)
|
||||
)
|
||||
}
|
||||
|
||||
return packageJsonPath
|
||||
} catch (error) {
|
||||
@@ -80,7 +98,7 @@ async function writeJsonValue(
|
||||
async function patchWorkspacePackageJsonMap(
|
||||
paths: DependencyPaths,
|
||||
packageJsonMap: PackageJson
|
||||
): Promise<PackageJson> {
|
||||
): Promise<[string, string][]> {
|
||||
const nextPeerDeps = await getNextPeerDeps()
|
||||
|
||||
const overrides: [string, string][] = [
|
||||
@@ -101,6 +119,12 @@ async function patchWorkspacePackageJsonMap(
|
||||
packageJsonMap.resolutions = packageJsonMap.resolutions || {}
|
||||
insertMapEntries(packageJsonMap.resolutions, overrides)
|
||||
|
||||
// pnpm v10 and below read `pnpm.overrides` from package.json.
|
||||
// pnpm v11+ reads `pnpm-workspace.yaml#overrides` (written separately).
|
||||
packageJsonMap.pnpm = packageJsonMap.pnpm || {}
|
||||
packageJsonMap.pnpm.overrides = packageJsonMap.pnpm.overrides || {}
|
||||
insertMapEntries(packageJsonMap.pnpm.overrides, overrides)
|
||||
|
||||
// Add @next/swc to dependencies
|
||||
packageJsonMap.dependencies = packageJsonMap.dependencies || {}
|
||||
insertMapEntries(packageJsonMap.dependencies, [
|
||||
@@ -110,7 +134,7 @@ async function patchWorkspacePackageJsonMap(
|
||||
// Update direct dependencies to match overrides
|
||||
updateMapEntriesIfExists(packageJsonMap.dependencies, overrides)
|
||||
|
||||
return packageJsonMap
|
||||
return overrides
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,6 +166,39 @@ async function getNextPeerDeps(): Promise<NextPeerDeps> {
|
||||
}
|
||||
}
|
||||
|
||||
async function shouldWritePnpmWorkspace(
|
||||
workspaceRoot: string
|
||||
): Promise<boolean> {
|
||||
return (
|
||||
(await fileExists(path.join(workspaceRoot, 'pnpm-workspace.yaml'))) ||
|
||||
(await fileExists(path.join(workspaceRoot, 'pnpm-lock.yaml')))
|
||||
)
|
||||
}
|
||||
|
||||
async function mergePnpmWorkspaceOverrides(
|
||||
workspaceRoot: string,
|
||||
overrides: Record<string, string>
|
||||
): Promise<void> {
|
||||
const yaml = await import('js-yaml')
|
||||
const filePath = path.join(workspaceRoot, 'pnpm-workspace.yaml')
|
||||
|
||||
let doc: Record<string, unknown> = {}
|
||||
if (await fileExists(filePath)) {
|
||||
const parsed = yaml.load(await fs.readFile(filePath, 'utf8'))
|
||||
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
||||
doc = parsed as Record<string, unknown>
|
||||
}
|
||||
}
|
||||
|
||||
const existing =
|
||||
doc.overrides && typeof doc.overrides === 'object'
|
||||
? (doc.overrides as Record<string, string>)
|
||||
: {}
|
||||
doc.overrides = { ...existing, ...overrides }
|
||||
|
||||
await fs.writeFile(filePath, yaml.dump(doc))
|
||||
}
|
||||
|
||||
function insertMapEntries(
|
||||
map: Record<string, string>,
|
||||
entries: [string, string][]
|
||||
|
||||
@@ -2,6 +2,7 @@ import { execSync } from 'node:child_process'
|
||||
import fs from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import { parseArgs } from 'node:util'
|
||||
import yaml from 'js-yaml'
|
||||
|
||||
const BASE_URL = 'https://vercel-packages.vercel.app/next/commits'
|
||||
|
||||
@@ -161,9 +162,8 @@ async function findWorkspaceRoot(projectPath) {
|
||||
|
||||
async function patchPackageJson(projectPath, tarballUrls) {
|
||||
const root = await findWorkspaceRoot(projectPath)
|
||||
const packageJsonPath = root
|
||||
? path.join(root, 'package.json')
|
||||
: path.join(projectPath, 'package.json')
|
||||
const workspaceRoot = root ?? projectPath
|
||||
const packageJsonPath = path.join(workspaceRoot, 'package.json')
|
||||
|
||||
if (!(await fileExists(packageJsonPath))) {
|
||||
console.error(`Error: package.json not found at ${packageJsonPath}`)
|
||||
@@ -175,18 +175,27 @@ async function patchPackageJson(projectPath, tarballUrls) {
|
||||
|
||||
const entries = Array.from(tarballUrls.entries())
|
||||
|
||||
// npm/pnpm overrides
|
||||
// npm uses top-level `overrides`
|
||||
pkg.overrides = pkg.overrides || {}
|
||||
for (const [name, url] of entries) {
|
||||
pkg.overrides[name] = url
|
||||
}
|
||||
|
||||
// yarn resolutions
|
||||
// yarn uses top-level `resolutions`
|
||||
pkg.resolutions = pkg.resolutions || {}
|
||||
for (const [name, url] of entries) {
|
||||
pkg.resolutions[name] = url
|
||||
}
|
||||
|
||||
// pnpm v10 and below read `pnpm.overrides` from package.json.
|
||||
// pnpm v11+ reads `pnpm-workspace.yaml#overrides` (handled below). See
|
||||
// https://pnpm.io/settings and https://github.com/pnpm/pnpm/issues/11536.
|
||||
pkg.pnpm = pkg.pnpm || {}
|
||||
pkg.pnpm.overrides = pkg.pnpm.overrides || {}
|
||||
for (const [name, url] of entries) {
|
||||
pkg.pnpm.overrides[name] = url
|
||||
}
|
||||
|
||||
// Add @next/swc-linux-x64-gnu to dependencies
|
||||
pkg.dependencies = pkg.dependencies || {}
|
||||
pkg.dependencies['@next/swc-linux-x64-gnu'] = tarballUrls.get(
|
||||
@@ -195,6 +204,16 @@ async function patchPackageJson(projectPath, tarballUrls) {
|
||||
|
||||
await fs.writeFile(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n')
|
||||
|
||||
// Only touch pnpm-workspace.yaml if it already exists (merge into it) or if
|
||||
// a pnpm-lock.yaml indicates this is a pnpm project — avoids dropping a
|
||||
// pnpm-workspace.yaml into non-pnpm projects.
|
||||
if (await shouldWritePnpmWorkspace(workspaceRoot)) {
|
||||
await mergePnpmWorkspaceOverrides(
|
||||
workspaceRoot,
|
||||
Object.fromEntries(entries)
|
||||
)
|
||||
}
|
||||
|
||||
console.log(`Patched ${packageJsonPath}`)
|
||||
console.log('Packages overridden:')
|
||||
for (const [name, url] of entries) {
|
||||
@@ -204,6 +223,29 @@ async function patchPackageJson(projectPath, tarballUrls) {
|
||||
return packageJsonPath
|
||||
}
|
||||
|
||||
async function shouldWritePnpmWorkspace(workspaceRoot) {
|
||||
return (
|
||||
(await fileExists(path.join(workspaceRoot, 'pnpm-workspace.yaml'))) ||
|
||||
(await fileExists(path.join(workspaceRoot, 'pnpm-lock.yaml')))
|
||||
)
|
||||
}
|
||||
|
||||
async function mergePnpmWorkspaceOverrides(workspaceRoot, overrides) {
|
||||
const filePath = path.join(workspaceRoot, 'pnpm-workspace.yaml')
|
||||
|
||||
let doc = {}
|
||||
if (await fileExists(filePath)) {
|
||||
const parsed = yaml.load(await fs.readFile(filePath, 'utf8'))
|
||||
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
||||
doc = parsed
|
||||
}
|
||||
}
|
||||
|
||||
doc.overrides = { ...(doc.overrides ?? {}), ...overrides }
|
||||
|
||||
await fs.writeFile(filePath, yaml.dump(doc))
|
||||
}
|
||||
|
||||
// --- Main ---
|
||||
|
||||
async function main() {
|
||||
|
||||
Reference in New Issue
Block a user