tools/patch-nextjs.js (100 lines of code) (raw):

/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable no-console */ const { dirname, join } = require('path'); const { writeFileSync, readFileSync } = require('fs'); /** * Replace content in a node module file * @param {string} moduleName - name of the module * @param {string} relativeFilePath - the relative path to the file inside the module * @param {RegExp} searchPattern - regular expression to search for the content to replace * @param {string} replacement - the content to replace with */ function replaceContentInNodeModule( next, relativeFilePath, searchPattern, replacement, ) { const modulePath = dirname( require.resolve(`../node_modules/${next}/package.json`), ); const targetFilePath = join(modulePath, relativeFilePath); let updatedContent; try { const fileContent = readFileSync(targetFilePath, 'utf-8'); updatedContent = fileContent.replaceAll(searchPattern, replacement); } catch (e) { console.error(`Error reading file: ${targetFilePath}`, e); throw e; } try { writeFileSync(targetFilePath, updatedContent, 'utf-8'); } catch (e) { console.error(`Error writing updates to file: ${targetFilePath}`, e); throw e; } console.log(`Content replaced in file: ${targetFilePath}`); } replaceContentInNodeModule( 'next', 'dist/shared/lib/router/utils/path-has-prefix.js', 'pathname === prefix', 'pathname == prefix', ); replaceContentInNodeModule( 'next', 'dist/server/config.js', 'if (typeof result.basePath !== "string")', 'if (false)', ); replaceContentInNodeModule( 'next', 'dist/server/config.js', 'if (!result.basePath.startsWith("/"))', 'if (false)', ); replaceContentInNodeModule( 'next', 'dist/build/webpack/loaders/next-font-loader/index.js', 'if (assetPrefix && !/^\\/|https?:\\/\\//.test(assetPrefix))', 'if (false)', ); replaceContentInNodeModule( 'next', 'dist/lib/load-custom-routes.js', 'if (config.basePath) {', 'if (config.basePath.toString()) {', ); replaceContentInNodeModule( 'next-auth', 'core/lib/callback-url.js', 'baseUrl: url.origin', `baseUrl: '' + url.origin + (process.env.APP_BASE_PATH || '')`, ); // Fix RxJs issue in innerFrom, when an observable is not recognized as an instance of Observable and throws an exception, // although it has lift and subscribe methods, therefore it should be considered as an Observable // as a workaround, here in the code is the factual replacement of "input instanceof Observable" with one-liner of "isObservable(input)" replaceContentInNodeModule( 'rxjs', 'dist/esm/internal/observable/innerFrom.js', 'if (input instanceof Observable) {', `if (!!input && (input instanceof Observable || (typeof input.lift === 'function' && typeof input.subscribe === 'function'))) {`, ); replaceContentInNodeModule( 'rxjs', 'dist/esm5/internal/observable/innerFrom.js', 'if (input instanceof Observable) {', `if (!!input && (input instanceof Observable || (typeof input.lift === 'function' && typeof input.subscribe === 'function'))) {`, ); replaceContentInNodeModule( 'rxjs', 'dist/cjs/internal/observable/innerFrom.js', 'if (input instanceof Observable_1.Observable) {', `if (!!input && (input instanceof Observable_1.Observable || (typeof input.lift === 'function' && typeof input.subscribe === 'function'))) {`, ); // Enable server-side debugging in Next.js, enable to set 0.0.0.0 as host replaceContentInNodeModule( 'next', 'dist/server/lib/utils.js', 'return debugPortStr ? parseInt(debugPortStr, 10) : 9229;', 'return debugPortStr ? debugPortStr : 9229;', ); replaceContentInNodeModule( 'next', 'dist/esm/server/lib/utils.js', 'return debugPortStr ? parseInt(debugPortStr, 10) : 9229;', 'return debugPortStr ? debugPortStr : 9229;', ); replaceContentInNodeModule( 'next', 'dist/cli/next-dev.js', 'NODE_OPTIONS = `${NODE_OPTIONS} --${nodeDebugType}=${(0, _utils.getDebugPort)() + 1}`;', "NODE_OPTIONS = `${NODE_OPTIONS} --${nodeDebugType}=${((str) => str.includes(':') ? str.replace(/(\\d+)$/, num => ++num) : ++str)(String((0, _utils.getDebugPort)()))}`;", );