@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.
- package/LICENSE +21 -0
- package/README.md +94 -0
- package/dist/adapters/binary.d.ts +1 -0
- package/dist/adapters/binary.js +63 -0
- package/dist/adapters/cache.d.ts +96 -0
- package/dist/adapters/cache.js +278 -0
- package/dist/adapters/config/index.d.ts +27 -0
- package/dist/adapters/config/index.js +21 -0
- package/dist/adapters/config/util.d.ts +28 -0
- package/dist/adapters/config/util.js +84 -0
- package/dist/adapters/dynamo-provider.d.ts +8 -0
- package/dist/adapters/dynamo-provider.js +42 -0
- package/dist/adapters/edge-adapter.d.ts +8 -0
- package/dist/adapters/edge-adapter.js +54 -0
- package/dist/adapters/image-optimization-adapter.d.ts +4 -0
- package/dist/adapters/image-optimization-adapter.js +193 -0
- package/dist/adapters/logger.d.ts +13 -0
- package/dist/adapters/logger.js +51 -0
- package/dist/adapters/middleware.d.ts +5 -0
- package/dist/adapters/middleware.js +84 -0
- package/dist/adapters/plugins/14.1/util.d.ts +1 -0
- package/dist/adapters/plugins/14.1/util.js +29 -0
- package/dist/adapters/plugins/image-optimization/image-optimization.d.ts +11 -0
- package/dist/adapters/plugins/image-optimization/image-optimization.js +14 -0
- package/dist/adapters/plugins/image-optimization/image-optimization.replacement.d.ts +11 -0
- package/dist/adapters/plugins/image-optimization/image-optimization.replacement.js +22 -0
- package/dist/adapters/plugins/without-routing/requestHandler.d.ts +2 -0
- package/dist/adapters/plugins/without-routing/requestHandler.js +10 -0
- package/dist/adapters/revalidate.d.ts +9 -0
- package/dist/adapters/revalidate.js +71 -0
- package/dist/adapters/server-adapter.d.ts +4 -0
- package/dist/adapters/server-adapter.js +27 -0
- package/dist/adapters/util.d.ts +10 -0
- package/dist/adapters/util.js +28 -0
- package/dist/adapters/warmer-function.d.ts +12 -0
- package/dist/adapters/warmer-function.js +80 -0
- package/dist/build/bundleNextServer.d.ts +1 -0
- package/dist/build/bundleNextServer.js +87 -0
- package/dist/build/compileConfig.d.ts +3 -0
- package/dist/build/compileConfig.js +64 -0
- package/dist/build/copyTracedFiles.d.ts +1 -0
- package/dist/build/copyTracedFiles.js +207 -0
- package/dist/build/createServerBundle.d.ts +3 -0
- package/dist/build/createServerBundle.js +228 -0
- package/dist/build/edge/createEdgeBundle.d.ts +20 -0
- package/dist/build/edge/createEdgeBundle.js +149 -0
- package/dist/build/generateOutput.d.ts +2 -0
- package/dist/build/generateOutput.js +239 -0
- package/dist/build/helper.d.ts +33 -0
- package/dist/build/helper.js +193 -0
- package/dist/build/patch/patchedAsyncStorage.d.ts +5 -0
- package/dist/build/patch/patchedAsyncStorage.js +16 -0
- package/dist/build/validateConfig.d.ts +2 -0
- package/dist/build/validateConfig.js +76 -0
- package/dist/build.d.ts +7 -0
- package/dist/build.js +533 -0
- package/dist/cache/incremental/s3-lite.d.ts +3 -0
- package/dist/cache/incremental/s3-lite.js +72 -0
- package/dist/cache/incremental/s3.d.ts +3 -0
- package/dist/cache/incremental/s3.js +44 -0
- package/dist/cache/incremental/types.d.ts +34 -0
- package/dist/cache/incremental/types.js +1 -0
- package/dist/cache/next-types.d.ts +62 -0
- package/dist/cache/next-types.js +1 -0
- package/dist/cache/tag/constants.d.ts +2 -0
- package/dist/cache/tag/constants.js +17 -0
- package/dist/cache/tag/dynamodb-lite.d.ts +3 -0
- package/dist/cache/tag/dynamodb-lite.js +174 -0
- package/dist/cache/tag/dynamodb.d.ts +3 -0
- package/dist/cache/tag/dynamodb.js +129 -0
- package/dist/cache/tag/types.d.ts +11 -0
- package/dist/cache/tag/types.js +1 -0
- package/dist/converters/aws-apigw-v1.d.ts +3 -0
- package/dist/converters/aws-apigw-v1.js +89 -0
- package/dist/converters/aws-apigw-v2.d.ts +3 -0
- package/dist/converters/aws-apigw-v2.js +99 -0
- package/dist/converters/aws-cloudfront.d.ts +3 -0
- package/dist/converters/aws-cloudfront.js +170 -0
- package/dist/converters/dummy.d.ts +7 -0
- package/dist/converters/dummy.js +16 -0
- package/dist/converters/edge.d.ts +6 -0
- package/dist/converters/edge.js +88 -0
- package/dist/converters/node.d.ts +3 -0
- package/dist/converters/node.js +45 -0
- package/dist/converters/sqs-revalidate.d.ts +4 -0
- package/dist/converters/sqs-revalidate.js +22 -0
- package/dist/converters/utils.d.ts +1 -0
- package/dist/converters/utils.js +9 -0
- package/dist/core/createGenericHandler.d.ts +11 -0
- package/dist/core/createGenericHandler.js +16 -0
- package/dist/core/createMainHandler.d.ts +18 -0
- package/dist/core/createMainHandler.js +24 -0
- package/dist/core/edgeFunctionHandler.d.ts +54 -0
- package/dist/core/edgeFunctionHandler.js +21 -0
- package/dist/core/patchAsyncStorage.d.ts +1 -0
- package/dist/core/patchAsyncStorage.js +16 -0
- package/dist/core/requestHandler.d.ts +3 -0
- package/dist/core/requestHandler.js +162 -0
- package/dist/core/require-hooks.d.ts +3 -0
- package/dist/core/require-hooks.js +102 -0
- package/dist/core/resolve.d.ts +31 -0
- package/dist/core/resolve.js +81 -0
- package/dist/core/routing/cacheInterceptor.d.ts +2 -0
- package/dist/core/routing/cacheInterceptor.js +162 -0
- package/dist/core/routing/i18n/accept-header.d.ts +1 -0
- package/dist/core/routing/i18n/accept-header.js +101 -0
- package/dist/core/routing/i18n/index.d.ts +2 -0
- package/dist/core/routing/i18n/index.js +36 -0
- package/dist/core/routing/matcher.d.ts +25 -0
- package/dist/core/routing/matcher.js +294 -0
- package/dist/core/routing/middleware.d.ts +7 -0
- package/dist/core/routing/middleware.js +167 -0
- package/dist/core/routing/util.d.ts +105 -0
- package/dist/core/routing/util.js +415 -0
- package/dist/core/routingHandler.d.ts +8 -0
- package/dist/core/routingHandler.js +127 -0
- package/dist/core/util.d.ts +5 -0
- package/dist/core/util.js +84 -0
- package/dist/helpers/withCloudflare.d.ts +65 -0
- package/dist/helpers/withCloudflare.js +58 -0
- package/dist/helpers/withSST.d.ts +54 -0
- package/dist/helpers/withSST.js +28 -0
- package/dist/http/index.d.ts +2 -0
- package/dist/http/index.js +4 -0
- package/dist/http/openNextResponse.d.ts +78 -0
- package/dist/http/openNextResponse.js +281 -0
- package/dist/http/request.d.ts +12 -0
- package/dist/http/request.js +35 -0
- package/dist/http/util.d.ts +4 -0
- package/dist/http/util.js +34 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +37 -0
- package/dist/logger.d.ts +12 -0
- package/dist/logger.js +13 -0
- package/dist/minimize-js.d.ts +1 -0
- package/dist/minimize-js.js +101 -0
- package/dist/overrides/imageLoader/host.d.ts +3 -0
- package/dist/overrides/imageLoader/host.js +29 -0
- package/dist/overrides/imageLoader/s3.d.ts +3 -0
- package/dist/overrides/imageLoader/s3.js +33 -0
- package/dist/plugins/edge.d.ts +15 -0
- package/dist/plugins/edge.js +157 -0
- package/dist/plugins/replacement.d.ts +42 -0
- package/dist/plugins/replacement.js +74 -0
- package/dist/plugins/resolve.d.ts +18 -0
- package/dist/plugins/resolve.js +45 -0
- package/dist/queue/sqs-lite.d.ts +3 -0
- package/dist/queue/sqs-lite.js +52 -0
- package/dist/queue/sqs.d.ts +3 -0
- package/dist/queue/sqs.js +20 -0
- package/dist/queue/types.d.ts +12 -0
- package/dist/queue/types.js +1 -0
- package/dist/types/aws-lambda.d.ts +22 -0
- package/dist/types/aws-lambda.js +1 -0
- package/dist/types/next-types.d.ts +155 -0
- package/dist/types/next-types.js +2 -0
- package/dist/types/open-next.d.ts +303 -0
- package/dist/types/open-next.js +1 -0
- package/dist/utils/error.d.ts +23 -0
- package/dist/utils/error.js +32 -0
- package/dist/utils/fetch.d.ts +2 -0
- package/dist/utils/fetch.js +23 -0
- package/dist/utils/promise.d.ts +18 -0
- package/dist/utils/promise.js +48 -0
- package/dist/utils/stream.d.ts +5 -0
- package/dist/utils/stream.js +30 -0
- package/dist/wrappers/aws-lambda-streaming.d.ts +7 -0
- package/dist/wrappers/aws-lambda-streaming.js +88 -0
- package/dist/wrappers/aws-lambda.d.ts +7 -0
- package/dist/wrappers/aws-lambda.js +39 -0
- package/dist/wrappers/cloudflare.d.ts +11 -0
- package/dist/wrappers/cloudflare.js +20 -0
- package/dist/wrappers/node.d.ts +7 -0
- package/dist/wrappers/node.js +57 -0
- 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,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,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
|
+
}
|