@opennextjs/aws 3.2.0 → 3.2.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.
Files changed (140) hide show
  1. package/README.md +15 -1
  2. package/dist/adapters/cache.d.ts +1 -23
  3. package/dist/adapters/cache.js +22 -18
  4. package/dist/adapters/config/index.js +1 -1
  5. package/dist/adapters/config/util.js +2 -2
  6. package/dist/adapters/dynamo-provider.js +3 -5
  7. package/dist/adapters/edge-adapter.d.ts +0 -3
  8. package/dist/adapters/edge-adapter.js +43 -38
  9. package/dist/adapters/image-optimization-adapter.js +4 -4
  10. package/dist/adapters/logger.d.ts +0 -3
  11. package/dist/adapters/logger.js +3 -5
  12. package/dist/adapters/middleware.js +42 -18
  13. package/dist/adapters/plugins/image-optimization/image-optimization.d.ts +0 -3
  14. package/dist/adapters/plugins/image-optimization/image-optimization.replacement.d.ts +0 -3
  15. package/dist/adapters/revalidate.js +2 -2
  16. package/dist/adapters/server-adapter.d.ts +0 -3
  17. package/dist/adapters/server-adapter.js +3 -1
  18. package/dist/adapters/util.js +2 -2
  19. package/dist/build/bundleNextServer.d.ts +3 -1
  20. package/dist/build/bundleNextServer.js +3 -3
  21. package/dist/build/compileConfig.js +3 -3
  22. package/dist/build/copyTracedFiles.js +16 -27
  23. package/dist/build/createAssets.js +35 -26
  24. package/dist/build/createImageOptimizationBundle.js +4 -1
  25. package/dist/build/createMiddleware.d.ts +4 -4
  26. package/dist/build/createMiddleware.js +16 -19
  27. package/dist/build/createRevalidationBundle.js +1 -1
  28. package/dist/build/createServerBundle.js +34 -45
  29. package/dist/build/createWarmerBundle.js +1 -1
  30. package/dist/build/edge/createEdgeBundle.d.ts +9 -7
  31. package/dist/build/edge/createEdgeBundle.js +19 -14
  32. package/dist/build/generateOutput.js +7 -13
  33. package/dist/build/helper.d.ts +22 -4
  34. package/dist/build/helper.js +26 -12
  35. package/dist/build/installDeps.js +12 -2
  36. package/dist/build/patch/patchedAsyncStorage.js +1 -1
  37. package/dist/build/utils.js +3 -2
  38. package/dist/build/validateConfig.js +1 -0
  39. package/dist/core/createGenericHandler.d.ts +2 -4
  40. package/dist/core/createGenericHandler.js +6 -7
  41. package/dist/core/createMainHandler.d.ts +0 -17
  42. package/dist/core/createMainHandler.js +10 -9
  43. package/dist/core/edgeFunctionHandler.d.ts +1 -51
  44. package/dist/core/patchAsyncStorage.js +5 -6
  45. package/dist/core/requestHandler.js +98 -89
  46. package/dist/core/require-hooks.js +8 -7
  47. package/dist/core/resolve.d.ts +13 -7
  48. package/dist/core/resolve.js +29 -35
  49. package/dist/core/routing/cacheInterceptor.js +12 -13
  50. package/dist/core/routing/i18n/accept-header.js +3 -2
  51. package/dist/core/routing/matcher.d.ts +2 -4
  52. package/dist/core/routing/matcher.js +29 -31
  53. package/dist/core/routing/middleware.js +22 -18
  54. package/dist/core/routing/util.d.ts +0 -13
  55. package/dist/core/routing/util.js +32 -91
  56. package/dist/core/routingHandler.d.ts +2 -0
  57. package/dist/core/routingHandler.js +30 -12
  58. package/dist/core/util.js +5 -3
  59. package/dist/helpers/withSST.d.ts +1 -1
  60. package/dist/http/openNextResponse.d.ts +5 -9
  61. package/dist/http/openNextResponse.js +29 -31
  62. package/dist/http/request.d.ts +0 -3
  63. package/dist/http/request.js +4 -2
  64. package/dist/http/util.d.ts +1 -1
  65. package/dist/http/util.js +8 -12
  66. package/dist/minimize-js.js +19 -19
  67. package/dist/overrides/converters/aws-apigw-v1.d.ts +2 -2
  68. package/dist/overrides/converters/aws-apigw-v1.js +2 -1
  69. package/dist/overrides/converters/aws-apigw-v2.d.ts +2 -2
  70. package/dist/overrides/converters/aws-apigw-v2.js +6 -7
  71. package/dist/overrides/converters/aws-cloudfront.d.ts +2 -2
  72. package/dist/overrides/converters/aws-cloudfront.js +11 -30
  73. package/dist/overrides/converters/dummy.d.ts +1 -1
  74. package/dist/overrides/converters/edge.d.ts +5 -1
  75. package/dist/overrides/converters/edge.js +16 -17
  76. package/dist/overrides/converters/node.d.ts +1 -1
  77. package/dist/overrides/converters/node.js +1 -1
  78. package/dist/overrides/converters/sqs-revalidate.d.ts +1 -1
  79. package/dist/overrides/imageLoader/dummy.d.ts +1 -1
  80. package/dist/overrides/imageLoader/host.d.ts +1 -1
  81. package/dist/overrides/imageLoader/s3.d.ts +1 -1
  82. package/dist/overrides/imageLoader/s3.js +1 -1
  83. package/dist/overrides/incrementalCache/dummy.d.ts +1 -1
  84. package/dist/overrides/incrementalCache/s3-lite.d.ts +1 -1
  85. package/dist/overrides/incrementalCache/s3-lite.js +15 -19
  86. package/dist/overrides/incrementalCache/s3.d.ts +1 -1
  87. package/dist/overrides/incrementalCache/s3.js +1 -1
  88. package/dist/overrides/originResolver/dummy.d.ts +1 -1
  89. package/dist/overrides/originResolver/pattern-env.d.ts +1 -1
  90. package/dist/overrides/originResolver/pattern-env.js +10 -11
  91. package/dist/overrides/proxyExternalRequest/dummy.d.ts +3 -0
  92. package/dist/overrides/proxyExternalRequest/dummy.js +7 -0
  93. package/dist/overrides/proxyExternalRequest/fetch.d.ts +3 -0
  94. package/dist/overrides/proxyExternalRequest/fetch.js +25 -0
  95. package/dist/overrides/proxyExternalRequest/node.d.ts +3 -0
  96. package/dist/overrides/proxyExternalRequest/node.js +67 -0
  97. package/dist/overrides/queue/dummy.d.ts +1 -1
  98. package/dist/overrides/queue/sqs-lite.d.ts +1 -1
  99. package/dist/overrides/queue/sqs-lite.js +7 -9
  100. package/dist/overrides/queue/sqs.d.ts +1 -1
  101. package/dist/overrides/queue/sqs.js +1 -1
  102. package/dist/overrides/tagCache/constants.js +2 -2
  103. package/dist/overrides/tagCache/dummy.d.ts +1 -1
  104. package/dist/overrides/tagCache/dynamodb-lite.d.ts +1 -1
  105. package/dist/overrides/tagCache/dynamodb-lite.js +10 -12
  106. package/dist/overrides/tagCache/dynamodb.d.ts +1 -1
  107. package/dist/overrides/tagCache/dynamodb.js +2 -2
  108. package/dist/overrides/warmer/aws-lambda.d.ts +1 -1
  109. package/dist/overrides/warmer/dummy.d.ts +1 -1
  110. package/dist/overrides/wrappers/aws-lambda-streaming.d.ts +2 -2
  111. package/dist/overrides/wrappers/aws-lambda.d.ts +2 -2
  112. package/dist/overrides/wrappers/cloudflare.d.ts +2 -1
  113. package/dist/overrides/wrappers/cloudflare.js +21 -3
  114. package/dist/overrides/wrappers/dummy.d.ts +2 -2
  115. package/dist/overrides/wrappers/node.d.ts +2 -2
  116. package/dist/overrides/wrappers/node.js +3 -3
  117. package/dist/plugins/edge.d.ts +3 -2
  118. package/dist/plugins/edge.js +33 -34
  119. package/dist/plugins/replacement.d.ts +1 -1
  120. package/dist/plugins/replacement.js +5 -6
  121. package/dist/plugins/resolve.d.ts +3 -1
  122. package/dist/plugins/resolve.js +4 -1
  123. package/dist/types/aws-lambda.d.ts +2 -5
  124. package/dist/types/cache.d.ts +0 -2
  125. package/dist/types/global.d.ts +188 -0
  126. package/dist/types/next-types.d.ts +1 -3
  127. package/dist/types/open-next.d.ts +24 -45
  128. package/dist/types/overrides.d.ts +87 -0
  129. package/dist/utils/promise.d.ts +3 -0
  130. package/dist/utils/promise.js +44 -0
  131. package/dist/utils/stream.d.ts +0 -1
  132. package/package.json +2 -2
  133. package/dist/adapters/plugins/without-routing/requestHandler.d.ts +0 -2
  134. package/dist/adapters/plugins/without-routing/requestHandler.js +0 -10
  135. package/dist/overrides/incrementalCache/types.d.ts +0 -34
  136. package/dist/overrides/queue/types.d.ts +0 -12
  137. package/dist/overrides/tagCache/types.d.ts +0 -11
  138. package/dist/overrides/tagCache/types.js +0 -1
  139. /package/dist/{overrides/incrementalCache/types.js → types/global.js} +0 -0
  140. /package/dist/{overrides/queue/types.js → types/overrides.js} +0 -0
