@@ -7,18 +7,7 @@ import type { BuildOptions } from "@opennextjs/aws/build/helper.js";
77import { build , Plugin } from "esbuild" ;
88
99import { Config } from "../config" ;
10- import { copyPackageCliFiles } from "./patches/investigated/copy-package-cli-files" ;
11- import { patchCache } from "./patches/investigated/patch-cache" ;
12- import { patchRequire } from "./patches/investigated/patch-require" ;
13- import { updateWebpackChunksFile } from "./patches/investigated/update-webpack-chunks-file" ;
14- import { inlineEvalManifest } from "./patches/to-investigate/inline-eval-manifest" ;
15- import { inlineMiddlewareManifestRequire } from "./patches/to-investigate/inline-middleware-manifest-require" ;
16- import { inlineNextRequire } from "./patches/to-investigate/inline-next-require" ;
17- import { patchExceptionBubbling } from "./patches/to-investigate/patch-exception-bubbling" ;
18- import { patchFindDir } from "./patches/to-investigate/patch-find-dir" ;
19- import { patchLoadInstrumentationModule } from "./patches/to-investigate/patch-load-instrumentation-module" ;
20- import { patchReadFile } from "./patches/to-investigate/patch-read-file" ;
21- import { patchWranglerDeps } from "./patches/to-investigate/wrangler-deps" ;
10+ import * as patches from "./patches" ;
2211import { copyPrerenderedRoutes } from "./utils" ;
2312
2413/** The dist directory of the Cloudflare adapter package */
@@ -31,7 +20,7 @@ export async function bundleServer(config: Config, openNextOptions: BuildOptions
3120 // Copy over prerendered assets (e.g. SSG routes)
3221 copyPrerenderedRoutes ( config ) ;
3322
34- copyPackageCliFiles ( packageDistDir , config , openNextOptions ) ;
23+ patches . copyPackageCliFiles ( packageDistDir , config , openNextOptions ) ;
3524
3625 const nextConfigStr =
3726 fs
@@ -40,8 +29,8 @@ export async function bundleServer(config: Config, openNextOptions: BuildOptions
4029
4130 console . log ( `\x1b[35m⚙️ Bundling the OpenNext server...\n\x1b[0m` ) ;
4231
43- patchWranglerDeps ( config ) ;
44- updateWebpackChunksFile ( config ) ;
32+ patches . patchWranglerDeps ( config ) ;
33+ patches . updateWebpackChunksFile ( config ) ;
4534
4635 const { appBuildOutputPath, appPath, outputDir, monorepoRoot } = openNextOptions ;
4736 const outputPath = path . join ( outputDir , "server-functions" , "default" ) ;
@@ -155,25 +144,35 @@ async function updateWorkerBundledCode(
155144 config : Config ,
156145 openNextOptions : BuildOptions
157146) : Promise < void > {
158- const originalCode = await readFile ( workerOutputFile , "utf8" ) ;
159-
160- let patchedCode = originalCode ;
161-
162- patchedCode = patchRequire ( patchedCode ) ;
163- patchedCode = patchReadFile ( patchedCode , config ) ;
164- patchedCode = inlineNextRequire ( patchedCode , config ) ;
165- patchedCode = patchFindDir ( patchedCode , config ) ;
166- patchedCode = inlineEvalManifest ( patchedCode , config ) ;
167- patchedCode = await patchCache ( patchedCode , openNextOptions ) ;
168- patchedCode = inlineMiddlewareManifestRequire ( patchedCode , config ) ;
169- patchedCode = patchExceptionBubbling ( patchedCode ) ;
170- patchedCode = patchLoadInstrumentationModule ( patchedCode ) ;
171-
172- patchedCode = patchedCode
173- // workers do not support dynamic require nor require.resolve
174- // TODO: implement for cf (possibly in @opennextjs/aws)
175- . replace ( "patchAsyncStorage();" , "//patchAsyncStorage();" )
176- . replace ( 'require.resolve("./cache.cjs")' , '"unused"' ) ;
147+ const code = await readFile ( workerOutputFile , "utf8" ) ;
148+
149+ const patchedCode = await patchCodeWithValidations ( code , [
150+ [ "require" , patches . patchRequire ] ,
151+ [ "`buildId` function" , ( code ) => patches . patchBuildId ( code , config ) ] ,
152+ [ "`loadManifest` function" , ( code ) => patches . patchLoadManifest ( code , config ) ] ,
153+ [ "next's require" , ( code ) => patches . inlineNextRequire ( code , config ) ] ,
154+ [ "`findDir` function" , ( code ) => patches . patchFindDir ( code , config ) ] ,
155+ [ "`evalManifest` function" , ( code ) => patches . inlineEvalManifest ( code , config ) ] ,
156+ [ "cacheHandler" , ( code ) => patches . patchCache ( code , openNextOptions ) ] ,
157+ [
158+ "'require(this.middlewareManifestPath)'" ,
159+ ( code ) => patches . inlineMiddlewareManifestRequire ( code , config ) ,
160+ ] ,
161+ [ "exception bubbling" , patches . patchExceptionBubbling ] ,
162+ [ "`loadInstrumentationModule` function" , patches . patchLoadInstrumentationModule ] ,
163+ [
164+ "`patchAsyncStorage` call" ,
165+ ( code ) =>
166+ code
167+ // TODO: implement for cf (possibly in @opennextjs/aws)
168+ . replace ( "patchAsyncStorage();" , "//patchAsyncStorage();" ) ,
169+ ] ,
170+ [
171+ "`require.resolve` call" ,
172+ // workers do not support dynamic require nor require.resolve
173+ ( code ) => code . replace ( 'require.resolve("./cache.cjs")' , '"unused"' ) ,
174+ ] ,
175+ ] ) ;
177176
178177 await writeFile ( workerOutputFile , patchedCode ) ;
179178}
@@ -192,3 +191,34 @@ function createFixRequiresESBuildPlugin(config: Config): Plugin {
192191 } ,
193192 } ;
194193}
194+
195+ /**
196+ * Applies multiple code patches in order to a given piece of code, at each step it validates that the code
197+ * has actually been patched/changed, if not an error is thrown
198+ *
199+ * @param code the code to apply the patches to
200+ * @param patches array of tuples, containing a string indicating the target of the patching (for logging) and
201+ * a patching function that takes a string (pre-patch code) and returns a string (post-patch code)
202+ * @returns the patched code
203+ */
204+ async function patchCodeWithValidations (
205+ code : string ,
206+ patches : [ string , ( code : string ) => string | Promise < string > ] [ ]
207+ ) : Promise < string > {
208+ console . log ( `Applying code patches:` ) ;
209+ let patchedCode = code ;
210+
211+ for ( const [ target , patchFunction ] of patches ) {
212+ console . log ( ` - patching ${ target } ` ) ;
213+
214+ const prePatchCode = patchedCode ;
215+ patchedCode = await patchFunction ( patchedCode ) ;
216+
217+ if ( prePatchCode === patchedCode ) {
218+ throw new Error ( `Failed to patch ${ target } ` ) ;
219+ }
220+ }
221+
222+ console . log ( `All ${ patches . length } patches applied\n` ) ;
223+ return patchedCode ;
224+ }
0 commit comments