@opennextjs/aws 3.1.4

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 (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +94 -0
  3. package/dist/adapters/binary.d.ts +1 -0
  4. package/dist/adapters/binary.js +63 -0
  5. package/dist/adapters/cache.d.ts +96 -0
  6. package/dist/adapters/cache.js +278 -0
  7. package/dist/adapters/config/index.d.ts +27 -0
  8. package/dist/adapters/config/index.js +21 -0
  9. package/dist/adapters/config/util.d.ts +28 -0
  10. package/dist/adapters/config/util.js +84 -0
  11. package/dist/adapters/dynamo-provider.d.ts +8 -0
  12. package/dist/adapters/dynamo-provider.js +42 -0
  13. package/dist/adapters/edge-adapter.d.ts +8 -0
  14. package/dist/adapters/edge-adapter.js +54 -0
  15. package/dist/adapters/image-optimization-adapter.d.ts +4 -0
  16. package/dist/adapters/image-optimization-adapter.js +193 -0
  17. package/dist/adapters/logger.d.ts +13 -0
  18. package/dist/adapters/logger.js +51 -0
  19. package/dist/adapters/middleware.d.ts +5 -0
  20. package/dist/adapters/middleware.js +84 -0
  21. package/dist/adapters/plugins/14.1/util.d.ts +1 -0
  22. package/dist/adapters/plugins/14.1/util.js +29 -0
  23. package/dist/adapters/plugins/image-optimization/image-optimization.d.ts +11 -0
  24. package/dist/adapters/plugins/image-optimization/image-optimization.js +14 -0
  25. package/dist/adapters/plugins/image-optimization/image-optimization.replacement.d.ts +11 -0
  26. package/dist/adapters/plugins/image-optimization/image-optimization.replacement.js +22 -0
  27. package/dist/adapters/plugins/without-routing/requestHandler.d.ts +2 -0
  28. package/dist/adapters/plugins/without-routing/requestHandler.js +10 -0
  29. package/dist/adapters/revalidate.d.ts +9 -0
  30. package/dist/adapters/revalidate.js +71 -0
  31. package/dist/adapters/server-adapter.d.ts +4 -0
  32. package/dist/adapters/server-adapter.js +27 -0
  33. package/dist/adapters/util.d.ts +10 -0
  34. package/dist/adapters/util.js +28 -0
  35. package/dist/adapters/warmer-function.d.ts +12 -0
  36. package/dist/adapters/warmer-function.js +80 -0
  37. package/dist/build/bundleNextServer.d.ts +1 -0
  38. package/dist/build/bundleNextServer.js +87 -0
  39. package/dist/build/compileConfig.d.ts +3 -0
  40. package/dist/build/compileConfig.js +64 -0
  41. package/dist/build/copyTracedFiles.d.ts +1 -0
  42. package/dist/build/copyTracedFiles.js +207 -0
  43. package/dist/build/createServerBundle.d.ts +3 -0
  44. package/dist/build/createServerBundle.js +228 -0
  45. package/dist/build/edge/createEdgeBundle.d.ts +20 -0
  46. package/dist/build/edge/createEdgeBundle.js +149 -0
  47. package/dist/build/generateOutput.d.ts +2 -0
  48. package/dist/build/generateOutput.js +239 -0
  49. package/dist/build/helper.d.ts +33 -0
  50. package/dist/build/helper.js +193 -0
  51. package/dist/build/patch/patchedAsyncStorage.d.ts +5 -0
  52. package/dist/build/patch/patchedAsyncStorage.js +16 -0
  53. package/dist/build/validateConfig.d.ts +2 -0
  54. package/dist/build/validateConfig.js +76 -0
  55. package/dist/build.d.ts +7 -0
  56. package/dist/build.js +533 -0
  57. package/dist/cache/incremental/s3-lite.d.ts +3 -0
  58. package/dist/cache/incremental/s3-lite.js +72 -0
  59. package/dist/cache/incremental/s3.d.ts +3 -0
  60. package/dist/cache/incremental/s3.js +44 -0
  61. package/dist/cache/incremental/types.d.ts +34 -0
  62. package/dist/cache/incremental/types.js +1 -0
  63. package/dist/cache/next-types.d.ts +62 -0
  64. package/dist/cache/next-types.js +1 -0
  65. package/dist/cache/tag/constants.d.ts +2 -0
  66. package/dist/cache/tag/constants.js +17 -0
  67. package/dist/cache/tag/dynamodb-lite.d.ts +3 -0
  68. package/dist/cache/tag/dynamodb-lite.js +174 -0
  69. package/dist/cache/tag/dynamodb.d.ts +3 -0
  70. package/dist/cache/tag/dynamodb.js +129 -0
  71. package/dist/cache/tag/types.d.ts +11 -0
  72. package/dist/cache/tag/types.js +1 -0
  73. package/dist/converters/aws-apigw-v1.d.ts +3 -0
  74. package/dist/converters/aws-apigw-v1.js +89 -0
  75. package/dist/converters/aws-apigw-v2.d.ts +3 -0
  76. package/dist/converters/aws-apigw-v2.js +99 -0
  77. package/dist/converters/aws-cloudfront.d.ts +3 -0
  78. package/dist/converters/aws-cloudfront.js +170 -0
  79. package/dist/converters/dummy.d.ts +7 -0
  80. package/dist/converters/dummy.js +16 -0
  81. package/dist/converters/edge.d.ts +6 -0
  82. package/dist/converters/edge.js +88 -0
  83. package/dist/converters/node.d.ts +3 -0
  84. package/dist/converters/node.js +45 -0
  85. package/dist/converters/sqs-revalidate.d.ts +4 -0
  86. package/dist/converters/sqs-revalidate.js +22 -0
  87. package/dist/converters/utils.d.ts +1 -0
  88. package/dist/converters/utils.js +9 -0
  89. package/dist/core/createGenericHandler.d.ts +11 -0
  90. package/dist/core/createGenericHandler.js +16 -0
  91. package/dist/core/createMainHandler.d.ts +18 -0
  92. package/dist/core/createMainHandler.js +24 -0
  93. package/dist/core/edgeFunctionHandler.d.ts +54 -0
  94. package/dist/core/edgeFunctionHandler.js +21 -0
  95. package/dist/core/patchAsyncStorage.d.ts +1 -0
  96. package/dist/core/patchAsyncStorage.js +16 -0
  97. package/dist/core/requestHandler.d.ts +3 -0
  98. package/dist/core/requestHandler.js +162 -0
  99. package/dist/core/require-hooks.d.ts +3 -0
  100. package/dist/core/require-hooks.js +102 -0
  101. package/dist/core/resolve.d.ts +31 -0
  102. package/dist/core/resolve.js +81 -0
  103. package/dist/core/routing/cacheInterceptor.d.ts +2 -0
  104. package/dist/core/routing/cacheInterceptor.js +162 -0
  105. package/dist/core/routing/i18n/accept-header.d.ts +1 -0
  106. package/dist/core/routing/i18n/accept-header.js +101 -0
  107. package/dist/core/routing/i18n/index.d.ts +2 -0
  108. package/dist/core/routing/i18n/index.js +36 -0
  109. package/dist/core/routing/matcher.d.ts +25 -0
  110. package/dist/core/routing/matcher.js +294 -0
  111. package/dist/core/routing/middleware.d.ts +7 -0
  112. package/dist/core/routing/middleware.js +167 -0
  113. package/dist/core/routing/util.d.ts +105 -0
  114. package/dist/core/routing/util.js +415 -0
  115. package/dist/core/routingHandler.d.ts +8 -0
  116. package/dist/core/routingHandler.js +127 -0
  117. package/dist/core/util.d.ts +5 -0
  118. package/dist/core/util.js +84 -0
  119. package/dist/helpers/withCloudflare.d.ts +65 -0
  120. package/dist/helpers/withCloudflare.js +58 -0
  121. package/dist/helpers/withSST.d.ts +54 -0
  122. package/dist/helpers/withSST.js +28 -0
  123. package/dist/http/index.d.ts +2 -0
  124. package/dist/http/index.js +4 -0
  125. package/dist/http/openNextResponse.d.ts +78 -0
  126. package/dist/http/openNextResponse.js +281 -0
  127. package/dist/http/request.d.ts +12 -0
  128. package/dist/http/request.js +35 -0
  129. package/dist/http/util.d.ts +4 -0
  130. package/dist/http/util.js +34 -0
  131. package/dist/index.d.ts +2 -0
  132. package/dist/index.js +37 -0
  133. package/dist/logger.d.ts +12 -0
  134. package/dist/logger.js +13 -0
  135. package/dist/minimize-js.d.ts +1 -0
  136. package/dist/minimize-js.js +101 -0
  137. package/dist/overrides/imageLoader/host.d.ts +3 -0
  138. package/dist/overrides/imageLoader/host.js +29 -0
  139. package/dist/overrides/imageLoader/s3.d.ts +3 -0
  140. package/dist/overrides/imageLoader/s3.js +33 -0
  141. package/dist/plugins/edge.d.ts +15 -0
  142. package/dist/plugins/edge.js +157 -0
  143. package/dist/plugins/replacement.d.ts +42 -0
  144. package/dist/plugins/replacement.js +74 -0
  145. package/dist/plugins/resolve.d.ts +18 -0
  146. package/dist/plugins/resolve.js +45 -0
  147. package/dist/queue/sqs-lite.d.ts +3 -0
  148. package/dist/queue/sqs-lite.js +52 -0
  149. package/dist/queue/sqs.d.ts +3 -0
  150. package/dist/queue/sqs.js +20 -0
  151. package/dist/queue/types.d.ts +12 -0
  152. package/dist/queue/types.js +1 -0
  153. package/dist/types/aws-lambda.d.ts +22 -0
  154. package/dist/types/aws-lambda.js +1 -0
  155. package/dist/types/next-types.d.ts +155 -0
  156. package/dist/types/next-types.js +2 -0
  157. package/dist/types/open-next.d.ts +303 -0
  158. package/dist/types/open-next.js +1 -0
  159. package/dist/utils/error.d.ts +23 -0
  160. package/dist/utils/error.js +32 -0
  161. package/dist/utils/fetch.d.ts +2 -0
  162. package/dist/utils/fetch.js +23 -0
  163. package/dist/utils/promise.d.ts +18 -0
  164. package/dist/utils/promise.js +48 -0
  165. package/dist/utils/stream.d.ts +5 -0
  166. package/dist/utils/stream.js +30 -0
  167. package/dist/wrappers/aws-lambda-streaming.d.ts +7 -0
  168. package/dist/wrappers/aws-lambda-streaming.js +88 -0
  169. package/dist/wrappers/aws-lambda.d.ts +7 -0
  170. package/dist/wrappers/aws-lambda.js +39 -0
  171. package/dist/wrappers/cloudflare.d.ts +11 -0
  172. package/dist/wrappers/cloudflare.js +20 -0
  173. package/dist/wrappers/node.d.ts +7 -0
  174. package/dist/wrappers/node.js +57 -0
  175. package/package.json +66 -0
@@ -0,0 +1,162 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { IncomingMessage, } from "../http/index.js";
3
+ import { DetachedPromiseRunner } from "../utils/promise";
4
+ import { debug, error, warn } from "../adapters/logger";
5
+ import { patchAsyncStorage } from "./patchAsyncStorage";
6
+ import { convertRes, createServerResponse, proxyRequest } from "./routing/util";
7
+ import routingHandler from "./routingHandler";
8
+ import { requestHandler, setNextjsPrebundledReact } from "./util";
9
+ // This is used to identify requests in the cache
10
+ globalThis.__als = new AsyncLocalStorage();
11
+ patchAsyncStorage();
12
+ export async function openNextHandler(internalEvent, responseStreaming) {
13
+ if (internalEvent.headers["x-forwarded-host"]) {
14
+ internalEvent.headers.host = internalEvent.headers["x-forwarded-host"];
15
+ }
16
+ debug("internalEvent", internalEvent);
17
+ //#override withRouting
18
+ let preprocessResult = {
19
+ internalEvent: internalEvent,
20
+ isExternalRewrite: false,
21
+ origin: false,
22
+ isISR: false,
23
+ };
24
+ try {
25
+ preprocessResult = await routingHandler(internalEvent);
26
+ }
27
+ catch (e) {
28
+ warn("Routing failed.", e);
29
+ }
30
+ //#endOverride
31
+ const headers = "type" in preprocessResult
32
+ ? preprocessResult.headers
33
+ : preprocessResult.internalEvent.headers;
34
+ const overwrittenResponseHeaders = Object.entries("type" in preprocessResult
35
+ ? preprocessResult.headers
36
+ : preprocessResult.internalEvent.headers).reduce((acc, [key, value]) => {
37
+ if (!key.startsWith("x-middleware-response-")) {
38
+ return acc;
39
+ }
40
+ else {
41
+ const newKey = key.replace("x-middleware-response-", "");
42
+ delete headers[key];
43
+ headers[newKey] = value;
44
+ return { ...acc, [newKey]: value };
45
+ }
46
+ }, {});
47
+ if ("type" in preprocessResult) {
48
+ // // res is used only in the streaming case
49
+ if (responseStreaming) {
50
+ const res = createServerResponse(internalEvent, headers, responseStreaming);
51
+ res.statusCode = preprocessResult.statusCode;
52
+ res.flushHeaders();
53
+ const [bodyToConsume, bodyToReturn] = preprocessResult.body.tee();
54
+ for await (const chunk of bodyToConsume) {
55
+ res.write(chunk);
56
+ }
57
+ res.end();
58
+ preprocessResult.body = bodyToReturn;
59
+ }
60
+ return preprocessResult;
61
+ }
62
+ else {
63
+ const preprocessedEvent = preprocessResult.internalEvent;
64
+ debug("preprocessedEvent", preprocessedEvent);
65
+ const reqProps = {
66
+ method: preprocessedEvent.method,
67
+ url: preprocessedEvent.url,
68
+ //WORKAROUND: We pass this header to the serverless function to mimic a prefetch request which will not trigger revalidation since we handle revalidation differently
69
+ // There is 3 way we can handle revalidation:
70
+ // 1. We could just let the revalidation go as normal, but due to race condtions the revalidation will be unreliable
71
+ // 2. We could alter the lastModified time of our cache to make next believe that the cache is fresh, but this could cause issues with stale data since the cdn will cache the stale data as if it was fresh
72
+ // 3. OUR CHOICE: We could pass a purpose prefetch header to the serverless function to make next believe that the request is a prefetch request and not trigger revalidation (This could potentially break in the future if next changes the behavior of prefetch requests)
73
+ headers: { ...headers, purpose: "prefetch" },
74
+ body: preprocessedEvent.body,
75
+ remoteAddress: preprocessedEvent.remoteAddress,
76
+ };
77
+ const requestId = Math.random().toString(36);
78
+ const pendingPromiseRunner = new DetachedPromiseRunner();
79
+ const isISRRevalidation = headers["x-isr"] === "1";
80
+ const mergeHeadersPriority = globalThis.openNextConfig.dangerous
81
+ ?.headersAndCookiesPriority
82
+ ? globalThis.openNextConfig.dangerous.headersAndCookiesPriority(preprocessedEvent)
83
+ : "middleware";
84
+ const internalResult = await globalThis.__als.run({
85
+ requestId,
86
+ pendingPromiseRunner,
87
+ isISRRevalidation,
88
+ mergeHeadersPriority,
89
+ }, async () => {
90
+ const preprocessedResult = preprocessResult;
91
+ const req = new IncomingMessage(reqProps);
92
+ const res = createServerResponse(preprocessedEvent, overwrittenResponseHeaders, responseStreaming);
93
+ await processRequest(req, res, preprocessedEvent, preprocessedResult.isExternalRewrite);
94
+ const { statusCode, headers, isBase64Encoded, body } = convertRes(res);
95
+ const internalResult = {
96
+ type: internalEvent.type,
97
+ statusCode,
98
+ headers,
99
+ body,
100
+ isBase64Encoded,
101
+ };
102
+ // reset lastModified. We need to do this to avoid memory leaks
103
+ delete globalThis.lastModified[requestId];
104
+ await pendingPromiseRunner.await();
105
+ return internalResult;
106
+ });
107
+ return internalResult;
108
+ }
109
+ }
110
+ async function processRequest(req, res, internalEvent, isExternalRewrite) {
111
+ // @ts-ignore
112
+ // Next.js doesn't parse body if the property exists
113
+ // https://github.com/dougmoscrop/serverless-http/issues/227
114
+ delete req.body;
115
+ try {
116
+ // `serverHandler` is replaced at build time depending on user's
117
+ // nextjs version to patch Nextjs 13.4.x and future breaking changes.
118
+ const { rawPath } = internalEvent;
119
+ if (isExternalRewrite) {
120
+ return proxyRequest(internalEvent, res);
121
+ }
122
+ else {
123
+ //#override applyNextjsPrebundledReact
124
+ setNextjsPrebundledReact(rawPath);
125
+ //#endOverride
126
+ // Next Server
127
+ await requestHandler(req, res);
128
+ }
129
+ }
130
+ catch (e) {
131
+ // This might fail when using bundled next, importing won't do the trick either
132
+ if (e.constructor.name === "NoFallbackError") {
133
+ // Do we need to handle _not-found
134
+ // Ideally this should never get triggered and be intercepted by the routing handler
135
+ await tryRenderError("404", res, internalEvent);
136
+ }
137
+ else {
138
+ error("NextJS request failed.", e);
139
+ await tryRenderError("500", res, internalEvent);
140
+ }
141
+ }
142
+ }
143
+ async function tryRenderError(type, res, internalEvent) {
144
+ try {
145
+ const _req = new IncomingMessage({
146
+ method: "GET",
147
+ url: `/${type}`,
148
+ headers: internalEvent.headers,
149
+ body: internalEvent.body,
150
+ remoteAddress: internalEvent.remoteAddress,
151
+ });
152
+ await requestHandler(_req, res);
153
+ }
154
+ catch (e) {
155
+ error("NextJS request failed.", e);
156
+ res.setHeader("Content-Type", "application/json");
157
+ res.end(JSON.stringify({
158
+ message: "Server failed to respond.",
159
+ details: e,
160
+ }, null, 2));
161
+ }
162
+ }
@@ -0,0 +1,3 @@
1
+ import type { NextConfig } from "../types/next-types.js";
2
+ export declare function overrideHooks(config: NextConfig): void;
3
+ export declare function applyOverride(): void;
@@ -0,0 +1,102 @@
1
+ // Synchronously inject a require hook for webpack and webpack/. It's required to use the internal ncc webpack version.
2
+ // This is needed for userland plugins to attach to the same webpack instance as Next.js'.
3
+ // Individually compiled modules are as defined for the compilation in bundles/webpack/packages/*.
4
+ import { error } from "../adapters/logger.js";
5
+ // This module will only be loaded once per process.
6
+ const mod = require("module");
7
+ const resolveFilename = mod._resolveFilename;
8
+ const hookPropertyMapApp = new Map();
9
+ const hookPropertyMapPage = new Map();
10
+ export function overrideHooks(config) {
11
+ try {
12
+ overrideDefault();
13
+ overrideReact(config);
14
+ }
15
+ catch (e) {
16
+ error("Failed to override Next.js require hooks.", e);
17
+ throw e;
18
+ }
19
+ }
20
+ function addHookAliases(aliases = [], type) {
21
+ for (const [key, value] of aliases) {
22
+ type === "app"
23
+ ? hookPropertyMapApp.set(key, value)
24
+ : hookPropertyMapPage.set(key, value);
25
+ }
26
+ }
27
+ const baseOverrides = {
28
+ react: "next/dist/compiled/react",
29
+ "react/package.json": "next/dist/compiled/react/package.json",
30
+ "react/jsx-runtime": "next/dist/compiled/react/jsx-runtime",
31
+ "react/jsx-dev-runtime": "next/dist/compiled/react/jsx-dev-runtime",
32
+ "react-dom": "next/dist/compiled/react-dom/server-rendering-stub",
33
+ "react-dom/package.json": "next/dist/compiled/react-dom/package.json",
34
+ "react-dom/client": "next/dist/compiled/react-dom/client",
35
+ "react-dom/server": "next/dist/compiled/react-dom/server",
36
+ "react-dom/server.browser": "next/dist/compiled/react-dom/server.browser",
37
+ "react-dom/server.edge": "next/dist/compiled/react-dom/server.edge",
38
+ "react-server-dom-webpack/client": "next/dist/compiled/react-server-dom-webpack/client",
39
+ "react-server-dom-webpack/client.edge": "next/dist/compiled/react-server-dom-webpack/client.edge",
40
+ "react-server-dom-webpack/server.edge": "next/dist/compiled/react-server-dom-webpack/server.edge",
41
+ "react-server-dom-webpack/server.node": "next/dist/compiled/react-server-dom-webpack/server.node",
42
+ };
43
+ const experimentalOverrides = {
44
+ react: "next/dist/compiled/react-experimental",
45
+ "react/jsx-runtime": "next/dist/compiled/react-experimental/jsx-runtime",
46
+ "react/jsx-dev-runtime": "next/dist/compiled/react-experimental/jsx-dev-runtime",
47
+ "react-dom": "next/dist/compiled/react-dom-experimental/server-rendering-stub",
48
+ "react/package.json": "next/dist/compiled/react-experimental/package.json",
49
+ "react-dom/package.json": "next/dist/compiled/react-dom-experimental/package.json",
50
+ "react-dom/client": "next/dist/compiled/react-dom-experimental/client",
51
+ "react-dom/server": "next/dist/compiled/react-dom-experimental/server",
52
+ "react-dom/server.browser": "next/dist/compiled/react-dom-experimental/server.browser",
53
+ "react-dom/server.edge": "next/dist/compiled/react-dom-experimental/server.edge",
54
+ "react-server-dom-webpack/client": "next/dist/compiled/react-server-dom-webpack-experimental/client",
55
+ "react-server-dom-webpack/client.edge": "next/dist/compiled/react-server-dom-webpack-experimental/client.edge",
56
+ "react-server-dom-webpack/server.edge": "next/dist/compiled/react-server-dom-webpack-experimental/server.edge",
57
+ "react-server-dom-webpack/server.node": "next/dist/compiled/react-server-dom-webpack-experimental/server.node",
58
+ };
59
+ // Add default aliases
60
+ function overrideDefault() {
61
+ addHookAliases([
62
+ // Use `require.resolve` explicitly to make them statically analyzable
63
+ // styled-jsx needs to be resolved as the external dependency.
64
+ ["styled-jsx", require.resolve("styled-jsx")],
65
+ ["styled-jsx/style", require.resolve("styled-jsx/style")],
66
+ ], "app");
67
+ }
68
+ const toResolveMap = (map) => Object.entries(map).map(([key, value]) => [key, require.resolve(value)]);
69
+ // Override built-in React packages if necessary
70
+ function overrideReact(config) {
71
+ addHookAliases([["react", require.resolve(`react`)]], "page");
72
+ // ignore: react/jsx-dev-runtime is not available on older version of Next.js ie. v13.1.6
73
+ // react/jsx-runtime is not available on newer version of Next.js ie. v13.4.10-canary.3
74
+ try {
75
+ addHookAliases([["react/jsx-runtime", require.resolve(`react/jsx-runtime`)]], "page");
76
+ addHookAliases([["react/jsx-dev-runtime", require.resolve(`react/jsx-dev-runtime`)]], "page");
77
+ }
78
+ catch (e) { }
79
+ if (config.experimental.appDir) {
80
+ if (config.experimental.serverActions) {
81
+ addHookAliases(toResolveMap(experimentalOverrides), "app");
82
+ }
83
+ else {
84
+ addHookAliases(toResolveMap(baseOverrides), "app");
85
+ }
86
+ }
87
+ }
88
+ function isApp() {
89
+ return (process.env.__NEXT_PRIVATE_PREBUNDLED_REACT === "next" ||
90
+ process.env.__NEXT_PRIVATE_PREBUNDLED_REACT === "experimental");
91
+ }
92
+ export function applyOverride() {
93
+ mod._resolveFilename = function (originalResolveFilename, requestMapApp, requestMapPage, request, parent, isMain, options) {
94
+ const hookResolved = isApp()
95
+ ? requestMapApp.get(request)
96
+ : requestMapPage.get(request);
97
+ if (hookResolved)
98
+ request = hookResolved;
99
+ return originalResolveFilename.call(mod, request, parent, isMain, options);
100
+ // We use `bind` here to avoid referencing outside variables to create potential memory leaks.
101
+ }.bind(null, resolveFilename, hookPropertyMapApp, hookPropertyMapPage);
102
+ }
@@ -0,0 +1,31 @@
1
+ import { BaseEventOrResult, Converter, DefaultOverrideOptions, ImageLoader, InternalEvent, InternalResult, LazyLoadedOverride, OverrideOptions, Wrapper } from "../types/open-next.js";
2
+ import { TagCache } from "../cache/tag/types.js";
3
+ export declare function resolveConverter<E extends BaseEventOrResult = InternalEvent, R extends BaseEventOrResult = InternalResult>(converter: DefaultOverrideOptions<E, R>["converter"]): Promise<Converter<E, R>>;
4
+ export declare function resolveWrapper<E extends BaseEventOrResult = InternalEvent, R extends BaseEventOrResult = InternalResult>(wrapper: DefaultOverrideOptions<E, R>["wrapper"]): Promise<Wrapper<E, R>>;
5
+ /**
6
+ *
7
+ * @param tagCache
8
+ * @returns
9
+ * @__PURE__
10
+ */
11
+ export declare function resolveTagCache(tagCache: OverrideOptions["tagCache"]): Promise<TagCache>;
12
+ /**
13
+ *
14
+ * @param queue
15
+ * @returns
16
+ * @__PURE__
17
+ */
18
+ export declare function resolveQueue(queue: OverrideOptions["queue"]): Promise<import("../queue/types.js").Queue>;
19
+ /**
20
+ *
21
+ * @param incrementalCache
22
+ * @returns
23
+ * @__PURE__
24
+ */
25
+ export declare function resolveIncrementalCache(incrementalCache: OverrideOptions["incrementalCache"]): Promise<import("../cache/incremental/types.js").IncrementalCache>;
26
+ /**
27
+ * @param imageLoader
28
+ * @returns
29
+ * @__PURE__
30
+ */
31
+ export declare function resolveImageLoader(imageLoader: LazyLoadedOverride<ImageLoader> | string): Promise<ImageLoader>;
@@ -0,0 +1,81 @@
1
+ export async function resolveConverter(converter) {
2
+ if (typeof converter === "function") {
3
+ return converter();
4
+ }
5
+ else {
6
+ const m_1 = await import(`../converters/aws-apigw-v2.js`);
7
+ // @ts-expect-error
8
+ return m_1.default;
9
+ }
10
+ }
11
+ export async function resolveWrapper(wrapper) {
12
+ if (typeof wrapper === "function") {
13
+ return wrapper();
14
+ }
15
+ else {
16
+ // This will be replaced by the bundler
17
+ const m_1 = await import("../wrappers/aws-lambda.js");
18
+ // @ts-expect-error
19
+ return m_1.default;
20
+ }
21
+ }
22
+ /**
23
+ *
24
+ * @param tagCache
25
+ * @returns
26
+ * @__PURE__
27
+ */
28
+ export async function resolveTagCache(tagCache) {
29
+ if (typeof tagCache === "function") {
30
+ return tagCache();
31
+ }
32
+ else {
33
+ // This will be replaced by the bundler
34
+ const m_1 = await import("../cache/tag/dynamodb.js");
35
+ return m_1.default;
36
+ }
37
+ }
38
+ /**
39
+ *
40
+ * @param queue
41
+ * @returns
42
+ * @__PURE__
43
+ */
44
+ export async function resolveQueue(queue) {
45
+ if (typeof queue === "function") {
46
+ return queue();
47
+ }
48
+ else {
49
+ const m_1 = await import("../queue/sqs.js");
50
+ return m_1.default;
51
+ }
52
+ }
53
+ /**
54
+ *
55
+ * @param incrementalCache
56
+ * @returns
57
+ * @__PURE__
58
+ */
59
+ export async function resolveIncrementalCache(incrementalCache) {
60
+ if (typeof incrementalCache === "function") {
61
+ return incrementalCache();
62
+ }
63
+ else {
64
+ const m_1 = await import("../cache/incremental/s3.js");
65
+ return m_1.default;
66
+ }
67
+ }
68
+ /**
69
+ * @param imageLoader
70
+ * @returns
71
+ * @__PURE__
72
+ */
73
+ export async function resolveImageLoader(imageLoader) {
74
+ if (typeof imageLoader === "function") {
75
+ return imageLoader();
76
+ }
77
+ else {
78
+ const m_1 = await import("../overrides/imageLoader/s3.js");
79
+ return m_1.default;
80
+ }
81
+ }
@@ -0,0 +1,2 @@
1
+ import { InternalEvent, InternalResult } from "../../types/open-next";
2
+ export declare function cacheInterceptor(event: InternalEvent): Promise<InternalEvent | InternalResult>;
@@ -0,0 +1,162 @@
1
+ import { createHash } from "node:crypto";
2
+ import { NextConfig, PrerenderManifest } from "../../adapters/config/index";
3
+ import { emptyReadableStream, toReadableStream } from "../../utils/stream";
4
+ import { debug } from "../../adapters/logger";
5
+ import { localizePath } from "./i18n";
6
+ import { generateMessageGroupId } from "./util";
7
+ const CACHE_ONE_YEAR = 60 * 60 * 24 * 365;
8
+ const CACHE_ONE_MONTH = 60 * 60 * 24 * 30;
9
+ async function computeCacheControl(path, body, host, revalidate, lastModified) {
10
+ let finalRevalidate = CACHE_ONE_YEAR;
11
+ const existingRoute = Object.entries(PrerenderManifest.routes).find((p) => p[0] === path)?.[1];
12
+ if (revalidate === undefined && existingRoute) {
13
+ finalRevalidate =
14
+ existingRoute.initialRevalidateSeconds === false
15
+ ? CACHE_ONE_YEAR
16
+ : existingRoute.initialRevalidateSeconds;
17
+ // eslint-disable-next-line sonarjs/elseif-without-else
18
+ }
19
+ else if (revalidate !== undefined) {
20
+ finalRevalidate = revalidate === false ? CACHE_ONE_YEAR : revalidate;
21
+ }
22
+ // calculate age
23
+ const age = Math.round((Date.now() - (lastModified ?? 0)) / 1000);
24
+ const hash = (str) => createHash("md5").update(str).digest("hex");
25
+ const etag = hash(body);
26
+ if (revalidate === 0) {
27
+ // This one should never happen
28
+ return {
29
+ "cache-control": "private, no-cache, no-store, max-age=0, must-revalidate",
30
+ "x-opennext-cache": "ERROR",
31
+ etag,
32
+ };
33
+ }
34
+ else if (finalRevalidate !== CACHE_ONE_YEAR) {
35
+ const sMaxAge = Math.max(finalRevalidate - age, 1);
36
+ debug("sMaxAge", {
37
+ finalRevalidate,
38
+ age,
39
+ lastModified,
40
+ revalidate,
41
+ });
42
+ const isStale = sMaxAge === 1;
43
+ if (isStale) {
44
+ let url = NextConfig.trailingSlash ? `${path}/` : path;
45
+ if (NextConfig.basePath) {
46
+ // We need to add the basePath to the url
47
+ url = `${NextConfig.basePath}${url}`;
48
+ }
49
+ await globalThis.queue.send({
50
+ MessageBody: { host, url },
51
+ MessageDeduplicationId: hash(`${path}-${lastModified}-${etag}`),
52
+ MessageGroupId: generateMessageGroupId(path),
53
+ });
54
+ }
55
+ return {
56
+ "cache-control": `s-maxage=${sMaxAge}, stale-while-revalidate=${CACHE_ONE_MONTH}`,
57
+ "x-opennext-cache": isStale ? "STALE" : "HIT",
58
+ etag,
59
+ };
60
+ }
61
+ else {
62
+ return {
63
+ "cache-control": `s-maxage=${CACHE_ONE_YEAR}, stale-while-revalidate=${CACHE_ONE_MONTH}`,
64
+ "x-opennext-cache": "HIT",
65
+ etag,
66
+ };
67
+ }
68
+ }
69
+ async function generateResult(event, localizedPath, cachedValue, lastModified) {
70
+ debug("Returning result from experimental cache");
71
+ let body = "";
72
+ let type = "application/octet-stream";
73
+ let isDataRequest = false;
74
+ switch (cachedValue.type) {
75
+ case "app":
76
+ isDataRequest = Boolean(event.headers["rsc"]);
77
+ body = isDataRequest ? cachedValue.rsc : cachedValue.html;
78
+ type = isDataRequest ? "text/x-component" : "text/html; charset=utf-8";
79
+ break;
80
+ case "page":
81
+ isDataRequest = Boolean(event.query["__nextDataReq"]);
82
+ body = isDataRequest
83
+ ? JSON.stringify(cachedValue.json)
84
+ : cachedValue.html;
85
+ type = isDataRequest ? "application/json" : "text/html; charset=utf-8";
86
+ break;
87
+ }
88
+ const cacheControl = await computeCacheControl(localizedPath, body, event.headers["host"], cachedValue.revalidate, lastModified);
89
+ return {
90
+ type: "core",
91
+ statusCode: 200,
92
+ body: toReadableStream(body, false),
93
+ isBase64Encoded: false,
94
+ headers: {
95
+ ...cacheControl,
96
+ "content-type": type,
97
+ ...cachedValue.meta?.headers,
98
+ },
99
+ };
100
+ }
101
+ export async function cacheInterceptor(event) {
102
+ if (Boolean(event.headers["next-action"]) ||
103
+ Boolean(event.headers["x-prerender-revalidate"]))
104
+ return event;
105
+ // We localize the path in case i18n is enabled
106
+ let localizedPath = localizePath(event);
107
+ // If using basePath we need to remove it from the path
108
+ if (NextConfig.basePath) {
109
+ localizedPath = localizedPath.replace(NextConfig.basePath, "");
110
+ }
111
+ // We also need to remove trailing slash
112
+ localizedPath = localizedPath.replace(/\/$/, "");
113
+ // If empty path, it means we want index
114
+ if (localizedPath === "") {
115
+ localizedPath = "index";
116
+ }
117
+ debug("Checking cache for", localizedPath, PrerenderManifest);
118
+ const isISR = Object.keys(PrerenderManifest.routes).includes(localizedPath) ||
119
+ Object.values(PrerenderManifest.dynamicRoutes).some((dr) => new RegExp(dr.routeRegex).test(localizedPath));
120
+ debug("isISR", isISR);
121
+ if (isISR) {
122
+ try {
123
+ const cachedData = await globalThis.incrementalCache.get(localizedPath);
124
+ debug("cached data in interceptor", cachedData);
125
+ if (cachedData.value?.type === "app") {
126
+ // We need to check the tag cache now
127
+ const _lastModified = await globalThis.tagCache.getLastModified(localizedPath, cachedData.lastModified);
128
+ if (_lastModified === -1) {
129
+ // If some tags are stale we need to force revalidation
130
+ return event;
131
+ }
132
+ }
133
+ const host = event.headers["host"];
134
+ switch (cachedData.value?.type) {
135
+ case "app":
136
+ case "page":
137
+ return generateResult(event, localizedPath, cachedData.value, cachedData.lastModified);
138
+ case "redirect":
139
+ const cacheControl = await computeCacheControl(localizedPath, "", host, cachedData.value.revalidate, cachedData.lastModified);
140
+ return {
141
+ type: "core",
142
+ statusCode: cachedData.value.meta?.status ?? 307,
143
+ body: emptyReadableStream(),
144
+ headers: {
145
+ ...(cachedData.value.meta?.headers ??
146
+ {}),
147
+ ...cacheControl,
148
+ },
149
+ isBase64Encoded: false,
150
+ };
151
+ default:
152
+ return event;
153
+ }
154
+ }
155
+ catch (e) {
156
+ debug("Error while fetching cache", e);
157
+ // In case of error we fallback to the server
158
+ return event;
159
+ }
160
+ }
161
+ return event;
162
+ }
@@ -0,0 +1 @@
1
+ export declare function acceptLanguage(header?: string, preferences?: string[]): string | undefined;
@@ -0,0 +1,101 @@
1
+ // Copied from Next.js source code
2
+ // https://github.com/vercel/next.js/blob/canary/packages/next/src/server/accept-header.ts
3
+ function parse(raw, preferences, options) {
4
+ const lowers = new Map();
5
+ const header = raw.replace(/[ \t]/g, "");
6
+ if (preferences) {
7
+ let pos = 0;
8
+ for (const preference of preferences) {
9
+ const lower = preference.toLowerCase();
10
+ lowers.set(lower, { orig: preference, pos: pos++ });
11
+ if (options.prefixMatch) {
12
+ const parts = lower.split("-");
13
+ while ((parts.pop(), parts.length > 0)) {
14
+ const joined = parts.join("-");
15
+ if (!lowers.has(joined)) {
16
+ lowers.set(joined, { orig: preference, pos: pos++ });
17
+ }
18
+ }
19
+ }
20
+ }
21
+ }
22
+ const parts = header.split(",");
23
+ const selections = [];
24
+ const map = new Set();
25
+ for (let i = 0; i < parts.length; ++i) {
26
+ const part = parts[i];
27
+ if (!part) {
28
+ continue;
29
+ }
30
+ const params = part.split(";");
31
+ if (params.length > 2) {
32
+ throw new Error(`Invalid ${options.type} header`);
33
+ }
34
+ let token = params[0].toLowerCase();
35
+ if (!token) {
36
+ throw new Error(`Invalid ${options.type} header`);
37
+ }
38
+ const selection = { token, pos: i, q: 1 };
39
+ if (preferences && lowers.has(token)) {
40
+ selection.pref = lowers.get(token).pos;
41
+ }
42
+ map.add(selection.token);
43
+ if (params.length === 2) {
44
+ const q = params[1];
45
+ const [key, value] = q.split("=");
46
+ if (!value || (key !== "q" && key !== "Q")) {
47
+ throw new Error(`Invalid ${options.type} header`);
48
+ }
49
+ const score = parseFloat(value);
50
+ if (score === 0) {
51
+ continue;
52
+ }
53
+ if (Number.isFinite(score) && score <= 1 && score >= 0.001) {
54
+ selection.q = score;
55
+ }
56
+ }
57
+ selections.push(selection);
58
+ }
59
+ selections.sort((a, b) => {
60
+ if (b.q !== a.q) {
61
+ return b.q - a.q;
62
+ }
63
+ if (b.pref !== a.pref) {
64
+ if (a.pref === undefined) {
65
+ return 1;
66
+ }
67
+ if (b.pref === undefined) {
68
+ return -1;
69
+ }
70
+ return a.pref - b.pref;
71
+ }
72
+ return a.pos - b.pos;
73
+ });
74
+ const values = selections.map((selection) => selection.token);
75
+ if (!preferences || !preferences.length) {
76
+ return values;
77
+ }
78
+ const preferred = [];
79
+ for (const selection of values) {
80
+ if (selection === "*") {
81
+ for (const [preference, value] of lowers) {
82
+ if (!map.has(preference)) {
83
+ preferred.push(value.orig);
84
+ }
85
+ }
86
+ }
87
+ else {
88
+ const lower = selection.toLowerCase();
89
+ if (lowers.has(lower)) {
90
+ preferred.push(lowers.get(lower).orig);
91
+ }
92
+ }
93
+ }
94
+ return preferred;
95
+ }
96
+ export function acceptLanguage(header = "", preferences) {
97
+ return (parse(header, preferences, {
98
+ type: "accept-language",
99
+ prefixMatch: true,
100
+ })[0] || undefined);
101
+ }
@@ -0,0 +1,2 @@
1
+ import { InternalEvent } from "../../../types/open-next";
2
+ export declare function localizePath(internalEvent: InternalEvent): string;