@opennextjs/aws 3.4.1 → 3.4.2

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.
@@ -28,14 +28,14 @@ export default class Cache {
28
28
  async getFetchCache(key, softTags, tags) {
29
29
  debug("get fetch cache", { key, softTags, tags });
30
30
  try {
31
- const { value, lastModified } = await globalThis.incrementalCache.get(key, true);
32
- const _lastModified = await globalThis.tagCache.getLastModified(key, lastModified);
31
+ const cachedEntry = await globalThis.incrementalCache.get(key, true);
32
+ if (cachedEntry?.value === undefined)
33
+ return null;
34
+ const _lastModified = await globalThis.tagCache.getLastModified(key, cachedEntry?.lastModified);
33
35
  if (_lastModified === -1) {
34
36
  // If some tags are stale we need to force revalidation
35
37
  return null;
36
38
  }
37
- if (value === undefined)
38
- return null;
39
39
  // For cases where we don't have tags, we need to ensure that the soft tags are not being revalidated
40
40
  // We only need to check for the path as it should already contain all the tags
41
41
  if ((tags ?? []).length === 0) {
@@ -44,7 +44,7 @@ export default class Cache {
44
44
  !tag.endsWith("layout") &&
45
45
  !tag.endsWith("page"));
46
46
  if (path) {
47
- const pathLastModified = await globalThis.tagCache.getLastModified(path.replace("_N_T_/", ""), lastModified);
47
+ const pathLastModified = await globalThis.tagCache.getLastModified(path.replace("_N_T_/", ""), cachedEntry.lastModified);
48
48
  if (pathLastModified === -1) {
49
49
  // In case the path has been revalidated, we don't want to use the fetch cache
50
50
  return null;
@@ -53,7 +53,7 @@ export default class Cache {
53
53
  }
54
54
  return {
55
55
  lastModified: _lastModified,
56
- value: value,
56
+ value: cachedEntry.value,
57
57
  };
58
58
  }
59
59
  catch (e) {
@@ -64,13 +64,17 @@ export default class Cache {
64
64
  }
65
65
  async getIncrementalCache(key) {
66
66
  try {
67
- const { value: cacheData, lastModified } = await globalThis.incrementalCache.get(key, false);
68
- const meta = cacheData?.meta;
69
- const _lastModified = await globalThis.tagCache.getLastModified(key, lastModified);
67
+ const cachedEntry = await globalThis.incrementalCache.get(key, false);
68
+ if (!cachedEntry?.value) {
69
+ return null;
70
+ }
71
+ const meta = cachedEntry.value.meta;
72
+ const _lastModified = await globalThis.tagCache.getLastModified(key, cachedEntry?.lastModified);
70
73
  if (_lastModified === -1) {
71
74
  // If some tags are stale we need to force revalidation
72
75
  return null;
73
76
  }
77
+ const cacheData = cachedEntry?.value;
74
78
  const requestId = globalThis.__openNextAls.getStore()?.requestId ?? "";
75
79
  globalThis.lastModified[requestId] = _lastModified;
76
80
  if (cacheData?.type === "route") {
@@ -45,7 +45,7 @@ export function createCacheAssets(options) {
45
45
  logger.info("Bundling cache assets...");
46
46
  const { appBuildOutputPath, outputDir } = options;
47
47
  const packagePath = buildHelper.getPackagePath(options);
48
- const buildId = buildHelper.getBuildId(appBuildOutputPath);
48
+ const buildId = buildHelper.getBuildId(options);
49
49
  let useTagCache = false;
50
50
  // Copy pages to cache folder
51
51
  const dotNextPath = path.join(appBuildOutputPath, ".next/standalone", packagePath);
@@ -167,7 +167,7 @@ export async function generateOutput(options) {
167
167
  const patterns = "patterns" in value ? value.patterns : ["*"];
168
168
  patterns.forEach((pattern) => {
169
169
  behaviors.push({
170
- pattern: prefixer(pattern.replace(/BUILD_ID/, getBuildId(appBuildOutputPath))),
170
+ pattern: prefixer(pattern.replace(/BUILD_ID/, getBuildId(options))),
171
171
  origin: value.placement === "global" ? undefined : key,
172
172
  edgeFunction: value.placement === "global"
173
173
  ? key
@@ -48,7 +48,7 @@ export declare function traverseFiles(root: string, conditionFn: (paths: Travers
48
48
  */
49
49
  export declare function removeFiles(root: string, conditionFn: (paths: TraversePath) => boolean): void;
50
50
  export declare function getHtmlPages(dotNextPath: string): Set<string>;
51
- export declare function getBuildId(dotNextPath: string): string;
51
+ export declare function getBuildId(options: BuildOptions): string;
52
52
  export declare function getOpenNextVersion(): string;
53
53
  export declare function getNextVersion(appPath: string): string;
54
54
  /**
@@ -101,12 +101,15 @@ export function esbuildSync(esbuildOptions, options) {
101
101
  }
102
102
  export async function esbuildAsync(esbuildOptions, options) {
103
103
  const { openNextVersion, debug, minify } = options;
104
+ // Dump ESBuild build metadata to file in debug mode
105
+ const metafile = debug && esbuildOptions.outfile !== undefined;
104
106
  const result = await buildAsync({
105
107
  target: "esnext",
106
108
  format: "esm",
107
109
  platform: "node",
108
110
  bundle: true,
109
111
  minify,
112
+ metafile,
110
113
  mainFields: ["module", "main"],
111
114
  sourcemap: debug ? "inline" : false,
112
115
  sourcesContent: false,
@@ -129,6 +132,10 @@ export async function esbuildAsync(esbuildOptions, options) {
129
132
  result.errors.forEach((error) => logger.error(error));
130
133
  throw new Error(`There was a problem bundling ${esbuildOptions.entryPoints[0]}.`);
131
134
  }
135
+ if (result.metafile) {
136
+ const metaFile = `${esbuildOptions.outfile}.meta.json`;
137
+ fs.writeFileSync(metaFile, JSON.stringify(result.metafile, null, 2));
138
+ }
132
139
  }
133
140
  /**
134
141
  * Recursively traverse files in a directory and call `callbackFn` when `conditionFn` returns true
@@ -180,9 +187,9 @@ export function getHtmlPages(dotNextPath) {
180
187
  .map(([_, value]) => value.replace(/^pages\//, ""))
181
188
  .reduce((acc, page) => acc.add(page), new Set());
182
189
  }
183
- export function getBuildId(dotNextPath) {
190
+ export function getBuildId(options) {
184
191
  return fs
185
- .readFileSync(path.join(dotNextPath, ".next/BUILD_ID"), "utf-8")
192
+ .readFileSync(path.join(options.appBuildOutputPath, ".next/BUILD_ID"), "utf-8")
186
193
  .trim();
187
194
  }
188
195
  export function getOpenNextVersion() {
@@ -120,7 +120,10 @@ export async function cacheInterceptor(event) {
120
120
  try {
121
121
  const cachedData = await globalThis.incrementalCache.get(localizedPath);
122
122
  debug("cached data in interceptor", cachedData);
123
- if (cachedData.value?.type === "app") {
123
+ if (!cachedData?.value) {
124
+ return event;
125
+ }
126
+ if (cachedData?.value?.type === "app") {
124
127
  // We need to check the tag cache now
125
128
  const _lastModified = await globalThis.tagCache.getLastModified(localizedPath, cachedData.lastModified);
126
129
  if (_lastModified === -1) {
@@ -129,7 +132,7 @@ export async function cacheInterceptor(event) {
129
132
  }
130
133
  }
131
134
  const host = event.headers.host;
132
- switch (cachedData.value?.type) {
135
+ switch (cachedData?.value?.type) {
133
136
  case "app":
134
137
  case "page":
135
138
  return generateResult(event, localizedPath, cachedData.value, cachedData.lastModified);
@@ -166,8 +166,9 @@ export function handleRewrites(event, rewrites) {
166
166
  };
167
167
  }
168
168
  function handleTrailingSlashRedirect(event) {
169
- const url = new URL(event.url, "http://localhost");
170
- const emptyBody = emptyReadableStream();
169
+ // When rawPath is `//domain`, `url.host` would be `domain`.
170
+ // https://github.com/opennextjs/opennextjs-aws/issues/355
171
+ const url = new URL(event.rawPath, "http://localhost");
171
172
  if (
172
173
  // Someone is trying to redirect to a different origin, let's not do that
173
174
  url.host !== "localhost" ||
@@ -176,6 +177,7 @@ function handleTrailingSlashRedirect(event) {
176
177
  event.rawPath.startsWith("/api/")) {
177
178
  return false;
178
179
  }
180
+ const emptyBody = emptyReadableStream();
179
181
  if (NextConfig.trailingSlash &&
180
182
  !event.headers["x-nextjs-data"] &&
181
183
  !event.rawPath.endsWith("/") &&
@@ -77,7 +77,7 @@ const multiTierCache = {
77
77
  }
78
78
  }
79
79
  const result = await S3Cache.get(key, isFetch);
80
- if (result.value) {
80
+ if (result?.value) {
81
81
  localCache.set(key, {
82
82
  value: result.value,
83
83
  lastModified: result.lastModified ?? Date.now(),
@@ -3,7 +3,8 @@ const fetchProxy = {
3
3
  name: "fetch-proxy",
4
4
  // @ts-ignore
5
5
  proxy: async (internalEvent) => {
6
- const { url, headers, method, body } = internalEvent;
6
+ const { url, headers: eventHeaders, method, body } = internalEvent;
7
+ const headers = Object.fromEntries(Object.entries(eventHeaders).filter(([key]) => key.toLowerCase() !== "cf-connecting-ip"));
7
8
  const response = await fetch(url, {
8
9
  method,
9
10
  headers,
@@ -26,6 +26,11 @@ const handler = async (handler, converter) => async (request, env, ctx) => {
26
26
  for (const cookie of cookies) {
27
27
  responseHeaders.append("Set-Cookie", cookie);
28
28
  }
29
+ // TODO(vicb): this is a workaround to make PPR work with `wrangler dev`
30
+ // See https://github.com/cloudflare/workers-sdk/issues/8004
31
+ if (url.hostname === "localhost") {
32
+ responseHeaders.set("Content-Encoding", "identity");
33
+ }
29
34
  const { readable, writable } = new TransformStream({
30
35
  transform(chunk, controller) {
31
36
  controller.enqueue(Uint8Array.from(chunk.chunk ?? chunk));
@@ -41,7 +41,7 @@ export type CacheValue<IsFetch extends boolean> = (IsFetch extends true ? FetchC
41
41
  revalidate?: number | false;
42
42
  };
43
43
  export type IncrementalCache = {
44
- get<IsFetch extends boolean = false>(key: string, isFetch?: IsFetch): Promise<WithLastModified<CacheValue<IsFetch>>>;
44
+ get<IsFetch extends boolean = false>(key: string, isFetch?: IsFetch): Promise<WithLastModified<CacheValue<IsFetch>> | null>;
45
45
  set<IsFetch extends boolean = false>(key: string, value: CacheValue<IsFetch>, isFetch?: IsFetch): Promise<void>;
46
46
  delete(key: string): Promise<void>;
47
47
  name: string;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "access": "public"
4
4
  },
5
5
  "name": "@opennextjs/aws",
6
- "version": "3.4.1",
6
+ "version": "3.4.2",
7
7
  "bin": {
8
8
  "open-next": "./dist/index.js"
9
9
  },