package/README.md CHANGED
@@ -36,7 +36,7 @@ OpenNext aims to support all Next.js 14 features. Some features are work in prog
36
36
  - [x] Image optimization
37
37
  - [x] [NextAuth.js](https://next-auth.js.org)
38
38
  - [x] Running at edge
39
- - [x] [Almost no coldstart (*)](#coldstart)
39
+ - [x] [Almost no coldstart (\*)](#coldstart)
40
40
 
41
41
  ## Who is using OpenNext?
42
42
 
@@ -56,6 +56,20 @@ This will output A LOT of additional logs to the console. This also disable mini
56
56
 
57
57
  You can read more about the configuration in the [docs](https://opennext.js.org/aws/config)
58
58
 
59
+ ## Preleases
60
+
61
+ Besides the standard npm releases we also automatically publish prerelease packages on branch pushes (using [`pkg.pr.new`](https://github.com/stackblitz-labs/pkg.pr.new)):
62
+
63
+ - `https://pkg.pr.new/@opennextjs/aws@main`:
64
+ Updated with every push to the `main` branch, this prerelease contains the most up to date yet (reasonably) stable version of the package.
65
+ - `https://pkg.pr.new/@opennextjs/aws@experimental`
66
+ Updated with every push to the `experimental` branch, this prerelease contains the latest experimental version of the package (containing features that we want to test/experiment on before committing to).
67
+
68
+ Which you can simply install directly with your package manager of choice, for example:
69
+
70
+ ```bash
71
+ npm i https://pkg.pr.new/@opennextjs/aws@main
72
+ ```
59
73
 
60
74
  ## Contribute
61
75
 
@@ -1,7 +1,3 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
- import type { IncrementalCache } from "../overrides/incrementalCache/types.js";
4
- import type { TagCache } from "../overrides/tagCache/types.js";
5
1
  interface CachedFetchValue {
6
2
  kind: "FETCH";
7
3
  data: {
@@ -56,16 +52,6 @@ type IncrementalCacheContext = {
56
52
  fetchIdx?: number | undefined;
57
53
  tags?: string[] | undefined;
58
54
  };
59
- interface CacheHandlerContext {
60
- fs?: never;
61
- dev?: boolean;
62
- flushToDisk?: boolean;
63
- serverDistDir?: string;
64
- maxMemoryCacheSize?: number;
65
- _appDir: boolean;
66
- _requestHeaders: never;
67
- fetchCacheKeyPrefix?: string;
68
- }
69
55
  interface CacheHandlerValue {
70
56
  lastModified?: number;
71
57
  age?: number;
@@ -73,21 +59,13 @@ interface CacheHandlerValue {
73
59
  value: IncrementalCacheValue | null;
74
60
  }
75
61
  export declare function hasCacheExtension(key: string): boolean;
76
- declare global {
77
- var incrementalCache: IncrementalCache;
78
- var tagCache: TagCache;
79
- var disableDynamoDBCache: boolean;
80
- var disableIncrementalCache: boolean;
81
- var lastModified: Record<string, number>;
82
- var isNextAfter15: boolean;
83
- }
84
62
  export default class S3Cache {
85
- constructor(_ctx: CacheHandlerContext);
86
63
  get(key: string, options?: boolean | {
87
64
  fetchCache?: boolean;
88
65
  kindHint?: "app" | "pages" | "fetch";
89
66
  tags?: string[];
90
67
  softTags?: string[];
68
+ kind?: "FETCH";
91
69
  }): Promise<CacheHandlerValue | null>;
92
70
  getFetchCache(key: string, softTags?: string[], tags?: string[]): Promise<CacheHandlerValue | null>;
93
71
  getIncrementalCache(key: string): Promise<CacheHandlerValue | null>;
@@ -1,27 +1,32 @@
1
- import { isBinaryContentType } from "./binary.js";
2
- import { debug, error, warn } from "./logger.js";
1
+ import { isBinaryContentType } from "./binary";
2
+ import { debug, error, warn } from "./logger";
3
3
  /** Beginning single backslash is intentional, to look for the dot + the extension. Do not escape it again. */
4
4
  const CACHE_EXTENSION_REGEX = /\.(cache|fetch)$/;
5
5
  export function hasCacheExtension(key) {
6
6
  return CACHE_EXTENSION_REGEX.test(key);
7
7
  }
8
+ function isFetchCache(options) {
9
+ if (typeof options === "boolean") {
10
+ return options;
11
+ }
12
+ if (typeof options === "object") {
13
+ return (options.kindHint === "fetch" ||
14
+ options.fetchCache ||
15
+ options.kind === "FETCH");
16
+ }
17
+ return false;
18
+ }
8
19
  // We need to use globalThis client here as this class can be defined at load time in next 12 but client is not available at load time
9
20
  export default class S3Cache {
10
- constructor(_ctx) { }
11
21
  async get(key,
12
22
  // fetchCache is for next 13.5 and above, kindHint is for next 14 and above and boolean is for earlier versions
13
23
  options) {
14
24
  if (globalThis.disableIncrementalCache) {
15
25
  return null;
16
26
  }
17
- const isFetchCache = typeof options === "object"
18
- ? options.kindHint
19
- ? options.kindHint === "fetch"
20
- : options.fetchCache
21
- : options;
22
27
  const softTags = typeof options === "object" ? options.softTags : [];
23
28
  const tags = typeof options === "object" ? options.tags : [];
24
- return isFetchCache
29
+ return isFetchCache(options)
25
30
  ? this.getFetchCache(key, softTags, tags)
26
31
  : this.getIncrementalCache(key);
27
32
  }
@@ -76,7 +81,7 @@ export default class S3Cache {
76
81
  // If some tags are stale we need to force revalidation
77
82
  return null;
78
83
  }
79
- const requestId = globalThis.__als.getStore()?.requestId ?? "";
84
+ const requestId = globalThis.__openNextAls.getStore()?.requestId ?? "";
80
85
  globalThis.lastModified[requestId] = _lastModified;
81
86
  if (cacheData?.type === "route") {
82
87
  return {
@@ -91,7 +96,7 @@ export default class S3Cache {
91
96
  },
92
97
  };
93
98
  }
94
- else if (cacheData?.type === "page" || cacheData?.type === "app") {
99
+ if (cacheData?.type === "page" || cacheData?.type === "app") {
95
100
  if (globalThis.isNextAfter15 && cacheData?.type === "app") {
96
101
  return {
97
102
  lastModified: _lastModified,
@@ -116,7 +121,7 @@ export default class S3Cache {
116
121
  },
117
122
  };
118
123
  }
119
- else if (cacheData?.type === "redirect") {
124
+ if (cacheData?.type === "redirect") {
120
125
  return {
121
126
  lastModified: _lastModified,
122
127
  value: {
@@ -125,10 +130,8 @@ export default class S3Cache {
125
130
  },
126
131
  };
127
132
  }
128
- else {
129
- warn("Unknown cache type", cacheData);
130
- return null;
131
- }
133
+ warn("Unknown cache type", cacheData);
134
+ return null;
132
135
  }
133
136
  catch (e) {
134
137
  // We can usually ignore errors here as they are usually due to cache not being found
@@ -142,7 +145,7 @@ export default class S3Cache {
142
145
  }
143
146
  // This one might not even be necessary anymore
144
147
  // Better be safe than sorry
145
- const detachedPromise = globalThis.__als
148
+ const detachedPromise = globalThis.__openNextAls
146
149
  .getStore()
147
150
  ?.pendingPromiseRunner.withResolvers();
148
151
  try {
@@ -152,7 +155,7 @@ export default class S3Cache {
152
155
  else {
153
156
  switch (data.kind) {
154
157
  case "ROUTE":
155
- case "APP_ROUTE":
158
+ case "APP_ROUTE": {
156
159
  const { body, status, headers } = data;
157
160
  await globalThis.incrementalCache.set(key, {
158
161
  type: "route",
@@ -165,6 +168,7 @@ export default class S3Cache {
165
168
  },
166
169
  }, false);
167
170
  break;
171
+ }
168
172
  case "PAGE":
169
173
  case "PAGES": {
170
174
  const { html, pageData, status, headers } = data;
@@ -1,4 +1,4 @@
1
- import path from "path";
1
+ import path from "node:path";
2
2
  import { debug } from "../logger";
3
3
  import { loadAppPathsManifestKeys, loadBuildId, loadConfig, loadConfigHeaders, loadHtmlPages, loadMiddlewareManifest, loadPrerenderManifest,
4
4
  // loadPublicAssets,
@@ -1,5 +1,5 @@
1
- import fs from "fs";
2
- import path from "path";
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
3
  export function loadConfig(nextDir) {
4
4
  const filePath = path.join(nextDir, "required-server-files.json");
5
5
  const json = fs.readFileSync(filePath, "utf-8");
@@ -1,4 +1,4 @@
1
- import { readFileSync } from "fs";
1
+ import { readFileSync } from "node:fs";
2
2
  import { createGenericHandler } from "../core/createGenericHandler.js";
3
3
  import { resolveTagCache } from "../core/resolve.js";
4
4
  const PHYSICAL_RESOURCE_ID = "dynamodb-cache";
@@ -11,19 +11,17 @@ async function defaultHandler(event) {
11
11
  switch (event.requestType) {
12
12
  case "delete":
13
13
  return remove();
14
- case "create":
15
- case "update":
16
14
  default:
17
15
  return insert(event.requestType);
18
16
  }
19
17
  }
20
18
  async function insert(requestType) {
21
- const file = readFileSync(`dynamodb-cache.json`, "utf8");
19
+ const file = readFileSync("dynamodb-cache.json", "utf8");
22
20
  const data = JSON.parse(file);
23
21
  const parsedData = data.map((item) => ({
24
22
  tag: item.tag.S,
25
23
  path: item.path.S,
26
- revalidatedAt: parseInt(item.revalidatedAt.N),
24
+ revalidatedAt: Number.parseInt(item.revalidatedAt.N),
27
25
  }));
28
26
  await tagCache.writeTags(parsedData);
29
27
  return {
@@ -1,6 +1,3 @@
1
- declare global {
2
- var isEdgeRuntime: true;
3
- }
4
1
  export declare const handler: (...args: any[]) => any;
5
2
  declare const _default: {
6
3
  fetch: (...args: any[]) => any;
@@ -1,49 +1,54 @@
1
+ import { runWithOpenNextRequestContext } from "../utils/promise";
1
2
  import { emptyReadableStream } from "../utils/stream";
2
3
  // We import it like that so that the edge plugin can replace it
3
4
  import { NextConfig } from "../adapters/config";
4
5
  import { createGenericHandler } from "../core/createGenericHandler";
5
6
  import { convertBodyToReadableStream, convertToQueryString, } from "../core/routing/util";
7
+ globalThis.__openNextAls = new AsyncLocalStorage();
6
8
  const defaultHandler = async (internalEvent) => {
7
9
  globalThis.isEdgeRuntime = true;
8
- const host = internalEvent.headers.host
9
- ? `https://${internalEvent.headers.host}`
10
- : "http://localhost:3000";
11
- const initialUrl = new URL(internalEvent.rawPath, host);
12
- initialUrl.search = convertToQueryString(internalEvent.query);
13
- const url = initialUrl.toString();
14
- // @ts-expect-error - This is bundled
15
- const handler = await import(`./middleware.mjs`);
16
- const response = await handler.default({
17
- headers: internalEvent.headers,
18
- method: internalEvent.method || "GET",
19
- nextConfig: {
20
- basePath: NextConfig.basePath,
21
- i18n: NextConfig.i18n,
22
- trailingSlash: NextConfig.trailingSlash,
23
- },
24
- url,
25
- body: convertBodyToReadableStream(internalEvent.method, internalEvent.body),
10
+ // We run everything in the async local storage context so that it is available in edge runtime functions
11
+ return runWithOpenNextRequestContext({ isISRRevalidation: false }, async () => {
12
+ const host = internalEvent.headers.host
13
+ ? `https://${internalEvent.headers.host}`
14
+ : "http://localhost:3000";
15
+ const initialUrl = new URL(internalEvent.rawPath, host);
16
+ initialUrl.search = convertToQueryString(internalEvent.query);
17
+ const url = initialUrl.toString();
18
+ // @ts-expect-error - This is bundled
19
+ const handler = await import("./middleware.mjs");
20
+ const response = await handler.default({
21
+ headers: internalEvent.headers,
22
+ method: internalEvent.method || "GET",
23
+ nextConfig: {
24
+ basePath: NextConfig.basePath,
25
+ i18n: NextConfig.i18n,
26
+ trailingSlash: NextConfig.trailingSlash,
27
+ },
28
+ url,
29
+ body: convertBodyToReadableStream(internalEvent.method, internalEvent.body),
30
+ });
31
+ const responseHeaders = {};
32
+ response.headers.forEach((value, key) => {
33
+ if (key.toLowerCase() === "set-cookie") {
34
+ responseHeaders[key] = responseHeaders[key]
35
+ ? [...responseHeaders[key], value]
36
+ : [value];
37
+ }
38
+ else {
39
+ responseHeaders[key] = value;
40
+ }
41
+ });
42
+ const body = response.body ?? emptyReadableStream();
43
+ return {
44
+ type: "core",
45
+ statusCode: response.status,
46
+ headers: responseHeaders,
47
+ body: body,
48
+ // Do we need to handle base64 encoded response?
49
+ isBase64Encoded: false,
50
+ };
26
51
  });
27
- const responseHeaders = {};
28
- response.headers.forEach((value, key) => {
29
- if (key.toLowerCase() === "set-cookie") {
30
- responseHeaders[key] = responseHeaders[key]
31
- ? [...responseHeaders[key], value]
32
- : [value];
33
- }
34
- else {
35
- responseHeaders[key] = value;
36
- }
37
- });
38
- const body = response.body ?? emptyReadableStream();
39
- return {
40
- type: "core",
41
- statusCode: response.status,
42
- headers: responseHeaders,
43
- body: body,
44
- // Do we need to handle base64 encoded response?
45
- isBase64Encoded: false,
46
- };
47
52
  };
48
53
  export const handler = await createGenericHandler({
49
54
  handler: defaultHandler,
@@ -46,7 +46,7 @@ export async function defaultHandler(event, streamCreator) {
46
46
  // It might be useful for cases where the user wants to use a different host than the one in the request
47
47
  // It could even allow to have multiple hosts for the image optimization by setting the HOST environment variable in the wrapper for example
48
48
  if (!process.env.HOST) {
49
- const headersHost = headers["x-forwarded-host"] || headers["host"];
49
+ const headersHost = headers["x-forwarded-host"] || headers.host;
50
50
  process.env.HOST = headersHost;
51
51
  }
52
52
  const imageParams = validateImageParams(headers, queryString === null ? undefined : queryString);
@@ -104,7 +104,7 @@ function buildSuccessResponse(result, streamCreator, etag) {
104
104
  };
105
105
  debug("result", result);
106
106
  if (etag) {
107
- headers["ETag"] = etag;
107
+ headers.ETag = etag;
108
108
  }
109
109
  if (streamCreator) {
110
110
  const response = new OpenNextNodeResponse(() => void 0, async () => void 0, streamCreator);
@@ -125,7 +125,7 @@ function buildFailureResponse(e, streamCreator) {
125
125
  const response = new OpenNextNodeResponse(() => void 0, async () => void 0, streamCreator);
126
126
  response.writeHead(500, {
127
127
  Vary: "Accept",
128
- "Cache-Control": `public,max-age=60,immutable`,
128
+ "Cache-Control": "public,max-age=60,immutable",
129
129
  "Content-Type": "application/json",
130
130
  });
131
131
  response.end(e?.message || e?.toString() || "An error occurred");
@@ -137,7 +137,7 @@ function buildFailureResponse(e, streamCreator) {
137
137
  headers: {
138
138
  Vary: "Accept",
139
139
  // For failed images, allow client to retry after 1 minute.
140
- "Cache-Control": `public,max-age=60,immutable`,
140
+ "Cache-Control": "public,max-age=60,immutable",
141
141
  "Content-Type": "application/json",
142
142
  },
143
143
  body: toReadableStream(e?.message || e?.toString() || "An error occurred"),
@@ -1,6 +1,3 @@
1
- declare global {
2
- var openNextDebug: boolean;
3
- }
4
1
  export declare function debug(...args: any[]): void;
5
2
  export declare function warn(...args: any[]): void;
6
3
  export declare function error(...args: any[]): void;
@@ -29,14 +29,12 @@ export function error(...args) {
29
29
  debug(...args);
30
30
  return;
31
31
  }
32
- else if (error.logLevel === 1) {
32
+ if (error.logLevel === 1) {
33
33
  warn(...args);
34
34
  return;
35
35
  }
36
- else {
37
- console.error(...args);
38
- return;
39
- }
36
+ console.error(...args);
37
+ return;
40
38
  }
41
39
  else {
42
40
  console.error(...args);
@@ -1,32 +1,56 @@
1
- import { debug } from "../adapters/logger";
1
+ import { runWithOpenNextRequestContext } from "../utils/promise";
2
+ import { debug, error } from "../adapters/logger";
2
3
  import { createGenericHandler } from "../core/createGenericHandler";
3
- import { resolveIncrementalCache, resolveOriginResolver, resolveQueue, resolveTagCache, } from "../core/resolve";
4
+ import { resolveIncrementalCache, resolveOriginResolver, resolveProxyRequest, resolveQueue, resolveTagCache, } from "../core/resolve";
4
5
  import routingHandler from "../core/routingHandler";
5
6
  globalThis.internalFetch = fetch;
7
+ globalThis.__openNextAls = new AsyncLocalStorage();
6
8
  const defaultHandler = async (internalEvent) => {
7
9
  const originResolver = await resolveOriginResolver(globalThis.openNextConfig.middleware?.originResolver);
10
+ const externalRequestProxy = await resolveProxyRequest(globalThis.openNextConfig.middleware?.override?.proxyExternalRequest);
8
11
  //#override includeCacheInMiddleware
9
12
  globalThis.tagCache = await resolveTagCache(globalThis.openNextConfig.middleware?.override?.tagCache);
10
13
  globalThis.queue = await resolveQueue(globalThis.openNextConfig.middleware?.override?.queue);
11
14
  globalThis.incrementalCache = await resolveIncrementalCache(globalThis.openNextConfig.middleware?.override?.incrementalCache);
12
15
  //#endOverride
13
- const result = await routingHandler(internalEvent);
14
- if ("internalEvent" in result) {
15
- debug("Middleware intercepted event", internalEvent);
16
- let origin = false;
17
- if (!result.isExternalRewrite) {
18
- origin = await originResolver.resolve(result.internalEvent.rawPath);
16
+ // We run everything in the async local storage context so that it is available in the external middleware
17
+ return runWithOpenNextRequestContext({ isISRRevalidation: internalEvent.headers["x-isr"] === "1" }, async () => {
18
+ const result = await routingHandler(internalEvent);
19
+ if ("internalEvent" in result) {
20
+ debug("Middleware intercepted event", internalEvent);
21
+ if (!result.isExternalRewrite) {
22
+ const origin = await originResolver.resolve(result.internalEvent.rawPath);
23
+ return {
24
+ type: "middleware",
25
+ internalEvent: result.internalEvent,
26
+ isExternalRewrite: result.isExternalRewrite,
27
+ origin,
28
+ isISR: result.isISR,
29
+ };
30
+ }
31
+ try {
32
+ return externalRequestProxy.proxy(result.internalEvent);
33
+ }
34
+ catch (e) {
35
+ error("External request failed.", e);
36
+ return {
37
+ type: "middleware",
38
+ internalEvent: {
39
+ ...result.internalEvent,
40
+ rawPath: "/500",
41
+ url: "/500",
42
+ method: "GET",
43
+ },
44
+ // On error we need to rewrite to the 500 page which is an internal rewrite
45
+ isExternalRewrite: false,
46
+ origin: false,
47
+ isISR: result.isISR,
48
+ };
49
+ }
19
50
  }
20
- return {
21
- type: "middleware",
22
- internalEvent: result.internalEvent,
23
- isExternalRewrite: result.isExternalRewrite,
24
- origin,
25
- isISR: result.isISR,
26
- };
27
- }
28
- debug("Middleware response", result);
29
- return result;
51
+ debug("Middleware response", result);
52
+ return result;
53
+ });
30
54
  };
31
55
  export const handler = await createGenericHandler({
32
56
  handler: defaultHandler,
@@ -1,6 +1,3 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
- /// <reference types="node" />
4
1
  import type { IncomingMessage, ServerResponse } from "node:http";
5
2
  import type { APIGatewayProxyEventHeaders } from "aws-lambda";
6
3
  import type { NextConfig } from "next/dist/server/config-shared";
@@ -1,6 +1,3 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
- /// <reference types="node" />
4
1
  import type { IncomingMessage, ServerResponse } from "node:http";
5
2
  import type { APIGatewayProxyEventHeaders } from "aws-lambda";
6
3
  import type { NextConfig } from "next/dist/server/config-shared";
@@ -8,7 +8,7 @@ const defaultHandler = async (event) => {
8
8
  const failedRecords = [];
9
9
  for (const record of event.records) {
10
10
  const { host, url } = record;
11
- debug(`Revalidating stale page`, { host, url });
11
+ debug("Revalidating stale page", { host, url });
12
12
  // Make a HEAD request to the page to revalidate it. This will trigger
13
13
  // the page to be re-rendered and cached in S3
14
14
  // - HEAD request is used b/c it's not necessary to make a GET request
@@ -39,7 +39,7 @@ const defaultHandler = async (event) => {
39
39
  resolve(res);
40
40
  });
41
41
  req.on("error", (err) => {
42
- error(`Error revalidating page`, { host, url });
42
+ error("Error revalidating page", { host, url });
43
43
  reject(err);
44
44
  });
45
45
  req.end();
@@ -1,4 +1 @@
1
- declare global {
2
- var internalFetch: typeof fetch;
3
- }
4
1
  export declare const handler: (...args: any[]) => any;
@@ -8,6 +8,7 @@ import { setNodeEnv } from "./util.js";
8
8
  setNodeEnv();
9
9
  setBuildIdEnv();
10
10
  setNextjsServerWorkingDirectory();
11
+ // Because next is messing with fetch, we have to make sure that we use an untouched version of fetch
11
12
  globalThis.internalFetch = fetch;
12
13
  /////////////
13
14
  // Handler //
@@ -17,7 +18,8 @@ export const handler = await createMainHandler();
17
18
  // Helper functions //
18
19
  //////////////////////
19
20
  function setNextjsServerWorkingDirectory() {
20
- // WORKAROUND: Set `NextServer` working directory (AWS specific) — https://github.com/serverless-stack/open-next#workaround-set-nextserver-working-directory-aws-specific
21
+ // WORKAROUND: Set `NextServer` working directory (AWS specific)
22
+ // See https://opennext.js.org/aws/v2/advanced/workaround#workaround-set-nextserver-working-directory-aws-specific
21
23
  process.chdir(__dirname);
22
24
  }
23
25
  function setBuildIdEnv() {
@@ -23,6 +23,6 @@ export function parseNumberFromEnv(envValue) {
23
23
  if (typeof envValue !== "string") {
24
24
  return envValue;
25
25
  }
26
- const parsedValue = parseInt(envValue);
27
- return isNaN(parsedValue) ? undefined : parsedValue;
26
+ const parsedValue = Number.parseInt(envValue);
27
+ return Number.isNaN(parsedValue) ? undefined : parsedValue;
28
28
  }
@@ -1 +1,3 @@
1
- export declare function bundleNextServer(outputDir: string, appPath: string): Promise<void>;
1
+ export declare function bundleNextServer(outputDir: string, appPath: string, { debug }: {
2
+ debug?: boolean | undefined;
3
+ }): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
+ import path from "node:path";
2
3
  import { build } from "esbuild";
3
- import path from "path";
4
4
  const externals = [
5
5
  // This one was causing trouble, don't know why
6
6
  "../experimental/testmode/server",
@@ -35,7 +35,7 @@ const externals = [
35
35
  // Adding it cause to add a lot of unnecessary deps
36
36
  "next/dist/compiled/next-server",
37
37
  ];
38
- export async function bundleNextServer(outputDir, appPath) {
38
+ export async function bundleNextServer(outputDir, appPath, { debug = false }) {
39
39
  const require = createRequire(`${appPath}/package.json`);
40
40
  const entrypoint = require.resolve("next/dist/esm/server/next-server.js");
41
41
  await build({
@@ -46,7 +46,7 @@ export async function bundleNextServer(outputDir, appPath) {
46
46
  // packages: "external",
47
47
  format: "cjs",
48
48
  external: externals,
49
- minify: true,
49
+ minify: !debug,
50
50
  outfile: path.join(outputDir, "next-server.runtime.prod.js"),
51
51
  sourcemap: false,
52
52
  plugins: [
@@ -23,7 +23,7 @@ export async function compileOpenNextConfig(baseDir, openNextConfigPath, nodeExt
23
23
  configPath = `file://${configPath}`;
24
24
  const config = (await import(configPath)).default;
25
25
  if (!config || !config.default) {
26
- logger.error(`config.default cannot be empty, it should be at least {}, see more info here: https://opennext.js.org/config#configuration-file`);
26
+ logger.error("config.default cannot be empty, it should be at least {}, see more info here: https://opennext.js.org/config#configuration-file");
27
27
  process.exit(1);
28
28
  }
29
29
  validateConfig(config);
@@ -42,6 +42,7 @@ export async function compileOpenNextConfig(baseDir, openNextConfigPath, nodeExt
42
42
  }
43
43
  export function compileOpenNextConfigNode(sourcePath, outputDir, externals) {
44
44
  const outputPath = path.join(outputDir, "open-next.config.mjs");
45
+ logger.debug("Compiling open-next.config.ts for Node.", outputPath);
45
46
  //Check if open-next.config.ts exists
46
47
  if (!fs.existsSync(sourcePath)) {
47
48
  //Create a simple open-next.config.mjs file
@@ -71,7 +72,7 @@ export function compileOpenNextConfigNode(sourcePath, outputDir, externals) {
71
72
  }
72
73
  export function compileOpenNextConfigEdge(sourcePath, outputDir, externals) {
73
74
  const outputPath = path.join(outputDir, "open-next.config.edge.mjs");
74
- logger.info("Compiling open-next.config.ts for edge runtime.", outputPath);
75
+ logger.debug("Compiling open-next.config.ts for edge runtime.", outputPath);
75
76
  buildSync({
76
77
  entryPoints: [sourcePath],
77
78
  outfile: outputPath,
@@ -82,5 +83,4 @@ export function compileOpenNextConfigEdge(sourcePath, outputDir, externals) {
82
83
  platform: "browser",
83
84
  external: externals,
84
85
  });
85
- logger.info("Compiled open-next.config.ts for edge runtime.");
86
86
  }