import { readFileSync, writeFileSync } from 'fs'; import { fileURLToPath } from 'url'; import { join, dirname } from 'path'; const __dirname = dirname(fileURLToPath(import.meta.url)); const foldsPath = join(__dirname, '../node_modules/folds/dist/index.js'); const foldsPkgPath = join(__dirname, '../node_modules/folds/package.json'); // Context lines around the target, not just the single `children: src(filled)` // expression, so a coincidental match elsewhere in the bundle (e.g. some other // `src(filled)` call) can't be mistaken for the Icon component we're patching. // This is still string matching, not an AST edit, but the extra context makes // an accidental match far less likely (Gitea #55). const original = [' ...props,', ' ref,', ' children: src(filled)', ' }'].join( '\n', ); const patched = [ ' ...props,', ' ref,', ' children: typeof src === "function" ? src(filled) : null', ' }', ].join('\n'); function foldsVersion() { try { return JSON.parse(readFileSync(foldsPkgPath, 'utf8')).version ?? 'unknown'; } catch { return 'unknown'; } } try { const content = readFileSync(foldsPath, 'utf8'); if (content.includes(patched)) { // Already patched (e.g. re-running postinstall, or a fresh checkout that // already has a patched node_modules cache) — no-op, exit 0. console.log('folds patch already applied.'); } else if (content.includes(original)) { writeFileSync(foldsPath, content.replace(original, patched), 'utf8'); console.log('Applied defensive Icon src guard to folds.'); } else { // Genuine "patch could not be applied" case: neither the original nor the // patched form was found, meaning folds changed the Icon implementation. // Fail loudly so the postinstall hook / CI breaks instead of silently // shipping an unpatched folds (which crashes at render with "src is not a // function"). See LOTUS_TODO.md "Dependencies / Build / Hygiene" for // context on why this is a direct node_modules patch rather than // patch-package. console.error('ERROR: folds Icon patch target not found.'); console.error(` folds version installed: ${foldsVersion()}`); console.error(` Expected to find (surrounding context):\n${original}`); console.error( ' folds likely changed its Icon implementation. Update the patch target ' + 'in scripts/patch-folds.mjs (see LOTUS_TODO -> "Dependencies / Build / Hygiene" ' + '-> patch-folds.mjs entry) before building.', ); process.exit(1); } } catch (e) { console.error('ERROR: Could not patch folds:', e.message); process.exit(1); }