wwwfiberdirekt/nuclear_fix.py

191 lines
6.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Nuclear fix: make every Payload-touching page force-dynamic,
remove all generateStaticParams from those pages,
and reduce Next.js build workers to prevent DB pool exhaustion.
"""
import os, re, glob
def read(path):
with open(path, 'r') as f: return f.read()
def write(path, content):
with open(path, 'w') as f: f.write(content)
def remove_generate_static_params(content):
"""Remove the entire generateStaticParams function from a file."""
# Match: export async function generateStaticParams() { ... }
# Using a simple brace-counting approach
pattern = r'export async function generateStaticParams\(\)'
match = re.search(pattern, content)
if not match:
return content, False
start = match.start()
# Find the opening brace
brace_start = content.index('{', match.end())
depth = 0
i = brace_start
while i < len(content):
if content[i] == '{':
depth += 1
elif content[i] == '}':
depth -= 1
if depth == 0:
end = i + 1
break
i += 1
# Remove the function (and any leading newlines before it)
before = content[:start].rstrip('\n') + '\n'
after = content[end:].lstrip('\n')
return before + after, True
def ensure_force_dynamic(content):
"""Add export const dynamic = 'force-dynamic' if not present."""
if "dynamic = 'force-dynamic'" in content or 'dynamic = "force-dynamic"' in content:
return content, False
# Remove conflicting revalidate settings
content = re.sub(r"export const revalidate = \d+\n?", '', content)
# Add after the last import line
lines = content.split('\n')
last_import = 0
for i, line in enumerate(lines):
if line.startswith('import '):
last_import = i
lines.insert(last_import + 1, '')
lines.insert(last_import + 2, "export const dynamic = 'force-dynamic'")
lines.insert(last_import + 3, 'export const dynamicParams = true')
return '\n'.join(lines), True
# ── Find all page.tsx files that use Payload ──────────────────────────────
print("=== Nuclear Payload Build Fix ===\n")
page_files = glob.glob('src/app/**/page.tsx', recursive=True)
print(f"Found {len(page_files)} page files total\n")
payload_pages = []
for path in page_files:
content = read(path)
if 'payload-config' in content or 'getPayload' in content or 'getCachedGlobal' in content:
payload_pages.append(path)
print(f"{len(payload_pages)} pages use Payload:\n")
for p in payload_pages:
print(f" {p}")
print()
# ── Fix each Payload page ─────────────────────────────────────────────────
for path in payload_pages:
content = read(path)
changed = False
# Remove generateStaticParams
new_content, removed = remove_generate_static_params(content)
if removed:
print(f" ✓ Removed generateStaticParams: {path}")
changed = True
content = new_content
# Ensure force-dynamic
new_content, added = ensure_force_dynamic(content)
if added:
print(f" ✓ Added force-dynamic: {path}")
changed = True
content = new_content
if changed:
write(path, content)
else:
print(f" - Already OK: {path}")
# ── Update next.config to limit workers ──────────────────────────────────
print("\n→ Looking for next.config...")
next_configs = glob.glob('next.config.*')
if next_configs:
nc_path = next_configs[0]
nc = read(nc_path)
if 'workerThreads' not in nc and 'cpus' not in nc:
# Add experimental config to limit parallel workers
nc = nc.replace(
'const nextConfig',
'/** @type {import("next").NextConfig} */\nconst nextConfig'
) if '/** @type' not in nc else nc
# Insert experimental block before the closing of nextConfig object
if 'experimental:' not in nc:
nc = re.sub(
r'(const nextConfig\s*=\s*\{)',
r'\1\n experimental: {\n workerThreads: false,\n cpus: 1,\n },',
nc
)
write(nc_path, nc)
print(f" ✓ Limited build workers in {nc_path}")
else:
print(f" - experimental block already exists in {nc_path}, add cpus: 1 manually")
else:
print(f" - Worker limits already set in {nc_path}")
else:
# Create a basic next.config.js
print(" - No next.config found, creating next.config.js with worker limit...")
# Try to find and read existing config
existing = None
for name in ['next.config.js', 'next.config.mjs', 'next.config.ts']:
if os.path.exists(name):
existing = name
break
if not existing:
# Check if there's a withPayload wrapper we need to preserve
# Write a minimal config
config_content = '''import { withPayload } from '@payloadcms/next'
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
workerThreads: false,
cpus: 1,
},
}
export default withPayload(nextConfig)
'''
write('next.config.js', config_content)
print(" ✓ Created next.config.js")
# ── Verify generateStaticParams is gone from all payload pages ────────────
print("\n→ Verifying...")
remaining = []
for path in payload_pages:
content = read(path)
if 'generateStaticParams' in content:
remaining.append(path)
if remaining:
print("\n ⚠ generateStaticParams still present in:")
for p in remaining:
print(f" {p}")
print(" These need manual removal.")
else:
print(" ✓ No generateStaticParams remaining in Payload pages")
# ── Check for any other pages with generateStaticParams ───────────────────
all_with_gsp = []
for path in page_files:
content = read(path)
if 'generateStaticParams' in content and path not in payload_pages:
all_with_gsp.append(path)
if all_with_gsp:
print(f"\n Non-Payload pages with generateStaticParams (likely fine):")
for p in all_with_gsp:
print(f" {p}")
print("\n=== Done! ===")
print("\nNow run:")
print(" rm -rf .next && npm run build")