@opennextjs/cloudflare 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/build/bundle-server.d.ts +1 -1
- package/dist/cli/build/bundle-server.js +10 -7
- package/dist/cli/build/open-next/compile-init.js +21 -0
- package/dist/cli/build/patches/plugins/next-server.spec.js +118 -331
- package/dist/cli/build/patches/plugins/open-next.js +0 -1
- package/dist/cli/build/patches/plugins/res-revalidate.spec.js +22 -64
- package/dist/cli/build/patches/plugins/use-cache.spec.js +22 -77
- package/dist/cli/build/{patches/investigated → utils}/copy-package-cli-files.js +1 -1
- package/dist/cli/build/utils/index.d.ts +1 -1
- package/dist/cli/build/utils/index.js +1 -1
- package/dist/cli/build/utils/test-patch.d.ts +9 -0
- package/dist/cli/build/utils/test-patch.js +14 -0
- package/dist/cli/templates/init.d.ts +17 -0
- package/dist/cli/templates/init.js +76 -0
- package/dist/cli/templates/worker.js +2 -4
- package/package.json +4 -1
- package/dist/cli/build/patches/index.d.ts +0 -1
- package/dist/cli/build/patches/index.js +0 -1
- package/dist/cli/build/patches/investigated/index.d.ts +0 -2
- package/dist/cli/build/patches/investigated/index.js +0 -2
- package/dist/cli/build/patches/investigated/patch-require.d.ts +0 -4
- package/dist/cli/build/patches/investigated/patch-require.js +0 -6
- package/dist/cli/build/utils/apply-patches.d.ts +0 -12
- package/dist/cli/build/utils/apply-patches.js +0 -23
- /package/dist/cli/build/{patches/investigated → utils}/copy-package-cli-files.d.ts +0 -0
|
@@ -4,7 +4,7 @@ import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
|
|
|
4
4
|
*/
|
|
5
5
|
export declare function bundleServer(buildOpts: BuildOptions): Promise<void>;
|
|
6
6
|
/**
|
|
7
|
-
* This function
|
|
7
|
+
* This function apply updates to the bundled code.
|
|
8
8
|
*/
|
|
9
9
|
export declare function updateWorkerBundledCode(workerOutputFile: string): Promise<void>;
|
|
10
10
|
/**
|
|
@@ -8,7 +8,6 @@ import { build } from "esbuild";
|
|
|
8
8
|
import { getOpenNextConfig } from "../../api/config.js";
|
|
9
9
|
import { patchVercelOgLibrary } from "./patches/ast/patch-vercel-og-library.js";
|
|
10
10
|
import { patchWebpackRuntime } from "./patches/ast/webpack-runtime.js";
|
|
11
|
-
import * as patches from "./patches/index.js";
|
|
12
11
|
import { inlineDynamicRequires } from "./patches/plugins/dynamic-requires.js";
|
|
13
12
|
import { inlineFindDir } from "./patches/plugins/find-dir.js";
|
|
14
13
|
import { patchInstrumentation } from "./patches/plugins/instrumentation.js";
|
|
@@ -21,7 +20,7 @@ import { patchDepdDeprecations } from "./patches/plugins/patch-depd-deprecations
|
|
|
21
20
|
import { fixRequire } from "./patches/plugins/require.js";
|
|
22
21
|
import { shimRequireHook } from "./patches/plugins/require-hook.js";
|
|
23
22
|
import { setWranglerExternal } from "./patches/plugins/wrangler-external.js";
|
|
24
|
-
import { needsExperimentalReact, normalizePath
|
|
23
|
+
import { copyPackageCliFiles, needsExperimentalReact, normalizePath } from "./utils/index.js";
|
|
25
24
|
/** The dist directory of the Cloudflare adapter package */
|
|
26
25
|
const packageDistDir = path.join(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
27
26
|
/**
|
|
@@ -41,8 +40,8 @@ const optionalDependencies = [
|
|
|
41
40
|
* Bundle the Open Next server.
|
|
42
41
|
*/
|
|
43
42
|
export async function bundleServer(buildOpts) {
|
|
44
|
-
|
|
45
|
-
const { appPath, outputDir, monorepoRoot } = buildOpts;
|
|
43
|
+
copyPackageCliFiles(packageDistDir, buildOpts);
|
|
44
|
+
const { appPath, outputDir, monorepoRoot, debug } = buildOpts;
|
|
46
45
|
const baseManifestPath = path.join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next");
|
|
47
46
|
const serverFiles = path.join(baseManifestPath, "required-server-files.json");
|
|
48
47
|
const nextConfig = JSON.parse(fs.readFileSync(serverFiles, "utf-8")).config;
|
|
@@ -60,7 +59,11 @@ export async function bundleServer(buildOpts) {
|
|
|
60
59
|
outfile: openNextServerBundle,
|
|
61
60
|
format: "esm",
|
|
62
61
|
target: "esnext",
|
|
63
|
-
|
|
62
|
+
// Minify code as much as possible but stay safe by not renaming identifiers
|
|
63
|
+
minifyWhitespace: !debug,
|
|
64
|
+
minifyIdentifiers: false,
|
|
65
|
+
minifySyntax: !debug,
|
|
66
|
+
legalComments: "none",
|
|
64
67
|
metafile: true,
|
|
65
68
|
// Next traces files using the default conditions from `nft` (`node`, `require`, `import` and `default`)
|
|
66
69
|
//
|
|
@@ -138,11 +141,11 @@ export async function bundleServer(buildOpts) {
|
|
|
138
141
|
console.log(`\x1b[35mWorker saved in \`${path.relative(buildOpts.appPath, getOutputWorkerPath(buildOpts))}\` 🚀\n\x1b[0m`);
|
|
139
142
|
}
|
|
140
143
|
/**
|
|
141
|
-
* This function
|
|
144
|
+
* This function apply updates to the bundled code.
|
|
142
145
|
*/
|
|
143
146
|
export async function updateWorkerBundledCode(workerOutputFile) {
|
|
144
147
|
const code = await readFile(workerOutputFile, "utf8");
|
|
145
|
-
const patchedCode =
|
|
148
|
+
const patchedCode = code.replace(/__require\d?\(/g, "require(").replace(/__require\d?\./g, "require.");
|
|
146
149
|
await writeFile(workerOutputFile, patchedCode);
|
|
147
150
|
}
|
|
148
151
|
/**
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
import { fileURLToPath } from "node:url";
|
|
3
4
|
import { loadConfig } from "@opennextjs/aws/adapters/config/util.js";
|
|
4
5
|
import { build } from "esbuild";
|
|
6
|
+
import pm from "picomatch";
|
|
5
7
|
/**
|
|
6
8
|
* Compiles the initialization code for the workerd runtime
|
|
7
9
|
*/
|
|
@@ -11,6 +13,23 @@ export async function compileInit(options) {
|
|
|
11
13
|
const initPath = path.join(templatesDir, "init.js");
|
|
12
14
|
const nextConfig = loadConfig(path.join(options.appBuildOutputPath, ".next"));
|
|
13
15
|
const basePath = nextConfig.basePath ?? "";
|
|
16
|
+
// https://github.com/vercel/next.js/blob/d76f0b13/packages/next/src/build/index.ts#L573
|
|
17
|
+
const nextRemotePatterns = nextConfig.images?.remotePatterns ?? [];
|
|
18
|
+
const remotePatterns = nextRemotePatterns.map((p) => ({
|
|
19
|
+
protocol: p.protocol,
|
|
20
|
+
hostname: p.hostname ? pm.makeRe(p.hostname).source : undefined,
|
|
21
|
+
port: p.port,
|
|
22
|
+
pathname: pm.makeRe(p.pathname ?? "**", { dot: true }).source,
|
|
23
|
+
// search is canary only as of June 2025
|
|
24
|
+
search: p.search,
|
|
25
|
+
}));
|
|
26
|
+
// Local patterns are only in canary as of June 2025
|
|
27
|
+
const nextLocalPatterns = nextConfig.images?.localPatterns ?? [];
|
|
28
|
+
// https://github.com/vercel/next.js/blob/d76f0b13/packages/next/src/build/index.ts#L573
|
|
29
|
+
const localPatterns = nextLocalPatterns.map((p) => ({
|
|
30
|
+
pathname: pm.makeRe(p.pathname ?? "**", { dot: true }).source,
|
|
31
|
+
search: p.search,
|
|
32
|
+
}));
|
|
14
33
|
await build({
|
|
15
34
|
entryPoints: [initPath],
|
|
16
35
|
outdir: path.join(options.outputDir, "cloudflare"),
|
|
@@ -22,6 +41,8 @@ export async function compileInit(options) {
|
|
|
22
41
|
define: {
|
|
23
42
|
__BUILD_TIMESTAMP_MS__: JSON.stringify(Date.now()),
|
|
24
43
|
__NEXT_BASE_PATH__: JSON.stringify(basePath),
|
|
44
|
+
__IMAGES_REMOTE_PATTERNS__: JSON.stringify(remotePatterns),
|
|
45
|
+
__IMAGES_LOCAL_PATTERNS__: JSON.stringify(localPatterns),
|
|
25
46
|
},
|
|
26
47
|
});
|
|
27
48
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
|
|
2
1
|
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { computePatchDiff } from "../../utils/test-patch.js";
|
|
3
3
|
import { buildIdRule, createCacheHandlerRule, createComposableCacheHandlersRule, createMiddlewareManifestRule, } from "./next-server.js";
|
|
4
4
|
describe("Next Server", () => {
|
|
5
5
|
const nextServerCode = `
|
|
@@ -86,344 +86,131 @@ class NextNodeServer extends _baseserver.default {
|
|
|
86
86
|
// ...
|
|
87
87
|
}`;
|
|
88
88
|
test("build ID", () => {
|
|
89
|
-
expect(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (!(0, _handlers.initializeCacheHandlers)()) return;
|
|
124
|
-
for (const [kind, handler] of Object.entries(cacheHandlers)){
|
|
125
|
-
if (!handler) continue;
|
|
126
|
-
(0, _handlers.setCacheHandler)(kind, (0, _interopdefault.interopDefault)(await dynamicImportEsmDefault((0, _formatdynamicimportpath.formatDynamicImportPath)(this.distDir, handler))));
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
async getIncrementalCache({ requestHeaders, requestProtocol }) {
|
|
130
|
-
const dev = !!this.renderOpts.dev;
|
|
131
|
-
let CacheHandler;
|
|
132
|
-
const { cacheHandler } = this.nextConfig;
|
|
133
|
-
if (cacheHandler) {
|
|
134
|
-
CacheHandler = (0, _interopdefault.interopDefault)(await dynamicImportEsmDefault((0, _formatdynamicimportpath.formatDynamicImportPath)(this.distDir, cacheHandler)));
|
|
135
|
-
}
|
|
136
|
-
await this.loadCustomCacheHandlers();
|
|
137
|
-
// incremental-cache is request specific
|
|
138
|
-
// although can have shared caches in module scope
|
|
139
|
-
// per-cache handler
|
|
140
|
-
return new _incrementalcache.IncrementalCache({
|
|
141
|
-
fs: this.getCacheFilesystem(),
|
|
142
|
-
dev,
|
|
143
|
-
requestHeaders,
|
|
144
|
-
requestProtocol,
|
|
145
|
-
allowedRevalidateHeaderKeys: this.nextConfig.experimental.allowedRevalidateHeaderKeys,
|
|
146
|
-
minimalMode: this.minimalMode,
|
|
147
|
-
serverDistDir: this.serverDistDir,
|
|
148
|
-
fetchCacheKeyPrefix: this.nextConfig.experimental.fetchCacheKeyPrefix,
|
|
149
|
-
maxMemoryCacheSize: this.nextConfig.cacheMaxMemorySize,
|
|
150
|
-
flushToDisk: !this.minimalMode && this.nextConfig.experimental.isrFlushToDisk,
|
|
151
|
-
getPrerenderManifest: ()=>this.getPrerenderManifest(),
|
|
152
|
-
CurCacheHandler: CacheHandler
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
getEnabledDirectories(dev) {
|
|
156
|
-
const dir = dev ? this.dir : this.serverDistDir;
|
|
157
|
-
return {
|
|
158
|
-
app: (0, _findpagesdir.findDir)(dir, "app") ? true : false,
|
|
159
|
-
pages: (0, _findpagesdir.findDir)(dir, "pages") ? true : false
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
// ...
|
|
163
|
-
}"
|
|
164
|
-
`);
|
|
89
|
+
expect(computePatchDiff("next-server.js", nextServerCode, buildIdRule)).toMatchInlineSnapshot(`
|
|
90
|
+
"Index: next-server.js
|
|
91
|
+
===================================================================
|
|
92
|
+
--- next-server.js
|
|
93
|
+
+++ next-server.js
|
|
94
|
+
@@ -1,5 +1,4 @@
|
|
95
|
+
-
|
|
96
|
+
class NextNodeServer extends _baseserver.default {
|
|
97
|
+
constructor(options){
|
|
98
|
+
// Initialize super class
|
|
99
|
+
super(options);
|
|
100
|
+
@@ -19,18 +18,10 @@
|
|
101
|
+
var _this_nextConfig_i18n;
|
|
102
|
+
return !!(0, _require.getMaybePagePath)(pathname, this.distDir, (_this_nextConfig_i18n = this.nextConfig.i18n) == null ? void 0 : _this_nextConfig_i18n.locales, this.enabledDirectories.app);
|
|
103
|
+
}
|
|
104
|
+
getBuildId() {
|
|
105
|
+
- const buildIdFile = (0, _path.join)(this.distDir, _constants.BUILD_ID_FILE);
|
|
106
|
+
- try {
|
|
107
|
+
- return _fs.default.readFileSync(buildIdFile, "utf8").trim();
|
|
108
|
+
- } catch (err) {
|
|
109
|
+
- if (err.code === "ENOENT") {
|
|
110
|
+
- throw new Error(\`Could not find a production build in the '\${this.distDir}' directory. Try building your app with 'next build' before starting the production server. https://nextjs.org/docs/messages/production-start-no-build-id\`);
|
|
111
|
+
- }
|
|
112
|
+
- throw err;
|
|
113
|
+
- }
|
|
114
|
+
- }
|
|
115
|
+
+ return process.env.NEXT_BUILD_ID;
|
|
116
|
+
+}
|
|
117
|
+
getMiddlewareManifest() {
|
|
118
|
+
if (this.minimalMode) return null;
|
|
119
|
+
const manifest = require(this.middlewareManifestPath);
|
|
120
|
+
return manifest;
|
|
121
|
+
"
|
|
122
|
+
`);
|
|
165
123
|
});
|
|
166
124
|
test("middleware manifest", () => {
|
|
167
|
-
expect(
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
throw err;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
getMiddlewareManifest() {
|
|
200
|
-
return "manifest";
|
|
201
|
-
}
|
|
202
|
-
async loadCustomCacheHandlers() {
|
|
203
|
-
const { cacheHandlers } = this.nextConfig.experimental;
|
|
204
|
-
if (!cacheHandlers) return;
|
|
205
|
-
// If we've already initialized the cache handlers interface, don't do it
|
|
206
|
-
// again.
|
|
207
|
-
if (!(0, _handlers.initializeCacheHandlers)()) return;
|
|
208
|
-
for (const [kind, handler] of Object.entries(cacheHandlers)){
|
|
209
|
-
if (!handler) continue;
|
|
210
|
-
(0, _handlers.setCacheHandler)(kind, (0, _interopdefault.interopDefault)(await dynamicImportEsmDefault((0, _formatdynamicimportpath.formatDynamicImportPath)(this.distDir, handler))));
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
async getIncrementalCache({ requestHeaders, requestProtocol }) {
|
|
214
|
-
const dev = !!this.renderOpts.dev;
|
|
215
|
-
let CacheHandler;
|
|
216
|
-
const { cacheHandler } = this.nextConfig;
|
|
217
|
-
if (cacheHandler) {
|
|
218
|
-
CacheHandler = (0, _interopdefault.interopDefault)(await dynamicImportEsmDefault((0, _formatdynamicimportpath.formatDynamicImportPath)(this.distDir, cacheHandler)));
|
|
219
|
-
}
|
|
220
|
-
await this.loadCustomCacheHandlers();
|
|
221
|
-
// incremental-cache is request specific
|
|
222
|
-
// although can have shared caches in module scope
|
|
223
|
-
// per-cache handler
|
|
224
|
-
return new _incrementalcache.IncrementalCache({
|
|
225
|
-
fs: this.getCacheFilesystem(),
|
|
226
|
-
dev,
|
|
227
|
-
requestHeaders,
|
|
228
|
-
requestProtocol,
|
|
229
|
-
allowedRevalidateHeaderKeys: this.nextConfig.experimental.allowedRevalidateHeaderKeys,
|
|
230
|
-
minimalMode: this.minimalMode,
|
|
231
|
-
serverDistDir: this.serverDistDir,
|
|
232
|
-
fetchCacheKeyPrefix: this.nextConfig.experimental.fetchCacheKeyPrefix,
|
|
233
|
-
maxMemoryCacheSize: this.nextConfig.cacheMaxMemorySize,
|
|
234
|
-
flushToDisk: !this.minimalMode && this.nextConfig.experimental.isrFlushToDisk,
|
|
235
|
-
getPrerenderManifest: ()=>this.getPrerenderManifest(),
|
|
236
|
-
CurCacheHandler: CacheHandler
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
getEnabledDirectories(dev) {
|
|
240
|
-
const dir = dev ? this.dir : this.serverDistDir;
|
|
241
|
-
return {
|
|
242
|
-
app: (0, _findpagesdir.findDir)(dir, "app") ? true : false,
|
|
243
|
-
pages: (0, _findpagesdir.findDir)(dir, "pages") ? true : false
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
// ...
|
|
247
|
-
}"
|
|
125
|
+
expect(computePatchDiff("next-server.js", nextServerCode, createMiddlewareManifestRule("manifest")))
|
|
126
|
+
.toMatchInlineSnapshot(`
|
|
127
|
+
"Index: next-server.js
|
|
128
|
+
===================================================================
|
|
129
|
+
--- next-server.js
|
|
130
|
+
+++ next-server.js
|
|
131
|
+
@@ -1,5 +1,4 @@
|
|
132
|
+
-
|
|
133
|
+
class NextNodeServer extends _baseserver.default {
|
|
134
|
+
constructor(options){
|
|
135
|
+
// Initialize super class
|
|
136
|
+
super(options);
|
|
137
|
+
@@ -30,12 +29,10 @@
|
|
138
|
+
throw err;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
getMiddlewareManifest() {
|
|
142
|
+
- if (this.minimalMode) return null;
|
|
143
|
+
- const manifest = require(this.middlewareManifestPath);
|
|
144
|
+
- return manifest;
|
|
145
|
+
- }
|
|
146
|
+
+ return "manifest";
|
|
147
|
+
+}
|
|
148
|
+
async loadCustomCacheHandlers() {
|
|
149
|
+
const { cacheHandlers } = this.nextConfig.experimental;
|
|
150
|
+
if (!cacheHandlers) return;
|
|
151
|
+
// If we've already initialized the cache handlers interface, don't do it
|
|
152
|
+
"
|
|
248
153
|
`);
|
|
249
154
|
});
|
|
250
155
|
test("cache handler", () => {
|
|
251
|
-
expect(
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
} catch (err) {
|
|
277
|
-
if (err.code === "ENOENT") {
|
|
278
|
-
throw new Error(\`Could not find a production build in the '\${this.distDir}' directory. Try building your app with 'next build' before starting the production server. https://nextjs.org/docs/messages/production-start-no-build-id\`);
|
|
279
|
-
}
|
|
280
|
-
throw err;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
getMiddlewareManifest() {
|
|
284
|
-
if (this.minimalMode) return null;
|
|
285
|
-
const manifest = require(this.middlewareManifestPath);
|
|
286
|
-
return manifest;
|
|
287
|
-
}
|
|
288
|
-
async loadCustomCacheHandlers() {
|
|
289
|
-
const { cacheHandlers } = this.nextConfig.experimental;
|
|
290
|
-
if (!cacheHandlers) return;
|
|
291
|
-
// If we've already initialized the cache handlers interface, don't do it
|
|
292
|
-
// again.
|
|
293
|
-
if (!(0, _handlers.initializeCacheHandlers)()) return;
|
|
294
|
-
for (const [kind, handler] of Object.entries(cacheHandlers)){
|
|
295
|
-
if (!handler) continue;
|
|
296
|
-
(0, _handlers.setCacheHandler)(kind, (0, _interopdefault.interopDefault)(await dynamicImportEsmDefault((0, _formatdynamicimportpath.formatDynamicImportPath)(this.distDir, handler))));
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
async getIncrementalCache({ requestHeaders, requestProtocol }) {
|
|
300
|
-
const dev = !!this.renderOpts.dev;
|
|
301
|
-
let CacheHandler;
|
|
302
|
-
const cacheHandler = null;
|
|
303
|
-
CacheHandler = require('manifest').default;
|
|
304
|
-
if (cacheHandler) {
|
|
305
|
-
CacheHandler = (0, _interopdefault.interopDefault)(await dynamicImportEsmDefault((0, _formatdynamicimportpath.formatDynamicImportPath)(this.distDir, cacheHandler)));
|
|
306
|
-
}
|
|
307
|
-
await this.loadCustomCacheHandlers();
|
|
308
|
-
// incremental-cache is request specific
|
|
309
|
-
// although can have shared caches in module scope
|
|
310
|
-
// per-cache handler
|
|
311
|
-
return new _incrementalcache.IncrementalCache({
|
|
312
|
-
fs: this.getCacheFilesystem(),
|
|
313
|
-
dev,
|
|
314
|
-
requestHeaders,
|
|
315
|
-
requestProtocol,
|
|
316
|
-
allowedRevalidateHeaderKeys: this.nextConfig.experimental.allowedRevalidateHeaderKeys,
|
|
317
|
-
minimalMode: this.minimalMode,
|
|
318
|
-
serverDistDir: this.serverDistDir,
|
|
319
|
-
fetchCacheKeyPrefix: this.nextConfig.experimental.fetchCacheKeyPrefix,
|
|
320
|
-
maxMemoryCacheSize: this.nextConfig.cacheMaxMemorySize,
|
|
321
|
-
flushToDisk: !this.minimalMode && this.nextConfig.experimental.isrFlushToDisk,
|
|
322
|
-
getPrerenderManifest: ()=>this.getPrerenderManifest(),
|
|
323
|
-
CurCacheHandler: CacheHandler
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
getEnabledDirectories(dev) {
|
|
327
|
-
const dir = dev ? this.dir : this.serverDistDir;
|
|
328
|
-
return {
|
|
329
|
-
app: (0, _findpagesdir.findDir)(dir, "app") ? true : false,
|
|
330
|
-
pages: (0, _findpagesdir.findDir)(dir, "pages") ? true : false
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
// ...
|
|
334
|
-
}"
|
|
156
|
+
expect(computePatchDiff("next-server.js", nextServerCode, createCacheHandlerRule("manifest")))
|
|
157
|
+
.toMatchInlineSnapshot(`
|
|
158
|
+
"Index: next-server.js
|
|
159
|
+
===================================================================
|
|
160
|
+
--- next-server.js
|
|
161
|
+
+++ next-server.js
|
|
162
|
+
@@ -1,5 +1,4 @@
|
|
163
|
+
-
|
|
164
|
+
class NextNodeServer extends _baseserver.default {
|
|
165
|
+
constructor(options){
|
|
166
|
+
// Initialize super class
|
|
167
|
+
super(options);
|
|
168
|
+
@@ -48,9 +47,10 @@
|
|
169
|
+
}
|
|
170
|
+
async getIncrementalCache({ requestHeaders, requestProtocol }) {
|
|
171
|
+
const dev = !!this.renderOpts.dev;
|
|
172
|
+
let CacheHandler;
|
|
173
|
+
- const { cacheHandler } = this.nextConfig;
|
|
174
|
+
+ const cacheHandler = null;
|
|
175
|
+
+CacheHandler = require('manifest').default;
|
|
176
|
+
if (cacheHandler) {
|
|
177
|
+
CacheHandler = (0, _interopdefault.interopDefault)(await dynamicImportEsmDefault((0, _formatdynamicimportpath.formatDynamicImportPath)(this.distDir, cacheHandler)));
|
|
178
|
+
}
|
|
179
|
+
await this.loadCustomCacheHandlers();
|
|
180
|
+
"
|
|
335
181
|
`);
|
|
336
182
|
});
|
|
337
183
|
test("composable cache handler", () => {
|
|
338
|
-
expect(
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
getMiddlewareManifest() {
|
|
371
|
-
if (this.minimalMode) return null;
|
|
372
|
-
const manifest = require(this.middlewareManifestPath);
|
|
373
|
-
return manifest;
|
|
374
|
-
}
|
|
375
|
-
async loadCustomCacheHandlers() {
|
|
376
|
-
const cacheHandlers = null;
|
|
377
|
-
const handlersSymbol = Symbol.for('@next/cache-handlers');
|
|
378
|
-
const handlersMapSymbol = Symbol.for('@next/cache-handlers-map');
|
|
379
|
-
const handlersSetSymbol = Symbol.for('@next/cache-handlers-set');
|
|
380
|
-
globalThis[handlersMapSymbol] = new Map();
|
|
381
|
-
globalThis[handlersMapSymbol].set("default", require('manifest').default);
|
|
382
|
-
globalThis[handlersSetSymbol] = new Set(globalThis[handlersMapSymbol].values());
|
|
383
|
-
if (!cacheHandlers) return;
|
|
384
|
-
// If we've already initialized the cache handlers interface, don't do it
|
|
385
|
-
// again.
|
|
386
|
-
if (!(0, _handlers.initializeCacheHandlers)()) return;
|
|
387
|
-
for (const [kind, handler] of Object.entries(cacheHandlers)){
|
|
388
|
-
if (!handler) continue;
|
|
389
|
-
(0, _handlers.setCacheHandler)(kind, (0, _interopdefault.interopDefault)(await dynamicImportEsmDefault((0, _formatdynamicimportpath.formatDynamicImportPath)(this.distDir, handler))));
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
async getIncrementalCache({ requestHeaders, requestProtocol }) {
|
|
393
|
-
const dev = !!this.renderOpts.dev;
|
|
394
|
-
let CacheHandler;
|
|
395
|
-
const { cacheHandler } = this.nextConfig;
|
|
396
|
-
if (cacheHandler) {
|
|
397
|
-
CacheHandler = (0, _interopdefault.interopDefault)(await dynamicImportEsmDefault((0, _formatdynamicimportpath.formatDynamicImportPath)(this.distDir, cacheHandler)));
|
|
398
|
-
}
|
|
399
|
-
await this.loadCustomCacheHandlers();
|
|
400
|
-
// incremental-cache is request specific
|
|
401
|
-
// although can have shared caches in module scope
|
|
402
|
-
// per-cache handler
|
|
403
|
-
return new _incrementalcache.IncrementalCache({
|
|
404
|
-
fs: this.getCacheFilesystem(),
|
|
405
|
-
dev,
|
|
406
|
-
requestHeaders,
|
|
407
|
-
requestProtocol,
|
|
408
|
-
allowedRevalidateHeaderKeys: this.nextConfig.experimental.allowedRevalidateHeaderKeys,
|
|
409
|
-
minimalMode: this.minimalMode,
|
|
410
|
-
serverDistDir: this.serverDistDir,
|
|
411
|
-
fetchCacheKeyPrefix: this.nextConfig.experimental.fetchCacheKeyPrefix,
|
|
412
|
-
maxMemoryCacheSize: this.nextConfig.cacheMaxMemorySize,
|
|
413
|
-
flushToDisk: !this.minimalMode && this.nextConfig.experimental.isrFlushToDisk,
|
|
414
|
-
getPrerenderManifest: ()=>this.getPrerenderManifest(),
|
|
415
|
-
CurCacheHandler: CacheHandler
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
getEnabledDirectories(dev) {
|
|
419
|
-
const dir = dev ? this.dir : this.serverDistDir;
|
|
420
|
-
return {
|
|
421
|
-
app: (0, _findpagesdir.findDir)(dir, "app") ? true : false,
|
|
422
|
-
pages: (0, _findpagesdir.findDir)(dir, "pages") ? true : false
|
|
423
|
-
};
|
|
424
|
-
}
|
|
425
|
-
// ...
|
|
426
|
-
}"
|
|
184
|
+
expect(computePatchDiff("next-server.js", nextServerCode, createComposableCacheHandlersRule("manifest")))
|
|
185
|
+
.toMatchInlineSnapshot(`
|
|
186
|
+
"Index: next-server.js
|
|
187
|
+
===================================================================
|
|
188
|
+
--- next-server.js
|
|
189
|
+
+++ next-server.js
|
|
190
|
+
@@ -1,5 +1,4 @@
|
|
191
|
+
-
|
|
192
|
+
class NextNodeServer extends _baseserver.default {
|
|
193
|
+
constructor(options){
|
|
194
|
+
// Initialize super class
|
|
195
|
+
super(options);
|
|
196
|
+
@@ -35,9 +34,15 @@
|
|
197
|
+
const manifest = require(this.middlewareManifestPath);
|
|
198
|
+
return manifest;
|
|
199
|
+
}
|
|
200
|
+
async loadCustomCacheHandlers() {
|
|
201
|
+
- const { cacheHandlers } = this.nextConfig.experimental;
|
|
202
|
+
+ const cacheHandlers = null;
|
|
203
|
+
+const handlersSymbol = Symbol.for('@next/cache-handlers');
|
|
204
|
+
+const handlersMapSymbol = Symbol.for('@next/cache-handlers-map');
|
|
205
|
+
+const handlersSetSymbol = Symbol.for('@next/cache-handlers-set');
|
|
206
|
+
+globalThis[handlersMapSymbol] = new Map();
|
|
207
|
+
+globalThis[handlersMapSymbol].set("default", require('manifest').default);
|
|
208
|
+
+globalThis[handlersSetSymbol] = new Set(globalThis[handlersMapSymbol].values());
|
|
209
|
+
if (!cacheHandlers) return;
|
|
210
|
+
// If we've already initialized the cache handlers interface, don't do it
|
|
211
|
+
// again.
|
|
212
|
+
if (!(0, _handlers.initializeCacheHandlers)()) return;
|
|
213
|
+
"
|
|
427
214
|
`);
|
|
428
215
|
});
|
|
429
216
|
});
|
|
@@ -10,7 +10,6 @@ export function patchResolveCache(updater, buildOpts) {
|
|
|
10
10
|
const packagePath = getPackagePath(buildOpts);
|
|
11
11
|
const outputPath = path.join(outputDir, "server-functions/default");
|
|
12
12
|
const indexPath = path.relative(buildOpts.appBuildOutputPath, path.join(outputPath, packagePath, `index.mjs`));
|
|
13
|
-
console.error({ index: indexPath });
|
|
14
13
|
return updater.updateContent("patch-resolve-cache", [
|
|
15
14
|
{
|
|
16
15
|
field: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
|
|
2
2
|
import { describe, expect, test } from "vitest";
|
|
3
|
+
import { computePatchDiff } from "../../utils/test-patch.js";
|
|
3
4
|
import { rule } from "./res-revalidate.js";
|
|
4
5
|
const minifiedApiPageRuntimeCode = `var r=/(?:^|,)\\s*?no-cache\\s*?(?:,|$)/;function t(e){var r=e&&Date.parse(e);return"number"==typeof r?r:NaN}e.exports=function(e,n){var o=e["if-modified-since"],i=e["if-none-match"];if(!o&&!i)return!1;var a=e["cache-control"];if(a&&r.test(a))return!1;if(i&&"*"!==i){var s=n.etag;if(!s)return!1;for(var d=!0,u=function(e){for(var r=0,t=[],n=0,o=0,i=e.length;o<i;o++)switch(e.charCodeAt(o)){case 32:n===r&&(n=r=o+1);break;case 44:t.push(e.substring(n,r)),n=r=o+1;break;default:r=o+1}return t.push(e.substring(n,r)),t}(i),l=0;l<u.length;l++){var p=u[l];if(p===s||p==="W/"+s||"W/"+p===s){d=!1;break}}if(d)return!1}if(o){var c=n["last-modified"];if(!c||!(t(c)<=t(o)))return!1}return!0}}},t={};function n(e){var o=t[e];if(void 0!==o)return o.exports;var i=t[e]={exports:{}},a=!0;try{r[e](i,i.exports,n),a=!1}finally{a&&delete t[e]}return i.exports}n.ab=__dirname+"/";var o=n(695);e.exports=o})()},"./dist/esm/server/crypto-utils.js":(e,r,t)=>{"use strict";t.r(r),t.d(r,{decryptWithSecret:()=>s,encryptWithSecret:()=>a});let n=require("crypto");var o=/*#__PURE__*/t.n(n);let i="aes-256-gcm";function a(e,r){let t=o().randomBytes(16),n=o().randomBytes(64),a=o().pbkdf2Sync(e,n,1e5,32,"sha512"),s=o().createCipheriv(i,a,t),d=Buffer.concat([s.update(r,"utf8"),s.final()]),u=s.getAuthTag();return Buffer.concat([n,t,u,d]).toString("hex")}function s(e,r){let t=Buffer.from(r,"hex"),n=t.slice(0,64),a=t.slice(64,80),s=t.slice(80,96),d=t.slice(96),u=o().pbkdf2Sync(e,n,1e5,32,"sha512"),l=o().createDecipheriv(i,u,a);return l.setAuthTag(s),l.update(d)+l.final("utf8")}},"next/dist/compiled/jsonwebtoken":e=>{"use strict";e.exports=require("next/dist/compiled/jsonwebtoken")},"next/dist/compiled/raw-body":e=>{"use strict";e.exports=require("next/dist/compiled/raw-body")},querystring:e=>{"use strict";e.exports=require("querystring")}},r={};function t(n){var o=r[n];if(void 0!==o)return o.exports;var i=r[n]={exports:{}};return e[n](i,i.exports,t),i.exports}t.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return t.d(r,{a:r}),r},t.d=(e,r)=>{for(var n in r)t.o(r,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:r[n]})},t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),t.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var n={};(()=>{"use strict";t.r(n),t.d(n,{PagesAPIRouteModule:()=>z,default:()=>U});class e{static get(e,r,t){let n=Reflect.get(e,r,t);return"function"==typeof n?n.bind(e):n}static set(e,r,t,n){return Reflect.set(e,r,t,n)}static has(e,r){return Reflect.has(e,r)}static deleteProperty(e,r){return Reflect.deleteProperty(e,r)}}class r extends Error{constructor(){super("Headers cannot be modified. Read more: https://nextjs.org/docs/app/api-reference/functions/headers")}static callable(){throw new r}}class o extends Headers{constructor(r){super(),this.headers=new Proxy(r,{get(t,n,o){if("symbol"==typeof n)return e.get(t,n,o);let i=n.toLowerCase(),a=Object.keys(r).find(e=>e.toLowerCase()===i);if(void 0!==a)return e.get(t,a,o)},set(t,n,o,i){if("symbol"==typeof n)return e.set(t,n,o,i);let a=n.toLowerCase(),s=Object.keys(r).find(e=>e.toLowerCase()===a);return e.set(t,s??n,o,i)},has(t,n){if("symbol"==typeof n)return e.has(t,n);let o=n.toLowerCase(),i=Object.keys(r).find(e=>e.toLowerCase()===o);return void 0!==i&&e.has(t,i)},deleteProperty(t,n){if("symbol"==typeof n)return e.deleteProperty(t,n);let o=n.toLowerCase(),i=Object.keys(r).find(e=>e.toLowerCase()===o);return void 0===i||e.deleteProperty(t,i)}})}static seal(t){return new Proxy(t,{get(t,n,o){switch(n){case"append":case"delete":case"set":return r.callable;default:return e.get(t,n,o)}}})}merge(e){return Array.isArray(e)?e.join(", "):e}static from(e){return e instanceof Headers?e:new o(e)}append(e,r){let t=this.headers[e];"string"==typeof t?this.headers[e]=[t,r]:Array.isArray(t)?t.push(r):this.headers[e]=r}delete(e){delete this.headers[e]}get(e){let r=this.headers[e];return void 0!==r?this.merge(r):null}has(e){return void 0!==this.headers[e]}set(e,r){this.headers[e]=r}forEach(e,r){for(let[t,n]of this.entries())e.call(r,n,t,this)}*entries(){for(let e of Object.keys(this.headers)){let r=e.toLowerCase(),t=this.get(r);yield[r,t]}}*keys(){for(let e of Object.keys(this.headers)){let r=e.toLowerCase();yield r}}*values(){for(let e of Object.keys(this.headers)){let r=this.get(e);yield r}}[Symbol.iterator](){return this.entries()}}let i="x-prerender-revalidate",a="x-prerender-revalidate-if-generated",s={shared:"shared",reactServerComponents:"rsc",serverSideRendering:"ssr",actionBrowser:"action-browser",apiNode:"api-node",apiEdge:"api-edge",middleware:"middleware",instrument:"instrument",edgeAsset:"edge-asset",appPagesBrowser:"app-pages-browser",pagesDirBrowser:"pages-dir-browser",pagesDirEdge:"pages-dir-edge",pagesDirNode:"pages-dir-node"};({...s,GROUP:{builtinReact:[s.reactServerComponents,s.actionBrowser],serverOnly:[s.reactServerComponents,s.actionBrowser,s.instrument,s.middleware],neutralTarget:[s.apiNode,s.apiEdge],clientOnly:[s.serverSideRendering,s.appPagesBrowser],bundled:[s.reactServerComponents,s.actionBrowser,s.serverSideRendering,s.appPagesBrowser,s.shared,s.instrument,s.middleware],appPages:[s.reactServerComponents,s.serverSideRendering,s.appPagesBrowser,s.actionBrowser]}});let d=require("next/dist/server/lib/trace/tracer");var u=/*#__PURE__*/function(e){return e.handleRequest="BaseServer.handleRequest",e.run="BaseServer.run",e.pipe="BaseServer.pipe",e.getStaticHTML="BaseServer.getStaticHTML",e.render="BaseServer.render",e.renderToResponseWithComponents="BaseServer.renderToResponseWithComponents",e.renderToResponse="BaseServer.renderToResponse",e.renderToHTML="BaseServer.renderToHTML",e.renderError="BaseServer.renderError",e.renderErrorToResponse="BaseServer.renderErrorToResponse",e.renderErrorToHTML="BaseServer.renderErrorToHTML",e.render404="BaseServer.render404",e}(u||{}),l=/*#__PURE__*/function(e){return e.loadDefaultErrorComponents="LoadComponents.loadDefaultErrorComponents",e.loadComponents="LoadComponents.loadComponents",e}(l||{}),p=/*#__PURE__*/function(e){return e.getRequestHandler="NextServer.getRequestHandler",e.getServer="NextServer.getServer",e.getServerRequestHandler="NextServer.getServerRequestHandler",e.createServer="createServer.createServer",e}(p||{}),c=/*#__PURE__*/function(e){return e.compression="NextNodeServer.compression",e.getBuildId="NextNodeServer.getBuildId",e.createComponentTree="NextNodeServer.createComponentTree",e.clientComponentLoading="NextNodeServer.clientComponentLoading",e.getLayoutOrPageModule="NextNodeServer.getLayoutOrPageModule",e.generateStaticRoutes="NextNodeServer.generateStaticRoutes",e.generateFsStaticRoutes="NextNodeServer.generateFsStaticRoutes",e.generatePublicRoutes="NextNodeServer.generatePublicRoutes",e.generateImageRoutes="NextNodeServer.generateImageRoutes.route",e.sendRenderResult="NextNodeServer.sendRenderResult",e.proxyRequest="NextNodeServer.proxyRequest",e.runApi="NextNodeServer.runApi",e.render="NextNodeServer.render",e.renderHTML="NextNodeServer.renderHTML",e.imageOptimizer="NextNodeServer.imageOptimizer",e.getPagePath="NextNodeServer.getPagePath",e.getRoutesManifest="NextNodeServer.getRoutesManifest",e.findPageComponents="NextNodeServer.findPageComponents",e.getFontManifest="NextNodeServer.getFontManifest",e.getServerComponentManifest="NextNodeServer.getServerComponentManifest",e.getRequestHandler="NextNodeServer.getRequestHandler",e.renderToHTML="NextNodeServer.renderToHTML",e.renderError="NextNodeServer.renderError",e.renderErrorToHTML="NextNodeServer.renderErrorToHTML",e.render404="NextNodeServer.render404",e.startResponse="NextNodeServer.startResponse",e.route="route",e.onProxyReq="onProxyReq",e.apiResolver="apiResolver",e.internalFetch="internalFetch",e}(c||{}),f=/*#__PURE__*/function(e){return e.startServer="startServer.startServer",e}(f||{}),g=/*#__PURE__*/function(e){return e.getServerSideProps="Render.getServerSideProps",e.getStaticProps="Render.getStaticProps",e.renderToString="Render.renderToString",e.renderDocument="Render.renderDocument",e.createBodyResult="Render.createBodyResult",e}(g||{}),v=/*#__PURE__*/function(e){return e.renderToString="AppRender.renderToString",e.renderToReadableStream="AppRender.renderToReadableStream",e.getBodyResult="AppRender.getBodyResult",e.fetch="AppRender.fetch",e}(v||{}),m=/*#__PURE__*/function(e){return e.executeRoute="Router.executeRoute",e}(m||{}),h=/*#__PURE__*/function(e){return e.runHandler="Node.runHandler",e}(h||{}),y=/*#__PURE__*/function(e){return e.runHandler="AppRouteRouteHandlers.runHandler",e}(y||{}),b=/*#__PURE__*/function(e){return e.generateMetadata="ResolveMetadata.generateMetadata",e.generateViewport="ResolveMetadata.generateViewport",e}(b||{}),x=/*#__PURE__*/function(e){return e.execute="Middleware.execute",e}(x||{});let w="__prerender_bypass",S="__next_preview_data",R=Symbol(S),_=Symbol(w);function E(e,r={}){if(_ in e)return e;let{serialize:n}=t("./dist/compiled/cookie/index.js"),o=e.getHeader("Set-Cookie");return e.setHeader("Set-Cookie",[..."string"==typeof o?[o]:Array.isArray(o)?o:[],n(w,"",{expires:new Date(0),httpOnly:!0,sameSite:"none",secure:!0,path:"/",...void 0!==r.path?{path:r.path}:void 0}),n(S,"",{expires:new Date(0),httpOnly:!0,sameSite:"none",secure:!0,path:"/",...void 0!==r.path?{path:r.path}:void 0})]),Object.defineProperty(e,_,{value:!0,enumerable:!1}),e}class O extends Error{constructor(e,r){super(r),this.statusCode=e}}function C(e,r,t){e.statusCode=r,e.statusMessage=t,e.end(t)}function N({req:e},r,t){let n={configurable:!0,enumerable:!0},o={...n,writable:!0};Object.defineProperty(e,r,{...n,get:()=>{let n=t();return Object.defineProperty(e,r,{...o,value:n}),n},set:t=>{Object.defineProperty(e,r,{...o,value:t})}})}class j{constructor({userland:e,definition:r}){this.userland=e,this.definition=r}}var T=t("./dist/compiled/bytes/index.js"),P=/*#__PURE__*/t.n(T);let A=e=>{let r=e.length,t=0,n=0,o=8997,i=0,a=33826,s=0,d=40164,u=0,l=52210;for(;t<r;)o^=e.charCodeAt(t++),n=435*o,i=435*a,s=435*d,u=435*l,s+=o<<8,u+=a<<8,i+=n>>>16,o=65535&n,s+=i>>>16,a=65535&i,l=u+(s>>>16)&65535,d=65535&s;return(15&l)*0x1000000000000+0x100000000*d+65536*a+(o^l>>4)},H=(e,r=!1)=>(r?'W/"':'"')+A(e).toString(36)+e.length.toString(36)+'"';"undefined"!=typeof performance&&["mark","measure","getEntriesByName"].every(e=>"function"==typeof performance[e]);var M=t("./dist/compiled/fresh/index.js"),k=/*#__PURE__*/t.n(M);let B=require("stream");function L(e){return"object"==typeof e&&null!==e&&"name"in e&&"message"in e}var D=t("./dist/compiled/@edge-runtime/cookies/index.js"),$=t("./dist/compiled/content-type/index.js");async function q(e,r){let n,o;try{n=(0,$.parse)(e.headers["content-type"]||"text/plain")}catch{n=(0,$.parse)("text/plain")}let{type:i,parameters:a}=n,s=a.charset||"utf-8";try{let n=t("next/dist/compiled/raw-body");o=await n(e,{encoding:s,limit:r})}catch(e){if(L(e)&&"entity.too.large"===e.type)throw Object.defineProperty(new O(413,\`Body exceeded \${r} limit\`),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0});throw Object.defineProperty(new O(400,"Invalid body"),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0})}let d=o.toString();return"application/json"===i||"application/ld+json"===i?function(e){if(0===e.length)return{};try{return JSON.parse(e)}catch(e){throw Object.defineProperty(new O(400,"Invalid JSON"),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0})}}(d):"application/x-www-form-urlencoded"===i?t("querystring").decode(d):d}function I(e){return"string"==typeof e&&e.length>=16}async function K(e,r,t,n){if("string"!=typeof e||!e.startsWith("/"))throw Object.defineProperty(Error(\`Invalid urlPath provided to revalidate(), must be a path e.g. /blog/post-1, received \${e}\`),"__NEXT_ERROR_CODE",{value:"E153",enumerable:!1,configurable:!0});let o={[i]:n.previewModeId,...r.unstable_onlyGenerated?{[a]:"1"}:{}},s=[...n.allowedRevalidateHeaderKeys||[]];for(let e of((n.trustHostHeader||n.dev)&&s.push("cookie"),n.trustHostHeader&&s.push("x-vercel-protection-bypass"),Object.keys(t.headers)))s.includes(e)&&(o[e]=t.headers[e]);try{if(n.trustHostHeader){let n=await fetch(\`https://\${t.headers.host}\${e}\`,{method:"HEAD",headers:o}),i=n.headers.get("x-vercel-cache")||n.headers.get("x-nextjs-cache");if((null==i?void 0:i.toUpperCase())!=="REVALIDATED"&&200!==n.status&&!(404===n.status&&r.unstable_onlyGenerated))throw Object.defineProperty(Error(\`Invalid response \${n.status}\`),"__NEXT_ERROR_CODE",{value:"E175",enumerable:!1,configurable:!0})}else if(n.revalidate)await n.revalidate({urlPath:e,revalidateHeaders:o,opts:r});else throw Object.defineProperty(Error("Invariant: required internal revalidate method not passed to api-utils"),"__NEXT_ERROR_CODE",{value:"E174",enumerable:!1,configurable:!0})}catch(r){throw Object.defineProperty(Error(\`Failed to revalidate \${e}: \${L(r)?r.message:r}\`),"__NEXT_ERROR_CODE",{value:"E240",enumerable:!1,configurable:!0})}}async function X(e,r,n,s,d,u,l,p,c){try{var f,g,v,m;if(!s){r.statusCode=404,r.end("Not Found");return}let u=s.config||{},l=(null==(f=u.api)?void 0:f.bodyParser)!==!1,p=(null==(g=u.api)?void 0:g.responseLimit)??!0;null==(v=u.api)||v.externalResolver,N({req:e},"cookies",(m=e.headers,function(){let{cookie:e}=m;if(!e)return{};let{parse:r}=t("./dist/compiled/cookie/index.js");return r(Array.isArray(e)?e.join("; "):e)})),e.query=n,N({req:e},"previewData",()=>(function(e,r,n,s){var d,u;let l;if(n&&function(e,r){let t=o.from(e.headers);return{isOnDemandRevalidate:t.get(i)===r.previewModeId,revalidateOnlyGenerated:t.has(a)}}(e,n).isOnDemandRevalidate)return!1;if(R in e)return e[R];let p=o.from(e.headers),c=new D.RequestCookies(p),f=null==(d=c.get(w))?void 0:d.value,g=null==(u=c.get(S))?void 0:u.value;if(f&&!g&&f===n.previewModeId){let r={};return Object.defineProperty(e,R,{value:r,enumerable:!1}),r}if(!f&&!g)return!1;if(!f||!g||f!==n.previewModeId)return s||E(r),!1;try{l=t("next/dist/compiled/jsonwebtoken").verify(g,n.previewModeSigningKey)}catch{return E(r),!1}let{decryptWithSecret:v}=t("./dist/esm/server/crypto-utils.js"),m=v(Buffer.from(n.previewModeEncryptionKey),l.data);try{let r=JSON.parse(m);return Object.defineProperty(e,R,{value:r,enumerable:!1}),r}catch{return!1}})(e,r,d,!!d.multiZoneDraftMode)),N({req:e},"preview",()=>!1!==e.previewData||void 0),N({req:e},"draftMode",()=>e.preview),l&&!e.body&&(e.body=await q(e,u.api&&u.api.bodyParser&&u.api.bodyParser.sizeLimit?u.api.bodyParser.sizeLimit:"1mb"));let c=0,h=p&&"boolean"!=typeof p?P().parse(p):4194304,y=r.write,b=r.end;r.write=(...e)=>(c+=Buffer.byteLength(e[0]||""),y.apply(r,e)),r.end=(...t)=>(t.length&&"function"!=typeof t[0]&&(c+=Buffer.byteLength(t[0]||"")),p&&c>=h&&console.warn(\`API response for \${e.url} exceeds \${P().format(h)}. API Routes are meant to respond quickly. https://nextjs.org/docs/messages/api-routes-response-size-limit\`),b.apply(r,t)),r.status=e=>(r.statusCode=e,r),r.send=t=>(function(e,r,t){var n;if(null==t){r.end();return}if(204===r.statusCode||304===r.statusCode){r.removeHeader("Content-Type"),r.removeHeader("Content-Length"),r.removeHeader("Transfer-Encoding"),r.end();return}let o=r.getHeader("Content-Type");if(t instanceof B.Stream){o||r.setHeader("Content-Type","application/octet-stream"),t.pipe(r);return}let i=["object","number","boolean"].includes(typeof t),a=i?JSON.stringify(t):t;if((n=H(a))&&r.setHeader("ETag",n),!k()(e.headers,{etag:n})||(r.statusCode=304,r.end(),0)){if(Buffer.isBuffer(t)){o||r.setHeader("Content-Type","application/octet-stream"),r.setHeader("Content-Length",t.length),r.end(t);return}i&&r.setHeader("Content-Type","application/json; charset=utf-8"),r.setHeader("Content-Length",Buffer.byteLength(a)),r.end(a)}})(e,r,t),r.json=e=>{r.setHeader("Content-Type","application/json; charset=utf-8"),r.send(JSON.stringify(e))},r.redirect=(e,t)=>(function(e,r,t){if("string"==typeof r&&(t=r,r=307),"number"!=typeof r||"string"!=typeof t)throw Object.defineProperty(Error("Invalid redirect arguments. Please use a single argument URL, e.g. res.redirect('/destination') or use a status code and URL, e.g. res.redirect(307, '/destination')."),"__NEXT_ERROR_CODE",{value:"E389",enumerable:!1,configurable:!0});return e.writeHead(r,{Location:t}),e.write(t),e.end(),e})(r,e,t),r.setDraftMode=(e={enable:!0})=>(function(e,r){if(!I(r.previewModeId))throw Object.defineProperty(Error("invariant: invalid previewModeId"),"__NEXT_ERROR_CODE",{value:"E169",enumerable:!1,configurable:!0});let n=r.enable?void 0:new Date(0),{serialize:o}=t("./dist/compiled/cookie/index.js"),i=e.getHeader("Set-Cookie");return e.setHeader("Set-Cookie",[..."string"==typeof i?[i]:Array.isArray(i)?i:[],o(w,r.previewModeId,{httpOnly:!0,sameSite:"none",secure:!0,path:"/",expires:n})]),e})(r,Object.assign({},d,e)),r.setPreviewData=(e,n={})=>(function(e,r,n){if(!I(n.previewModeId))throw Object.defineProperty(Error("invariant: invalid previewModeId"),"__NEXT_ERROR_CODE",{value:"E169",enumerable:!1,configurable:!0});if(!I(n.previewModeEncryptionKey))throw Object.defineProperty(Error("invariant: invalid previewModeEncryptionKey"),"__NEXT_ERROR_CODE",{value:"E334",enumerable:!1,configurable:!0});if(!I(n.previewModeSigningKey))throw Object.defineProperty(Error("invariant: invalid previewModeSigningKey"),"__NEXT_ERROR_CODE",{value:"E436",enumerable:!1,configurable:!0});let o=t("next/dist/compiled/jsonwebtoken"),{encryptWithSecret:i}=t("./dist/esm/server/crypto-utils.js"),a=o.sign({data:i(Buffer.from(n.previewModeEncryptionKey),JSON.stringify(r))},n.previewModeSigningKey,{algorithm:"HS256",...void 0!==n.maxAge?{expiresIn:n.maxAge}:void 0});if(a.length>2048)throw Object.defineProperty(Error("Preview data is limited to 2KB currently, reduce how much data you are storing as preview data to continue"),"__NEXT_ERROR_CODE",{value:"E465",enumerable:!1,configurable:!0});let{serialize:s}=t("./dist/compiled/cookie/index.js"),d=e.getHeader("Set-Cookie");return e.setHeader("Set-Cookie",[..."string"==typeof d?[d]:Array.isArray(d)?d:[],s(w,n.previewModeId,{httpOnly:!0,sameSite:"none",secure:!0,path:"/",...void 0!==n.maxAge?{maxAge:n.maxAge}:void 0,...void 0!==n.path?{path:n.path}:void 0}),s(S,a,{httpOnly:!0,sameSite:"none",secure:!0,path:"/",...void 0!==n.maxAge?{maxAge:n.maxAge}:void 0,...void 0!==n.path?{path:n.path}:void 0})]),e})(r,e,Object.assign({},d,n)),r.clearPreviewData=(e={})=>E(r,e),r.revalidate=(r,t)=>K(r,t||{},e,d);let x=s.default||s;await x(e,r)}catch(t){if(null==c||c(t,e,{routerKind:"Pages Router",routePath:p||"",routeType:"route",revalidateReason:void 0}),t instanceof O)C(r,t.statusCode,t.message);else{if(l)throw L(t)&&(t.page=p),t;if(console.error(t),u)throw t;C(r,500,"Internal Server Error")}}}class z extends j{constructor(e){if(super(e),"function"!=typeof e.userland.default)throw Object.defineProperty(Error(\`Page \${e.definition.page} does not export a default function.\`),"__NEXT_ERROR_CODE",{value:"E379",enumerable:!1,configurable:!0});this.apiResolverWrapped=function(e,r){return(...t)=>((0,d.getTracer)().setRootSpanAttribute("next.route",e),(0,d.getTracer)().trace(h.runHandler,{spanName:\`executing api route (pages) \${e}\`},()=>r(...t)))}(e.definition.page,X)}async render(e,r,t){let{apiResolverWrapped:n}=this;await n(e,r,t.query,this.userland,{...t.previewProps,revalidate:t.revalidate,trustHostHeader:t.trustHostHeader,allowedRevalidateHeaderKeys:t.allowedRevalidateHeaderKeys,hostname:t.hostname,multiZoneDraftMode:t.multiZoneDraftMode,dev:t.dev},t.minimalMode,t.dev,t.page,t.onError)}}let U=z})(),module.exports=n})();`;
|
|
5
6
|
const unminifiedCode = `async function revalidate(urlPath, opts, req, context) {
|
|
@@ -73,69 +74,26 @@ describe("patchResRevalidate", () => {
|
|
|
73
74
|
expect(patchCode(minifiedApiPageRuntimeCode, rule)).toMatchInlineSnapshot(`"var r=/(?:^|,)\\s*?no-cache\\s*?(?:,|$)/;function t(e){var r=e&&Date.parse(e);return"number"==typeof r?r:NaN}e.exports=function(e,n){var o=e["if-modified-since"],i=e["if-none-match"];if(!o&&!i)return!1;var a=e["cache-control"];if(a&&r.test(a))return!1;if(i&&"*"!==i){var s=n.etag;if(!s)return!1;for(var d=!0,u=function(e){for(var r=0,t=[],n=0,o=0,i=e.length;o<i;o++)switch(e.charCodeAt(o)){case 32:n===r&&(n=r=o+1);break;case 44:t.push(e.substring(n,r)),n=r=o+1;break;default:r=o+1}return t.push(e.substring(n,r)),t}(i),l=0;l<u.length;l++){var p=u[l];if(p===s||p==="W/"+s||"W/"+p===s){d=!1;break}}if(d)return!1}if(o){var c=n["last-modified"];if(!c||!(t(c)<=t(o)))return!1}return!0}}},t={};function n(e){var o=t[e];if(void 0!==o)return o.exports;var i=t[e]={exports:{}},a=!0;try{r[e](i,i.exports,n),a=!1}finally{a&&delete t[e]}return i.exports}n.ab=__dirname+"/";var o=n(695);e.exports=o})()},"./dist/esm/server/crypto-utils.js":(e,r,t)=>{"use strict";t.r(r),t.d(r,{decryptWithSecret:()=>s,encryptWithSecret:()=>a});let n=require("crypto");var o=/*#__PURE__*/t.n(n);let i="aes-256-gcm";function a(e,r){let t=o().randomBytes(16),n=o().randomBytes(64),a=o().pbkdf2Sync(e,n,1e5,32,"sha512"),s=o().createCipheriv(i,a,t),d=Buffer.concat([s.update(r,"utf8"),s.final()]),u=s.getAuthTag();return Buffer.concat([n,t,u,d]).toString("hex")}function s(e,r){let t=Buffer.from(r,"hex"),n=t.slice(0,64),a=t.slice(64,80),s=t.slice(80,96),d=t.slice(96),u=o().pbkdf2Sync(e,n,1e5,32,"sha512"),l=o().createDecipheriv(i,u,a);return l.setAuthTag(s),l.update(d)+l.final("utf8")}},"next/dist/compiled/jsonwebtoken":e=>{"use strict";e.exports=require("next/dist/compiled/jsonwebtoken")},"next/dist/compiled/raw-body":e=>{"use strict";e.exports=require("next/dist/compiled/raw-body")},querystring:e=>{"use strict";e.exports=require("querystring")}},r={};function t(n){var o=r[n];if(void 0!==o)return o.exports;var i=r[n]={exports:{}};return e[n](i,i.exports,t),i.exports}t.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return t.d(r,{a:r}),r},t.d=(e,r)=>{for(var n in r)t.o(r,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:r[n]})},t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),t.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var n={};(()=>{"use strict";t.r(n),t.d(n,{PagesAPIRouteModule:()=>z,default:()=>U});class e{static get(e,r,t){let n=Reflect.get(e,r,t);return"function"==typeof n?n.bind(e):n}static set(e,r,t,n){return Reflect.set(e,r,t,n)}static has(e,r){return Reflect.has(e,r)}static deleteProperty(e,r){return Reflect.deleteProperty(e,r)}}class r extends Error{constructor(){super("Headers cannot be modified. Read more: https://nextjs.org/docs/app/api-reference/functions/headers")}static callable(){throw new r}}class o extends Headers{constructor(r){super(),this.headers=new Proxy(r,{get(t,n,o){if("symbol"==typeof n)return e.get(t,n,o);let i=n.toLowerCase(),a=Object.keys(r).find(e=>e.toLowerCase()===i);if(void 0!==a)return e.get(t,a,o)},set(t,n,o,i){if("symbol"==typeof n)return e.set(t,n,o,i);let a=n.toLowerCase(),s=Object.keys(r).find(e=>e.toLowerCase()===a);return e.set(t,s??n,o,i)},has(t,n){if("symbol"==typeof n)return e.has(t,n);let o=n.toLowerCase(),i=Object.keys(r).find(e=>e.toLowerCase()===o);return void 0!==i&&e.has(t,i)},deleteProperty(t,n){if("symbol"==typeof n)return e.deleteProperty(t,n);let o=n.toLowerCase(),i=Object.keys(r).find(e=>e.toLowerCase()===o);return void 0===i||e.deleteProperty(t,i)}})}static seal(t){return new Proxy(t,{get(t,n,o){switch(n){case"append":case"delete":case"set":return r.callable;default:return e.get(t,n,o)}}})}merge(e){return Array.isArray(e)?e.join(", "):e}static from(e){return e instanceof Headers?e:new o(e)}append(e,r){let t=this.headers[e];"string"==typeof t?this.headers[e]=[t,r]:Array.isArray(t)?t.push(r):this.headers[e]=r}delete(e){delete this.headers[e]}get(e){let r=this.headers[e];return void 0!==r?this.merge(r):null}has(e){return void 0!==this.headers[e]}set(e,r){this.headers[e]=r}forEach(e,r){for(let[t,n]of this.entries())e.call(r,n,t,this)}*entries(){for(let e of Object.keys(this.headers)){let r=e.toLowerCase(),t=this.get(r);yield[r,t]}}*keys(){for(let e of Object.keys(this.headers)){let r=e.toLowerCase();yield r}}*values(){for(let e of Object.keys(this.headers)){let r=this.get(e);yield r}}[Symbol.iterator](){return this.entries()}}let i="x-prerender-revalidate",a="x-prerender-revalidate-if-generated",s={shared:"shared",reactServerComponents:"rsc",serverSideRendering:"ssr",actionBrowser:"action-browser",apiNode:"api-node",apiEdge:"api-edge",middleware:"middleware",instrument:"instrument",edgeAsset:"edge-asset",appPagesBrowser:"app-pages-browser",pagesDirBrowser:"pages-dir-browser",pagesDirEdge:"pages-dir-edge",pagesDirNode:"pages-dir-node"};({...s,GROUP:{builtinReact:[s.reactServerComponents,s.actionBrowser],serverOnly:[s.reactServerComponents,s.actionBrowser,s.instrument,s.middleware],neutralTarget:[s.apiNode,s.apiEdge],clientOnly:[s.serverSideRendering,s.appPagesBrowser],bundled:[s.reactServerComponents,s.actionBrowser,s.serverSideRendering,s.appPagesBrowser,s.shared,s.instrument,s.middleware],appPages:[s.reactServerComponents,s.serverSideRendering,s.appPagesBrowser,s.actionBrowser]}});let d=require("next/dist/server/lib/trace/tracer");var u=/*#__PURE__*/function(e){return e.handleRequest="BaseServer.handleRequest",e.run="BaseServer.run",e.pipe="BaseServer.pipe",e.getStaticHTML="BaseServer.getStaticHTML",e.render="BaseServer.render",e.renderToResponseWithComponents="BaseServer.renderToResponseWithComponents",e.renderToResponse="BaseServer.renderToResponse",e.renderToHTML="BaseServer.renderToHTML",e.renderError="BaseServer.renderError",e.renderErrorToResponse="BaseServer.renderErrorToResponse",e.renderErrorToHTML="BaseServer.renderErrorToHTML",e.render404="BaseServer.render404",e}(u||{}),l=/*#__PURE__*/function(e){return e.loadDefaultErrorComponents="LoadComponents.loadDefaultErrorComponents",e.loadComponents="LoadComponents.loadComponents",e}(l||{}),p=/*#__PURE__*/function(e){return e.getRequestHandler="NextServer.getRequestHandler",e.getServer="NextServer.getServer",e.getServerRequestHandler="NextServer.getServerRequestHandler",e.createServer="createServer.createServer",e}(p||{}),c=/*#__PURE__*/function(e){return e.compression="NextNodeServer.compression",e.getBuildId="NextNodeServer.getBuildId",e.createComponentTree="NextNodeServer.createComponentTree",e.clientComponentLoading="NextNodeServer.clientComponentLoading",e.getLayoutOrPageModule="NextNodeServer.getLayoutOrPageModule",e.generateStaticRoutes="NextNodeServer.generateStaticRoutes",e.generateFsStaticRoutes="NextNodeServer.generateFsStaticRoutes",e.generatePublicRoutes="NextNodeServer.generatePublicRoutes",e.generateImageRoutes="NextNodeServer.generateImageRoutes.route",e.sendRenderResult="NextNodeServer.sendRenderResult",e.proxyRequest="NextNodeServer.proxyRequest",e.runApi="NextNodeServer.runApi",e.render="NextNodeServer.render",e.renderHTML="NextNodeServer.renderHTML",e.imageOptimizer="NextNodeServer.imageOptimizer",e.getPagePath="NextNodeServer.getPagePath",e.getRoutesManifest="NextNodeServer.getRoutesManifest",e.findPageComponents="NextNodeServer.findPageComponents",e.getFontManifest="NextNodeServer.getFontManifest",e.getServerComponentManifest="NextNodeServer.getServerComponentManifest",e.getRequestHandler="NextNodeServer.getRequestHandler",e.renderToHTML="NextNodeServer.renderToHTML",e.renderError="NextNodeServer.renderError",e.renderErrorToHTML="NextNodeServer.renderErrorToHTML",e.render404="NextNodeServer.render404",e.startResponse="NextNodeServer.startResponse",e.route="route",e.onProxyReq="onProxyReq",e.apiResolver="apiResolver",e.internalFetch="internalFetch",e}(c||{}),f=/*#__PURE__*/function(e){return e.startServer="startServer.startServer",e}(f||{}),g=/*#__PURE__*/function(e){return e.getServerSideProps="Render.getServerSideProps",e.getStaticProps="Render.getStaticProps",e.renderToString="Render.renderToString",e.renderDocument="Render.renderDocument",e.createBodyResult="Render.createBodyResult",e}(g||{}),v=/*#__PURE__*/function(e){return e.renderToString="AppRender.renderToString",e.renderToReadableStream="AppRender.renderToReadableStream",e.getBodyResult="AppRender.getBodyResult",e.fetch="AppRender.fetch",e}(v||{}),m=/*#__PURE__*/function(e){return e.executeRoute="Router.executeRoute",e}(m||{}),h=/*#__PURE__*/function(e){return e.runHandler="Node.runHandler",e}(h||{}),y=/*#__PURE__*/function(e){return e.runHandler="AppRouteRouteHandlers.runHandler",e}(y||{}),b=/*#__PURE__*/function(e){return e.generateMetadata="ResolveMetadata.generateMetadata",e.generateViewport="ResolveMetadata.generateViewport",e}(b||{}),x=/*#__PURE__*/function(e){return e.execute="Middleware.execute",e}(x||{});let w="__prerender_bypass",S="__next_preview_data",R=Symbol(S),_=Symbol(w);function E(e,r={}){if(_ in e)return e;let{serialize:n}=t("./dist/compiled/cookie/index.js"),o=e.getHeader("Set-Cookie");return e.setHeader("Set-Cookie",[..."string"==typeof o?[o]:Array.isArray(o)?o:[],n(w,"",{expires:new Date(0),httpOnly:!0,sameSite:"none",secure:!0,path:"/",...void 0!==r.path?{path:r.path}:void 0}),n(S,"",{expires:new Date(0),httpOnly:!0,sameSite:"none",secure:!0,path:"/",...void 0!==r.path?{path:r.path}:void 0})]),Object.defineProperty(e,_,{value:!0,enumerable:!1}),e}class O extends Error{constructor(e,r){super(r),this.statusCode=e}}function C(e,r,t){e.statusCode=r,e.statusMessage=t,e.end(t)}function N({req:e},r,t){let n={configurable:!0,enumerable:!0},o={...n,writable:!0};Object.defineProperty(e,r,{...n,get:()=>{let n=t();return Object.defineProperty(e,r,{...o,value:n}),n},set:t=>{Object.defineProperty(e,r,{...o,value:t})}})}class j{constructor({userland:e,definition:r}){this.userland=e,this.definition=r}}var T=t("./dist/compiled/bytes/index.js"),P=/*#__PURE__*/t.n(T);let A=e=>{let r=e.length,t=0,n=0,o=8997,i=0,a=33826,s=0,d=40164,u=0,l=52210;for(;t<r;)o^=e.charCodeAt(t++),n=435*o,i=435*a,s=435*d,u=435*l,s+=o<<8,u+=a<<8,i+=n>>>16,o=65535&n,s+=i>>>16,a=65535&i,l=u+(s>>>16)&65535,d=65535&s;return(15&l)*0x1000000000000+0x100000000*d+65536*a+(o^l>>4)},H=(e,r=!1)=>(r?'W/"':'"')+A(e).toString(36)+e.length.toString(36)+'"';"undefined"!=typeof performance&&["mark","measure","getEntriesByName"].every(e=>"function"==typeof performance[e]);var M=t("./dist/compiled/fresh/index.js"),k=/*#__PURE__*/t.n(M);let B=require("stream");function L(e){return"object"==typeof e&&null!==e&&"name"in e&&"message"in e}var D=t("./dist/compiled/@edge-runtime/cookies/index.js"),$=t("./dist/compiled/content-type/index.js");async function q(e,r){let n,o;try{n=(0,$.parse)(e.headers["content-type"]||"text/plain")}catch{n=(0,$.parse)("text/plain")}let{type:i,parameters:a}=n,s=a.charset||"utf-8";try{let n=t("next/dist/compiled/raw-body");o=await n(e,{encoding:s,limit:r})}catch(e){if(L(e)&&"entity.too.large"===e.type)throw Object.defineProperty(new O(413,\`Body exceeded \${r} limit\`),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0});throw Object.defineProperty(new O(400,"Invalid body"),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0})}let d=o.toString();return"application/json"===i||"application/ld+json"===i?function(e){if(0===e.length)return{};try{return JSON.parse(e)}catch(e){throw Object.defineProperty(new O(400,"Invalid JSON"),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0})}}(d):"application/x-www-form-urlencoded"===i?t("querystring").decode(d):d}function I(e){return"string"==typeof e&&e.length>=16}async function K(e,r,t,n){if("string"!=typeof e||!e.startsWith("/"))throw Object.defineProperty(Error(\`Invalid urlPath provided to revalidate(), must be a path e.g. /blog/post-1, received \${e}\`),"__NEXT_ERROR_CODE",{value:"E153",enumerable:!1,configurable:!0});let o={[i]:n.previewModeId,...r.unstable_onlyGenerated?{[a]:"1"}:{}},s=[...n.allowedRevalidateHeaderKeys||[]];for(let e of((n.trustHostHeader||n.dev)&&s.push("cookie"),n.trustHostHeader&&s.push("x-vercel-protection-bypass"),Object.keys(t.headers)))s.includes(e)&&(o[e]=t.headers[e]);try{if(n.trustHostHeader){let n=await (await import("@opennextjs/cloudflare")).getCloudflareContext().env.WORKER_SELF_REFERENCE.fetch(\`\${t.headers.host.includes("localhost") ? "http":"https" }://\${t.headers.host}\${e}\`,{method:'HEAD', headers:o}),i=n.headers.get("x-vercel-cache")||n.headers.get("x-nextjs-cache");if((null==i?void 0:i.toUpperCase())!=="REVALIDATED"&&200!==n.status&&!(404===n.status&&r.unstable_onlyGenerated))throw Object.defineProperty(Error(\`Invalid response \${n.status}\`),"__NEXT_ERROR_CODE",{value:"E175",enumerable:!1,configurable:!0})}else if(n.revalidate)await n.revalidate({urlPath:e,revalidateHeaders:o,opts:r});else throw Object.defineProperty(Error("Invariant: required internal revalidate method not passed to api-utils"),"__NEXT_ERROR_CODE",{value:"E174",enumerable:!1,configurable:!0})}catch(r){throw Object.defineProperty(Error(\`Failed to revalidate \${e}: \${L(r)?r.message:r}\`),"__NEXT_ERROR_CODE",{value:"E240",enumerable:!1,configurable:!0})}}async function X(e,r,n,s,d,u,l,p,c){try{var f,g,v,m;if(!s){r.statusCode=404,r.end("Not Found");return}let u=s.config||{},l=(null==(f=u.api)?void 0:f.bodyParser)!==!1,p=(null==(g=u.api)?void 0:g.responseLimit)??!0;null==(v=u.api)||v.externalResolver,N({req:e},"cookies",(m=e.headers,function(){let{cookie:e}=m;if(!e)return{};let{parse:r}=t("./dist/compiled/cookie/index.js");return r(Array.isArray(e)?e.join("; "):e)})),e.query=n,N({req:e},"previewData",()=>(function(e,r,n,s){var d,u;let l;if(n&&function(e,r){let t=o.from(e.headers);return{isOnDemandRevalidate:t.get(i)===r.previewModeId,revalidateOnlyGenerated:t.has(a)}}(e,n).isOnDemandRevalidate)return!1;if(R in e)return e[R];let p=o.from(e.headers),c=new D.RequestCookies(p),f=null==(d=c.get(w))?void 0:d.value,g=null==(u=c.get(S))?void 0:u.value;if(f&&!g&&f===n.previewModeId){let r={};return Object.defineProperty(e,R,{value:r,enumerable:!1}),r}if(!f&&!g)return!1;if(!f||!g||f!==n.previewModeId)return s||E(r),!1;try{l=t("next/dist/compiled/jsonwebtoken").verify(g,n.previewModeSigningKey)}catch{return E(r),!1}let{decryptWithSecret:v}=t("./dist/esm/server/crypto-utils.js"),m=v(Buffer.from(n.previewModeEncryptionKey),l.data);try{let r=JSON.parse(m);return Object.defineProperty(e,R,{value:r,enumerable:!1}),r}catch{return!1}})(e,r,d,!!d.multiZoneDraftMode)),N({req:e},"preview",()=>!1!==e.previewData||void 0),N({req:e},"draftMode",()=>e.preview),l&&!e.body&&(e.body=await q(e,u.api&&u.api.bodyParser&&u.api.bodyParser.sizeLimit?u.api.bodyParser.sizeLimit:"1mb"));let c=0,h=p&&"boolean"!=typeof p?P().parse(p):4194304,y=r.write,b=r.end;r.write=(...e)=>(c+=Buffer.byteLength(e[0]||""),y.apply(r,e)),r.end=(...t)=>(t.length&&"function"!=typeof t[0]&&(c+=Buffer.byteLength(t[0]||"")),p&&c>=h&&console.warn(\`API response for \${e.url} exceeds \${P().format(h)}. API Routes are meant to respond quickly. https://nextjs.org/docs/messages/api-routes-response-size-limit\`),b.apply(r,t)),r.status=e=>(r.statusCode=e,r),r.send=t=>(function(e,r,t){var n;if(null==t){r.end();return}if(204===r.statusCode||304===r.statusCode){r.removeHeader("Content-Type"),r.removeHeader("Content-Length"),r.removeHeader("Transfer-Encoding"),r.end();return}let o=r.getHeader("Content-Type");if(t instanceof B.Stream){o||r.setHeader("Content-Type","application/octet-stream"),t.pipe(r);return}let i=["object","number","boolean"].includes(typeof t),a=i?JSON.stringify(t):t;if((n=H(a))&&r.setHeader("ETag",n),!k()(e.headers,{etag:n})||(r.statusCode=304,r.end(),0)){if(Buffer.isBuffer(t)){o||r.setHeader("Content-Type","application/octet-stream"),r.setHeader("Content-Length",t.length),r.end(t);return}i&&r.setHeader("Content-Type","application/json; charset=utf-8"),r.setHeader("Content-Length",Buffer.byteLength(a)),r.end(a)}})(e,r,t),r.json=e=>{r.setHeader("Content-Type","application/json; charset=utf-8"),r.send(JSON.stringify(e))},r.redirect=(e,t)=>(function(e,r,t){if("string"==typeof r&&(t=r,r=307),"number"!=typeof r||"string"!=typeof t)throw Object.defineProperty(Error("Invalid redirect arguments. Please use a single argument URL, e.g. res.redirect('/destination') or use a status code and URL, e.g. res.redirect(307, '/destination')."),"__NEXT_ERROR_CODE",{value:"E389",enumerable:!1,configurable:!0});return e.writeHead(r,{Location:t}),e.write(t),e.end(),e})(r,e,t),r.setDraftMode=(e={enable:!0})=>(function(e,r){if(!I(r.previewModeId))throw Object.defineProperty(Error("invariant: invalid previewModeId"),"__NEXT_ERROR_CODE",{value:"E169",enumerable:!1,configurable:!0});let n=r.enable?void 0:new Date(0),{serialize:o}=t("./dist/compiled/cookie/index.js"),i=e.getHeader("Set-Cookie");return e.setHeader("Set-Cookie",[..."string"==typeof i?[i]:Array.isArray(i)?i:[],o(w,r.previewModeId,{httpOnly:!0,sameSite:"none",secure:!0,path:"/",expires:n})]),e})(r,Object.assign({},d,e)),r.setPreviewData=(e,n={})=>(function(e,r,n){if(!I(n.previewModeId))throw Object.defineProperty(Error("invariant: invalid previewModeId"),"__NEXT_ERROR_CODE",{value:"E169",enumerable:!1,configurable:!0});if(!I(n.previewModeEncryptionKey))throw Object.defineProperty(Error("invariant: invalid previewModeEncryptionKey"),"__NEXT_ERROR_CODE",{value:"E334",enumerable:!1,configurable:!0});if(!I(n.previewModeSigningKey))throw Object.defineProperty(Error("invariant: invalid previewModeSigningKey"),"__NEXT_ERROR_CODE",{value:"E436",enumerable:!1,configurable:!0});let o=t("next/dist/compiled/jsonwebtoken"),{encryptWithSecret:i}=t("./dist/esm/server/crypto-utils.js"),a=o.sign({data:i(Buffer.from(n.previewModeEncryptionKey),JSON.stringify(r))},n.previewModeSigningKey,{algorithm:"HS256",...void 0!==n.maxAge?{expiresIn:n.maxAge}:void 0});if(a.length>2048)throw Object.defineProperty(Error("Preview data is limited to 2KB currently, reduce how much data you are storing as preview data to continue"),"__NEXT_ERROR_CODE",{value:"E465",enumerable:!1,configurable:!0});let{serialize:s}=t("./dist/compiled/cookie/index.js"),d=e.getHeader("Set-Cookie");return e.setHeader("Set-Cookie",[..."string"==typeof d?[d]:Array.isArray(d)?d:[],s(w,n.previewModeId,{httpOnly:!0,sameSite:"none",secure:!0,path:"/",...void 0!==n.maxAge?{maxAge:n.maxAge}:void 0,...void 0!==n.path?{path:n.path}:void 0}),s(S,a,{httpOnly:!0,sameSite:"none",secure:!0,path:"/",...void 0!==n.maxAge?{maxAge:n.maxAge}:void 0,...void 0!==n.path?{path:n.path}:void 0})]),e})(r,e,Object.assign({},d,n)),r.clearPreviewData=(e={})=>E(r,e),r.revalidate=(r,t)=>K(r,t||{},e,d);let x=s.default||s;await x(e,r)}catch(t){if(null==c||c(t,e,{routerKind:"Pages Router",routePath:p||"",routeType:"route",revalidateReason:void 0}),t instanceof O)C(r,t.statusCode,t.message);else{if(l)throw L(t)&&(t.page=p),t;if(console.error(t),u)throw t;C(r,500,"Internal Server Error")}}}class z extends j{constructor(e){if(super(e),"function"!=typeof e.userland.default)throw Object.defineProperty(Error(\`Page \${e.definition.page} does not export a default function.\`),"__NEXT_ERROR_CODE",{value:"E379",enumerable:!1,configurable:!0});this.apiResolverWrapped=function(e,r){return(...t)=>((0,d.getTracer)().setRootSpanAttribute("next.route",e),(0,d.getTracer)().trace(h.runHandler,{spanName:\`executing api route (pages) \${e}\`},()=>r(...t)))}(e.definition.page,X)}async render(e,r,t){let{apiResolverWrapped:n}=this;await n(e,r,t.query,this.userland,{...t.previewProps,revalidate:t.revalidate,trustHostHeader:t.trustHostHeader,allowedRevalidateHeaderKeys:t.allowedRevalidateHeaderKeys,hostname:t.hostname,multiZoneDraftMode:t.multiZoneDraftMode,dev:t.dev},t.minimalMode,t.dev,t.page,t.onError)}}let U=z})(),module.exports=n})();"`);
|
|
74
75
|
});
|
|
75
76
|
test("patch unminified code", () => {
|
|
76
|
-
expect(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (context.trustHostHeader) {
|
|
98
|
-
allowedRevalidateHeaderKeys.push('x-vercel-protection-bypass');
|
|
99
|
-
}
|
|
100
|
-
for (const key of Object.keys(req.headers)){
|
|
101
|
-
if (allowedRevalidateHeaderKeys.includes(key)) {
|
|
102
|
-
revalidateHeaders[key] = req.headers[key];
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
try {
|
|
106
|
-
if (context.trustHostHeader) {
|
|
107
|
-
const res = await (await import("@opennextjs/cloudflare")).getCloudflareContext().env.WORKER_SELF_REFERENCE.fetch(\`\${req.headers.host.includes("localhost") ? "http":"https" }://\${req.headers.host}\${urlPath}\`,{method:'HEAD', headers:revalidateHeaders});
|
|
108
|
-
// we use the cache header to determine successful revalidate as
|
|
109
|
-
// a non-200 status code can be returned from a successful revalidate
|
|
110
|
-
// e.g. notFound: true returns 404 status code but is successful
|
|
111
|
-
const cacheHeader = res.headers.get('x-vercel-cache') || res.headers.get('x-nextjs-cache');
|
|
112
|
-
if ((cacheHeader == null ? void 0 : cacheHeader.toUpperCase()) !== 'REVALIDATED' && res.status !== 200 && !(res.status === 404 && opts.unstable_onlyGenerated)) {
|
|
113
|
-
throw Object.defineProperty(new Error(\`Invalid response \${res.status}\`), "__NEXT_ERROR_CODE", {
|
|
114
|
-
value: "E175",
|
|
115
|
-
enumerable: false,
|
|
116
|
-
configurable: true
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
} else if (context.revalidate) {
|
|
120
|
-
await context.revalidate({
|
|
121
|
-
urlPath,
|
|
122
|
-
revalidateHeaders,
|
|
123
|
-
opts
|
|
124
|
-
});
|
|
125
|
-
} else {
|
|
126
|
-
throw Object.defineProperty(new Error(\`Invariant: required internal revalidate method not passed to api-utils\`), "__NEXT_ERROR_CODE", {
|
|
127
|
-
value: "E174",
|
|
128
|
-
enumerable: false,
|
|
129
|
-
configurable: true
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
} catch (err) {
|
|
133
|
-
throw Object.defineProperty(new Error(\`Failed to revalidate \${urlPath}: \${(0, _iserror.default)(err) ? err.message : err}\`), "__NEXT_ERROR_CODE", {
|
|
134
|
-
value: "E240",
|
|
135
|
-
enumerable: false,
|
|
136
|
-
configurable: true
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
}"`);
|
|
77
|
+
expect(computePatchDiff("pages-api.runtime.prod.js", unminifiedCode, rule)).toMatchInlineSnapshot(`
|
|
78
|
+
"Index: pages-api.runtime.prod.js
|
|
79
|
+
===================================================================
|
|
80
|
+
--- pages-api.runtime.prod.js
|
|
81
|
+
+++ pages-api.runtime.prod.js
|
|
82
|
+
@@ -27,12 +27,9 @@
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
if (context.trustHostHeader) {
|
|
87
|
+
- const res = await fetch(\`https://\${req.headers.host}\${urlPath}\`, {
|
|
88
|
+
- method: 'HEAD',
|
|
89
|
+
- headers: revalidateHeaders
|
|
90
|
+
- });
|
|
91
|
+
+ const res = await (await import("@opennextjs/cloudflare")).getCloudflareContext().env.WORKER_SELF_REFERENCE.fetch(\`\${req.headers.host.includes("localhost") ? "http":"https" }://\${req.headers.host}\${urlPath}\`,{method:'HEAD', headers:revalidateHeaders});
|
|
92
|
+
// we use the cache header to determine successful revalidate as
|
|
93
|
+
// a non-200 status code can be returned from a successful revalidate
|
|
94
|
+
// e.g. notFound: true returns 404 status code but is successful
|
|
95
|
+
const cacheHeader = res.headers.get('x-vercel-cache') || res.headers.get('x-nextjs-cache');
|
|
96
|
+
"
|
|
97
|
+
`);
|
|
140
98
|
});
|
|
141
99
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
|
|
2
1
|
import { expect, test } from "vitest";
|
|
2
|
+
import { computePatchDiff } from "../../utils/test-patch.js";
|
|
3
3
|
import { rule } from "./use-cache.js";
|
|
4
|
-
const
|
|
4
|
+
const code = `"use strict";
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
@@ -78,79 +78,24 @@ function createSnapshot() {
|
|
|
78
78
|
//# sourceMappingURL=async-local-storage.js.map
|
|
79
79
|
`;
|
|
80
80
|
test("patch the createSnapshot function", () => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
createAsyncLocalStorage: function() {
|
|
102
|
-
return createAsyncLocalStorage;
|
|
103
|
-
},
|
|
104
|
-
createSnapshot: function() {
|
|
105
|
-
return createSnapshot;
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
const sharedAsyncLocalStorageNotAvailableError = Object.defineProperty(new Error('Invariant: AsyncLocalStorage accessed in runtime where it is not available'), "__NEXT_ERROR_CODE", {
|
|
109
|
-
value: "E504",
|
|
110
|
-
enumerable: false,
|
|
111
|
-
configurable: true
|
|
112
|
-
});
|
|
113
|
-
class FakeAsyncLocalStorage {
|
|
114
|
-
disable() {
|
|
115
|
-
throw sharedAsyncLocalStorageNotAvailableError;
|
|
116
|
-
}
|
|
117
|
-
getStore() {
|
|
118
|
-
// This fake implementation of AsyncLocalStorage always returns \`undefined\`.
|
|
119
|
-
return undefined;
|
|
120
|
-
}
|
|
121
|
-
run() {
|
|
122
|
-
throw sharedAsyncLocalStorageNotAvailableError;
|
|
123
|
-
}
|
|
124
|
-
exit() {
|
|
125
|
-
throw sharedAsyncLocalStorageNotAvailableError;
|
|
126
|
-
}
|
|
127
|
-
enterWith() {
|
|
128
|
-
throw sharedAsyncLocalStorageNotAvailableError;
|
|
129
|
-
}
|
|
130
|
-
static bind(fn) {
|
|
131
|
-
return fn;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
const maybeGlobalAsyncLocalStorage = typeof globalThis !== 'undefined' && globalThis.AsyncLocalStorage;
|
|
135
|
-
function createAsyncLocalStorage() {
|
|
136
|
-
if (maybeGlobalAsyncLocalStorage) {
|
|
137
|
-
return new maybeGlobalAsyncLocalStorage();
|
|
138
|
-
}
|
|
139
|
-
return new FakeAsyncLocalStorage();
|
|
140
|
-
}
|
|
141
|
-
function bindSnapshot(fn) {
|
|
142
|
-
if (maybeGlobalAsyncLocalStorage) {
|
|
143
|
-
return maybeGlobalAsyncLocalStorage.bind(fn);
|
|
144
|
-
}
|
|
145
|
-
return FakeAsyncLocalStorage.bind(fn);
|
|
146
|
-
}
|
|
147
|
-
function createSnapshot() {
|
|
148
|
-
// Ignored snapshot
|
|
149
|
-
return function(fn, ...args) {
|
|
150
|
-
return fn(...args);
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
//# sourceMappingURL=async-local-storage.js.map
|
|
155
|
-
"`);
|
|
81
|
+
expect(computePatchDiff("async-local-storage.js", code, rule)).toMatchInlineSnapshot(`
|
|
82
|
+
"Index: async-local-storage.js
|
|
83
|
+
===================================================================
|
|
84
|
+
--- async-local-storage.js
|
|
85
|
+
+++ async-local-storage.js
|
|
86
|
+
@@ -63,11 +63,9 @@
|
|
87
|
+
}
|
|
88
|
+
return FakeAsyncLocalStorage.bind(fn);
|
|
89
|
+
}
|
|
90
|
+
function createSnapshot() {
|
|
91
|
+
- if (maybeGlobalAsyncLocalStorage) {
|
|
92
|
+
- return maybeGlobalAsyncLocalStorage.snapshot();
|
|
93
|
+
- }
|
|
94
|
+
+ // Ignored snapshot
|
|
95
|
+
return function(fn, ...args) {
|
|
96
|
+
return fn(...args);
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
"
|
|
100
|
+
`);
|
|
156
101
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { getOutputWorkerPath } from "
|
|
3
|
+
import { getOutputWorkerPath } from "../bundle-server.js";
|
|
4
4
|
/**
|
|
5
5
|
* Copies
|
|
6
6
|
* - the template files present in the cloudflare adapter package to `.open-next/cloudflare-templates`
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the diff resulting of applying the `rule` to `src`.
|
|
3
|
+
*
|
|
4
|
+
* @param filename Filename used in the patch output
|
|
5
|
+
* @param src Content of the source code
|
|
6
|
+
* @param rule ASTgrep rule
|
|
7
|
+
* @returns diff in unified diff format
|
|
8
|
+
*/
|
|
9
|
+
export declare function computePatchDiff(filename: string, src: string, rule: string): string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
|
|
2
|
+
import { createPatch } from "diff";
|
|
3
|
+
/**
|
|
4
|
+
* Compute the diff resulting of applying the `rule` to `src`.
|
|
5
|
+
*
|
|
6
|
+
* @param filename Filename used in the patch output
|
|
7
|
+
* @param src Content of the source code
|
|
8
|
+
* @param rule ASTgrep rule
|
|
9
|
+
* @returns diff in unified diff format
|
|
10
|
+
*/
|
|
11
|
+
export function computePatchDiff(filename, src, rule) {
|
|
12
|
+
const dst = patchCode(src, rule);
|
|
13
|
+
return createPatch(filename, src, dst);
|
|
14
|
+
}
|
|
@@ -7,7 +7,24 @@
|
|
|
7
7
|
* Executes the handler with the Cloudflare context.
|
|
8
8
|
*/
|
|
9
9
|
export declare function runWithCloudflareRequestContext(request: Request, env: CloudflareEnv, ctx: ExecutionContext, handler: () => Promise<Response>): Promise<Response>;
|
|
10
|
+
export type RemotePattern = {
|
|
11
|
+
protocol?: "http" | "https";
|
|
12
|
+
hostname: string;
|
|
13
|
+
port?: string;
|
|
14
|
+
pathname: string;
|
|
15
|
+
search?: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Fetches an images.
|
|
19
|
+
*
|
|
20
|
+
* Local images (starting with a '/' as fetched using the passed fetcher).
|
|
21
|
+
* Remote images should match the configured remote patterns or a 404 response is returned.
|
|
22
|
+
*/
|
|
23
|
+
export declare function fetchImage(fetcher: Fetcher | undefined, url: string): Response | Promise<Response> | undefined;
|
|
24
|
+
export declare function matchRemotePattern(pattern: RemotePattern, url: URL): boolean;
|
|
10
25
|
declare global {
|
|
11
26
|
var __BUILD_TIMESTAMP_MS__: number;
|
|
12
27
|
var __NEXT_BASE_PATH__: string;
|
|
28
|
+
var __IMAGES_REMOTE_PATTERNS__: RemotePattern[];
|
|
29
|
+
var __IMAGES_LOCAL_PATTERNS__: unknown[];
|
|
13
30
|
}
|
|
@@ -114,4 +114,80 @@ function populateProcessEnv(url, env) {
|
|
|
114
114
|
*/
|
|
115
115
|
process.env.__NEXT_PRIVATE_ORIGIN = url.origin;
|
|
116
116
|
}
|
|
117
|
+
const imgRemotePatterns = __IMAGES_REMOTE_PATTERNS__;
|
|
118
|
+
/**
|
|
119
|
+
* Fetches an images.
|
|
120
|
+
*
|
|
121
|
+
* Local images (starting with a '/' as fetched using the passed fetcher).
|
|
122
|
+
* Remote images should match the configured remote patterns or a 404 response is returned.
|
|
123
|
+
*/
|
|
124
|
+
export function fetchImage(fetcher, url) {
|
|
125
|
+
// https://github.com/vercel/next.js/blob/d76f0b1/packages/next/src/server/image-optimizer.ts#L208
|
|
126
|
+
if (!url || url.length > 3072 || url.startsWith("//")) {
|
|
127
|
+
return new Response("Not Found", { status: 404 });
|
|
128
|
+
}
|
|
129
|
+
// Local
|
|
130
|
+
if (url.startsWith("/")) {
|
|
131
|
+
if (/\/_next\/image($|\/)/.test(decodeURIComponent(parseUrl(url)?.pathname ?? ""))) {
|
|
132
|
+
return new Response("Not Found", { status: 404 });
|
|
133
|
+
}
|
|
134
|
+
return fetcher?.fetch(`http://assets.local${url}`);
|
|
135
|
+
}
|
|
136
|
+
// Remote
|
|
137
|
+
let hrefParsed;
|
|
138
|
+
try {
|
|
139
|
+
hrefParsed = new URL(url);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return new Response("Not Found", { status: 404 });
|
|
143
|
+
}
|
|
144
|
+
if (!["http:", "https:"].includes(hrefParsed.protocol)) {
|
|
145
|
+
return new Response("Not Found", { status: 404 });
|
|
146
|
+
}
|
|
147
|
+
if (!imgRemotePatterns.some((p) => matchRemotePattern(p, hrefParsed))) {
|
|
148
|
+
return new Response("Not Found", { status: 404 });
|
|
149
|
+
}
|
|
150
|
+
return fetch(url, { cf: { cacheEverything: true } });
|
|
151
|
+
}
|
|
152
|
+
export function matchRemotePattern(pattern, url) {
|
|
153
|
+
// https://github.com/vercel/next.js/blob/d76f0b1/packages/next/src/shared/lib/match-remote-pattern.ts
|
|
154
|
+
if (pattern.protocol !== undefined) {
|
|
155
|
+
if (pattern.protocol.replace(/:$/, "") !== url.protocol.replace(/:$/, "")) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (pattern.port !== undefined) {
|
|
160
|
+
if (pattern.port !== url.port) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (pattern.hostname === undefined) {
|
|
165
|
+
throw new Error(`Pattern should define hostname but found\n${JSON.stringify(pattern)}`);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
if (!new RegExp(pattern.hostname).test(url.hostname)) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (pattern.search !== undefined) {
|
|
173
|
+
if (pattern.search !== url.search) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Should be the same as writeImagesManifest()
|
|
178
|
+
if (!new RegExp(pattern.pathname).test(url.pathname)) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
function parseUrl(url) {
|
|
184
|
+
let parsed = undefined;
|
|
185
|
+
try {
|
|
186
|
+
parsed = new URL(url, "http://n");
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// empty
|
|
190
|
+
}
|
|
191
|
+
return parsed;
|
|
192
|
+
}
|
|
117
193
|
/* eslint-enable no-var */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//@ts-expect-error: Will be resolved by wrangler build
|
|
2
|
-
import { runWithCloudflareRequestContext } from "./cloudflare/init.js";
|
|
2
|
+
import { fetchImage, runWithCloudflareRequestContext } from "./cloudflare/init.js";
|
|
3
3
|
// @ts-expect-error: Will be resolved by wrangler build
|
|
4
4
|
import { handler as middlewareHandler } from "./middleware/handler.mjs";
|
|
5
5
|
//@ts-expect-error: Will be resolved by wrangler build
|
|
@@ -27,9 +27,7 @@ export default {
|
|
|
27
27
|
// Fallback for the Next default image loader.
|
|
28
28
|
if (url.pathname === `${globalThis.__NEXT_BASE_PATH__}/_next/image`) {
|
|
29
29
|
const imageUrl = url.searchParams.get("url") ?? "";
|
|
30
|
-
return imageUrl
|
|
31
|
-
? env.ASSETS?.fetch(`http://assets.local${imageUrl}`)
|
|
32
|
-
: fetch(imageUrl, { cf: { cacheEverything: true } });
|
|
30
|
+
return fetchImage(env.ASSETS, imageUrl);
|
|
33
31
|
}
|
|
34
32
|
// - `Request`s are handled by the Next server
|
|
35
33
|
const reqOrResp = await middlewareHandler(request, env, ctx);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opennextjs/cloudflare",
|
|
3
3
|
"description": "Cloudflare builder for next apps",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.3.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"opennextjs-cloudflare": "dist/cli/index.js"
|
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
"@tsconfig/strictest": "^2.0.5",
|
|
55
55
|
"@types/mock-fs": "^4.13.4",
|
|
56
56
|
"@types/node": "^22.2.0",
|
|
57
|
+
"@types/picomatch": "^4.0.0",
|
|
58
|
+
"diff": "^8.0.2",
|
|
57
59
|
"esbuild": "^0.25.4",
|
|
58
60
|
"eslint": "^9.11.1",
|
|
59
61
|
"eslint-plugin-import": "^2.31.0",
|
|
@@ -62,6 +64,7 @@
|
|
|
62
64
|
"globals": "^15.9.0",
|
|
63
65
|
"mock-fs": "^5.4.1",
|
|
64
66
|
"next": "~14.2.24",
|
|
67
|
+
"picomatch": "^4.0.2",
|
|
65
68
|
"rimraf": "^6.0.1",
|
|
66
69
|
"typescript": "^5.7.3",
|
|
67
70
|
"typescript-eslint": "^8.7.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./investigated/index.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./investigated/index.js";
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Applies multiple code patches in order to a given piece of code, at each step it validates that the code
|
|
3
|
-
* has actually been patched/changed, if not an error is thrown
|
|
4
|
-
*
|
|
5
|
-
* @param code the code to apply the patches to
|
|
6
|
-
* @param patches array of tuples, containing a string indicating the target of the patching (for logging) and
|
|
7
|
-
* a patching function that takes a string (pre-patch code) and returns a string (post-patch code)
|
|
8
|
-
* @returns the patched code
|
|
9
|
-
*/
|
|
10
|
-
export declare function patchCodeWithValidations(code: string, patches: [string, (code: string) => string | Promise<string>, opts?: {
|
|
11
|
-
isOptional?: boolean;
|
|
12
|
-
}][]): Promise<string>;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Applies multiple code patches in order to a given piece of code, at each step it validates that the code
|
|
3
|
-
* has actually been patched/changed, if not an error is thrown
|
|
4
|
-
*
|
|
5
|
-
* @param code the code to apply the patches to
|
|
6
|
-
* @param patches array of tuples, containing a string indicating the target of the patching (for logging) and
|
|
7
|
-
* a patching function that takes a string (pre-patch code) and returns a string (post-patch code)
|
|
8
|
-
* @returns the patched code
|
|
9
|
-
*/
|
|
10
|
-
export async function patchCodeWithValidations(code, patches) {
|
|
11
|
-
console.log(`Applying code patches:`);
|
|
12
|
-
let patchedCode = code;
|
|
13
|
-
for (const [target, patchFunction, opts] of patches) {
|
|
14
|
-
console.log(` - patching ${target}`);
|
|
15
|
-
const prePatchCode = patchedCode;
|
|
16
|
-
patchedCode = await patchFunction(patchedCode);
|
|
17
|
-
if (!opts?.isOptional && prePatchCode === patchedCode) {
|
|
18
|
-
throw new Error(`Failed to patch ${target}`);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
console.log(`All ${patches.length} patches applied\n`);
|
|
22
|
-
return patchedCode;
|
|
23
|
-
}
|
|
File without changes
|