@opennextjs/aws 3.6.0 → 3.6.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.
- package/dist/build/compileConfig.js +4 -0
- package/dist/build/createMiddleware.js +2 -1
- package/dist/core/requestHandler.js +57 -29
- package/dist/core/routing/cacheInterceptor.js +30 -6
- package/dist/core/routing/matcher.js +38 -5
- package/dist/core/routing/middleware.js +0 -1
- package/dist/core/routing/routeMatcher.d.ts +3 -9
- package/dist/overrides/converters/edge.js +17 -1
- package/dist/overrides/converters/node.js +2 -1
- package/dist/overrides/imageLoader/fs-dev.js +4 -2
- package/dist/overrides/incrementalCache/fs-dev.js +2 -1
- package/dist/overrides/tagCache/fs-dev.js +3 -2
- package/dist/overrides/wrappers/express-dev.js +4 -2
- package/dist/plugins/edge.js +1 -1
- package/dist/types/global.d.ts +5 -0
- package/dist/utils/normalize-path.d.ts +2 -0
- package/dist/utils/normalize-path.js +15 -0
- package/package.json +4 -4
|
@@ -83,5 +83,9 @@ export function compileOpenNextConfigEdge(sourcePath, outputDir, externals) {
|
|
|
83
83
|
conditions: ["worker", "browser"],
|
|
84
84
|
platform: "browser",
|
|
85
85
|
external: externals,
|
|
86
|
+
define: {
|
|
87
|
+
// with the default esbuild config, the NODE_ENV will be set to "development", we don't want that
|
|
88
|
+
"process.env.NODE_ENV": '"production"',
|
|
89
|
+
},
|
|
86
90
|
});
|
|
87
91
|
}
|
|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { loadFunctionsConfigManifest, loadMiddlewareManifest, } from "../adapters/config/util.js";
|
|
4
4
|
import logger from "../logger.js";
|
|
5
|
-
import { buildEdgeBundle } from "./edge/createEdgeBundle.js";
|
|
5
|
+
import { buildEdgeBundle, copyMiddlewareResources, } from "./edge/createEdgeBundle.js";
|
|
6
6
|
import * as buildHelper from "./helper.js";
|
|
7
7
|
import { installDependencies } from "./installDeps.js";
|
|
8
8
|
import { buildBundledNodeMiddleware, buildExternalNodeMiddleware, } from "./middleware/buildNodeMiddleware.js";
|
|
@@ -31,6 +31,7 @@ export async function createMiddleware(options, { forceOnlyBuildOnce = false } =
|
|
|
31
31
|
}
|
|
32
32
|
if (config.middleware?.external) {
|
|
33
33
|
const outputPath = path.join(outputDir, "middleware");
|
|
34
|
+
copyMiddlewareResources(options, edgeMiddlewareInfo, outputPath);
|
|
34
35
|
fs.mkdirSync(outputPath, { recursive: true });
|
|
35
36
|
// Copy open-next.config.mjs
|
|
36
37
|
buildHelper.copyOpenNextConfig(options.buildDir, outputPath, await buildHelper.isEdgeRuntime(config.middleware.override));
|
|
@@ -51,7 +51,11 @@ export async function openNextHandler(internalEvent, options) {
|
|
|
51
51
|
continue;
|
|
52
52
|
}
|
|
53
53
|
const key = rawKey.slice(MIDDLEWARE_HEADER_PREFIX_LEN);
|
|
54
|
-
|
|
54
|
+
// We skip this header here since it is used by Next internally and we don't want it on the response headers.
|
|
55
|
+
// This header needs to be present in the request headers for processRequest, so cookies().get() from Next will work on initial render.
|
|
56
|
+
if (key !== "x-middleware-set-cookie") {
|
|
57
|
+
overwrittenResponseHeaders[key] = value;
|
|
58
|
+
}
|
|
55
59
|
headers[key] = value;
|
|
56
60
|
delete headers[rawKey];
|
|
57
61
|
}
|
|
@@ -151,44 +155,68 @@ async function processRequest(req, res, routingResult) {
|
|
|
151
155
|
// Next.js doesn't parse body if the property exists
|
|
152
156
|
// https://github.com/dougmoscrop/serverless-http/issues/227
|
|
153
157
|
delete req.body;
|
|
158
|
+
// Here we try to apply as much request metadata as possible
|
|
159
|
+
// We apply every metadata from `resolve-routes` https://github.com/vercel/next.js/blob/916f105b97211de50f8580f0b39c9e7c60de4886/packages/next/src/server/lib/router-utils/resolve-routes.ts
|
|
160
|
+
// and `router-server` https://github.com/vercel/next.js/blob/916f105b97211de50f8580f0b39c9e7c60de4886/packages/next/src/server/lib/router-server.ts
|
|
161
|
+
const initialURL = new URL(routingResult.initialURL);
|
|
162
|
+
let invokeStatus;
|
|
163
|
+
if (routingResult.internalEvent.rawPath === "/500") {
|
|
164
|
+
invokeStatus = 500;
|
|
165
|
+
}
|
|
166
|
+
else if (routingResult.internalEvent.rawPath === "/404") {
|
|
167
|
+
invokeStatus = 404;
|
|
168
|
+
}
|
|
169
|
+
const requestMetadata = {
|
|
170
|
+
isNextDataReq: routingResult.internalEvent.query.__nextDataReq === "1",
|
|
171
|
+
initURL: routingResult.initialURL,
|
|
172
|
+
initQuery: convertToQuery(initialURL.search),
|
|
173
|
+
initProtocol: initialURL.protocol,
|
|
174
|
+
defaultLocale: NextConfig.i18n?.defaultLocale,
|
|
175
|
+
locale: routingResult.locale,
|
|
176
|
+
middlewareInvoke: false,
|
|
177
|
+
// By setting invokePath and invokeQuery we can bypass some of the routing logic in Next.js
|
|
178
|
+
invokePath: routingResult.internalEvent.rawPath,
|
|
179
|
+
invokeQuery: routingResult.internalEvent.query,
|
|
180
|
+
// invokeStatus is only used for error pages
|
|
181
|
+
invokeStatus,
|
|
182
|
+
};
|
|
154
183
|
try {
|
|
155
184
|
//#override applyNextjsPrebundledReact
|
|
156
185
|
setNextjsPrebundledReact(routingResult.internalEvent.rawPath);
|
|
157
186
|
//#endOverride
|
|
158
|
-
// Here we try to apply as much request metadata as possible
|
|
159
|
-
// We apply every metadata from `resolve-routes` https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/router-utils/resolve-routes.ts
|
|
160
|
-
// and `router-server` https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/router-server.ts
|
|
161
|
-
const initialURL = new URL(routingResult.initialURL);
|
|
162
|
-
let invokeStatus;
|
|
163
|
-
if (routingResult.internalEvent.rawPath === "/500") {
|
|
164
|
-
invokeStatus = 500;
|
|
165
|
-
}
|
|
166
|
-
else if (routingResult.internalEvent.rawPath === "/404") {
|
|
167
|
-
invokeStatus = 404;
|
|
168
|
-
}
|
|
169
|
-
const requestMetadata = {
|
|
170
|
-
isNextDataReq: routingResult.internalEvent.query.__nextDataReq === "1",
|
|
171
|
-
initURL: routingResult.initialURL,
|
|
172
|
-
initQuery: convertToQuery(initialURL.search),
|
|
173
|
-
initProtocol: initialURL.protocol,
|
|
174
|
-
defaultLocale: NextConfig.i18n?.defaultLocale,
|
|
175
|
-
locale: routingResult.locale,
|
|
176
|
-
middlewareInvoke: false,
|
|
177
|
-
// By setting invokePath and invokeQuery we can bypass some of the routing logic in Next.js
|
|
178
|
-
invokePath: routingResult.internalEvent.rawPath,
|
|
179
|
-
invokeQuery: routingResult.internalEvent.query,
|
|
180
|
-
// invokeStatus is only used for error pages
|
|
181
|
-
invokeStatus,
|
|
182
|
-
};
|
|
183
187
|
// Next Server
|
|
184
188
|
await requestHandler(requestMetadata)(req, res);
|
|
185
189
|
}
|
|
186
190
|
catch (e) {
|
|
187
191
|
// This might fail when using bundled next, importing won't do the trick either
|
|
188
192
|
if (e.constructor.name === "NoFallbackError") {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
193
|
+
await handleNoFallbackError(req, res, routingResult, requestMetadata);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
error("NextJS request failed.", e);
|
|
197
|
+
await tryRenderError("500", res, routingResult.internalEvent);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
async function handleNoFallbackError(req, res, routingResult, metadata, index = 1) {
|
|
202
|
+
if (index >= 5) {
|
|
203
|
+
await tryRenderError("500", res, routingResult.internalEvent);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (index >= routingResult.resolvedRoutes.length) {
|
|
207
|
+
await tryRenderError("404", res, routingResult.internalEvent);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
try {
|
|
211
|
+
await requestHandler({
|
|
212
|
+
...routingResult,
|
|
213
|
+
invokeOutput: routingResult.resolvedRoutes[index].route,
|
|
214
|
+
...metadata,
|
|
215
|
+
})(req, res);
|
|
216
|
+
}
|
|
217
|
+
catch (e) {
|
|
218
|
+
if (e.constructor.name === "NoFallbackError") {
|
|
219
|
+
await handleNoFallbackError(req, res, routingResult, metadata, index + 1);
|
|
192
220
|
}
|
|
193
221
|
else {
|
|
194
222
|
error("NextJS request failed.", e);
|
|
@@ -102,6 +102,32 @@ async function generateResult(event, localizedPath, cachedValue, lastModified) {
|
|
|
102
102
|
},
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
*
|
|
107
|
+
* https://github.com/vercel/next.js/blob/34039551d2e5f611c0abde31a197d9985918adaf/packages/next/src/shared/lib/router/utils/escape-path-delimiters.ts#L2-L10
|
|
108
|
+
*/
|
|
109
|
+
function escapePathDelimiters(segment, escapeEncoded) {
|
|
110
|
+
return segment.replace(new RegExp(`([/#?]${escapeEncoded ? "|%(2f|23|3f|5c)" : ""})`, "gi"), (char) => encodeURIComponent(char));
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
*
|
|
114
|
+
* SSG cache key needs to be decoded, but some characters needs to be properly escaped
|
|
115
|
+
* https://github.com/vercel/next.js/blob/34039551d2e5f611c0abde31a197d9985918adaf/packages/next/src/server/lib/router-utils/decode-path-params.ts#L11-L26
|
|
116
|
+
*/
|
|
117
|
+
function decodePathParams(pathname) {
|
|
118
|
+
return pathname
|
|
119
|
+
.split("/")
|
|
120
|
+
.map((segment) => {
|
|
121
|
+
try {
|
|
122
|
+
return escapePathDelimiters(decodeURIComponent(segment), true);
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
// If decodeURIComponent fails, we return the original segment
|
|
126
|
+
return segment;
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
.join("/");
|
|
130
|
+
}
|
|
105
131
|
export async function cacheInterceptor(event) {
|
|
106
132
|
if (Boolean(event.headers["next-action"]) ||
|
|
107
133
|
Boolean(event.headers["x-prerender-revalidate"]))
|
|
@@ -114,17 +140,15 @@ export async function cacheInterceptor(event) {
|
|
|
114
140
|
}
|
|
115
141
|
// We also need to remove trailing slash
|
|
116
142
|
localizedPath = localizedPath.replace(/\/$/, "");
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
localizedPath = "index";
|
|
120
|
-
}
|
|
143
|
+
// Then we decode the path params
|
|
144
|
+
localizedPath = decodePathParams(localizedPath);
|
|
121
145
|
debug("Checking cache for", localizedPath, PrerenderManifest);
|
|
122
|
-
const isISR = Object.keys(PrerenderManifest.routes).includes(localizedPath) ||
|
|
146
|
+
const isISR = Object.keys(PrerenderManifest.routes).includes(localizedPath ?? "/") ||
|
|
123
147
|
Object.values(PrerenderManifest.dynamicRoutes).some((dr) => new RegExp(dr.routeRegex).test(localizedPath));
|
|
124
148
|
debug("isISR", isISR);
|
|
125
149
|
if (isISR) {
|
|
126
150
|
try {
|
|
127
|
-
const cachedData = await globalThis.incrementalCache.get(localizedPath);
|
|
151
|
+
const cachedData = await globalThis.incrementalCache.get(localizedPath ?? "/index");
|
|
128
152
|
debug("cached data in interceptor", cachedData);
|
|
129
153
|
if (!cachedData?.value) {
|
|
130
154
|
return event;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { NextConfig } from "../../adapters/config/index";
|
|
2
2
|
import { compile, match } from "path-to-regexp";
|
|
3
|
+
import { normalizeRepeatedSlashes } from "../../utils/normalize-path";
|
|
3
4
|
import { emptyReadableStream, toReadableStream } from "../../utils/stream";
|
|
4
5
|
import { debug } from "../../adapters/logger";
|
|
5
6
|
import { handleLocaleRedirect, localizePath } from "./i18n";
|
|
7
|
+
import { dynamicRouteMatcher, staticRouteMatcher } from "./routeMatcher";
|
|
6
8
|
import { constructNextUrl, convertFromQueryString, convertToQueryString, escapeRegex, getUrlParts, isExternal, unescapeRegex, } from "./util";
|
|
7
9
|
const routeHasMatcher = (headers, cookies, query) => (redirect) => {
|
|
8
10
|
switch (redirect.type) {
|
|
@@ -168,6 +170,25 @@ export function handleRewrites(event, rewrites) {
|
|
|
168
170
|
isExternalRewrite,
|
|
169
171
|
};
|
|
170
172
|
}
|
|
173
|
+
// Normalizes repeated slashes in the path e.g. hello//world -> hello/world
|
|
174
|
+
// or backslashes to forward slashes. This prevents requests such as //domain
|
|
175
|
+
// from invoking the middleware with `request.url === "domain"`.
|
|
176
|
+
// See: https://github.com/vercel/next.js/blob/3ecf087f10fdfba4426daa02b459387bc9c3c54f/packages/next/src/server/base-server.ts#L1016-L1020
|
|
177
|
+
function handleRepeatedSlashRedirect(event) {
|
|
178
|
+
// Redirect `https://example.com//foo` to `https://example.com/foo`.
|
|
179
|
+
if (event.rawPath.match(/(\\|\/\/)/)) {
|
|
180
|
+
return {
|
|
181
|
+
type: event.type,
|
|
182
|
+
statusCode: 308,
|
|
183
|
+
headers: {
|
|
184
|
+
Location: normalizeRepeatedSlashes(new URL(event.url)),
|
|
185
|
+
},
|
|
186
|
+
body: emptyReadableStream(),
|
|
187
|
+
isBase64Encoded: false,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
171
192
|
function handleTrailingSlashRedirect(event) {
|
|
172
193
|
// When rawPath is `//domain`, `url.host` would be `domain`.
|
|
173
194
|
// https://github.com/opennextjs/opennextjs-aws/issues/355
|
|
@@ -214,6 +235,9 @@ function handleTrailingSlashRedirect(event) {
|
|
|
214
235
|
return false;
|
|
215
236
|
}
|
|
216
237
|
export function handleRedirects(event, redirects) {
|
|
238
|
+
const repeatedSlashRedirect = handleRepeatedSlashRedirect(event);
|
|
239
|
+
if (repeatedSlashRedirect)
|
|
240
|
+
return repeatedSlashRedirect;
|
|
217
241
|
const trailingSlashRedirect = handleTrailingSlashRedirect(event);
|
|
218
242
|
if (trailingSlashRedirect)
|
|
219
243
|
return trailingSlashRedirect;
|
|
@@ -265,9 +289,8 @@ export function fixDataPage(internalEvent, buildId) {
|
|
|
265
289
|
export function handleFallbackFalse(internalEvent, prerenderManifest) {
|
|
266
290
|
const { rawPath } = internalEvent;
|
|
267
291
|
const { dynamicRoutes, routes } = prerenderManifest;
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
.some(([, { routeRegex }]) => {
|
|
292
|
+
const prerenderedFallbackRoutes = Object.entries(dynamicRoutes).filter(([, { fallback }]) => fallback === false);
|
|
293
|
+
const routeFallback = prerenderedFallbackRoutes.some(([, { routeRegex }]) => {
|
|
271
294
|
const routeRegexExp = new RegExp(routeRegex);
|
|
272
295
|
return routeRegexExp.test(rawPath);
|
|
273
296
|
});
|
|
@@ -275,11 +298,21 @@ export function handleFallbackFalse(internalEvent, prerenderManifest) {
|
|
|
275
298
|
const routesAlreadyHaveLocale = locales?.includes(rawPath.split("/")[1]) ||
|
|
276
299
|
// If we don't use locales, we don't need to add the default locale
|
|
277
300
|
locales === undefined;
|
|
278
|
-
|
|
301
|
+
let localizedPath = routesAlreadyHaveLocale
|
|
279
302
|
? rawPath
|
|
280
303
|
: `/${NextConfig.i18n?.defaultLocale}${rawPath}`;
|
|
304
|
+
// We need to remove the trailing slash if it exists
|
|
305
|
+
if (NextConfig.trailingSlash && localizedPath.endsWith("/")) {
|
|
306
|
+
localizedPath = localizedPath.slice(0, -1);
|
|
307
|
+
}
|
|
308
|
+
const matchedStaticRoute = staticRouteMatcher(localizedPath);
|
|
309
|
+
const prerenderedFallbackRoutesName = prerenderedFallbackRoutes.map(([name]) => name);
|
|
310
|
+
const matchedDynamicRoute = dynamicRouteMatcher(localizedPath).filter(({ route }) => !prerenderedFallbackRoutesName.includes(route));
|
|
281
311
|
const isPregenerated = Object.keys(routes).includes(localizedPath);
|
|
282
|
-
if (routeFallback &&
|
|
312
|
+
if (routeFallback &&
|
|
313
|
+
!isPregenerated &&
|
|
314
|
+
matchedStaticRoute.length === 0 &&
|
|
315
|
+
matchedDynamicRoute.length === 0) {
|
|
283
316
|
return {
|
|
284
317
|
event: {
|
|
285
318
|
...internalEvent,
|
|
@@ -75,7 +75,6 @@ export async function handleMiddleware(internalEvent, initialSearch, middlewareL
|
|
|
75
75
|
// These are internal headers used by Next.js, we don't want to expose them to the client
|
|
76
76
|
const filteredHeaders = [
|
|
77
77
|
"x-middleware-override-headers",
|
|
78
|
-
"x-middleware-set-cookie",
|
|
79
78
|
"x-middleware-next",
|
|
80
79
|
"x-middleware-rewrite",
|
|
81
80
|
// We need to drop `content-encoding` because it will be decoded
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ResolvedRoute } from "../../types/open-next";
|
|
2
2
|
export declare const apiPrefix: string;
|
|
3
|
-
export declare const staticRouteMatcher: (path: string) =>
|
|
4
|
-
|
|
5
|
-
type: RouteType;
|
|
6
|
-
}[];
|
|
7
|
-
export declare const dynamicRouteMatcher: (path: string) => {
|
|
8
|
-
route: string;
|
|
9
|
-
type: RouteType;
|
|
10
|
-
}[];
|
|
3
|
+
export declare const staticRouteMatcher: (path: string) => ResolvedRoute[];
|
|
4
|
+
export declare const dynamicRouteMatcher: (path: string) => ResolvedRoute[];
|
|
@@ -55,7 +55,23 @@ const converter = {
|
|
|
55
55
|
}
|
|
56
56
|
const headers = new Headers();
|
|
57
57
|
for (const [key, value] of Object.entries(result.headers)) {
|
|
58
|
-
|
|
58
|
+
if (key === "set-cookie" && typeof value === "string") {
|
|
59
|
+
// If the value is a string, we need to parse it into an array
|
|
60
|
+
// This is the case for middleware direct result
|
|
61
|
+
const cookies = parseCookies(value);
|
|
62
|
+
for (const cookie of cookies) {
|
|
63
|
+
headers.append(key, cookie);
|
|
64
|
+
}
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (Array.isArray(value)) {
|
|
68
|
+
for (const v of value) {
|
|
69
|
+
headers.append(key, v);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
headers.set(key, value);
|
|
74
|
+
}
|
|
59
75
|
}
|
|
60
76
|
return new Response(result.body, {
|
|
61
77
|
status: result.statusCode,
|
|
@@ -17,7 +17,8 @@ const converter = {
|
|
|
17
17
|
Array.isArray(value) ? value.join(",") : value,
|
|
18
18
|
])
|
|
19
19
|
.filter(([key]) => key));
|
|
20
|
-
|
|
20
|
+
// https://nodejs.org/api/http.html#messageurl
|
|
21
|
+
const url = new URL(`${req.protocol ? req.protocol : "http"}://${extractHostFromHeaders(headers)}${req.url}`);
|
|
21
22
|
const query = getQueryFromSearchParams(url.searchParams);
|
|
22
23
|
return {
|
|
23
24
|
type: "core",
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { getMonorepoRelativePath } from "../../utils/normalize-path";
|
|
2
4
|
export default {
|
|
3
5
|
name: "fs-dev",
|
|
4
6
|
load: async (url) => {
|
|
5
|
-
const
|
|
6
|
-
const body = fs.createReadStream(
|
|
7
|
+
const imagePath = path.join(getMonorepoRelativePath(), "assets", url);
|
|
8
|
+
const body = fs.createReadStream(imagePath);
|
|
7
9
|
const contentType = url.endsWith(".png") ? "image/png" : "image/jpeg";
|
|
8
10
|
return {
|
|
9
11
|
body,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { getMonorepoRelativePath } from "../../utils/normalize-path";
|
|
3
4
|
const buildId = process.env.NEXT_BUILD_ID;
|
|
4
|
-
const basePath = path.
|
|
5
|
+
const basePath = path.join(getMonorepoRelativePath(), `cache/${buildId}`);
|
|
5
6
|
const getCacheKey = (key) => {
|
|
6
7
|
return path.join(basePath, `${key}.cache`);
|
|
7
8
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { getMonorepoRelativePath } from "../../utils/normalize-path";
|
|
4
|
+
const tagFile = path.join(getMonorepoRelativePath(), "dynamodb-provider/dynamodb-cache.json");
|
|
4
5
|
const tagContent = fs.readFileSync(tagFile, "utf-8");
|
|
5
6
|
let tags = JSON.parse(tagContent);
|
|
6
7
|
const tagCache = {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import path from "node:path";
|
|
1
2
|
import express from "express";
|
|
3
|
+
import { getMonorepoRelativePath } from "../../utils/normalize-path";
|
|
2
4
|
const wrapper = async (handler, converter) => {
|
|
3
5
|
const app = express();
|
|
4
6
|
// To serve static assets
|
|
5
|
-
app.use(express.static("
|
|
6
|
-
const imageHandlerPath = "
|
|
7
|
+
app.use(express.static(path.join(getMonorepoRelativePath(), "assets")));
|
|
8
|
+
const imageHandlerPath = path.join(getMonorepoRelativePath(), "image-optimization-function/index.mjs");
|
|
7
9
|
const imageHandler = await import(imageHandlerPath).then((m) => m.handler);
|
|
8
10
|
app.all("/_next/image", async (req, res) => {
|
|
9
11
|
const internalEvent = await converter.convertFrom(req);
|
package/dist/plugins/edge.js
CHANGED
|
@@ -27,7 +27,7 @@ export function openNextEdgePlugins({ nextDir, middlewareInfo, isInCloudflare, }
|
|
|
27
27
|
name: "opennext-edge",
|
|
28
28
|
setup(build) {
|
|
29
29
|
logger.debug(chalk.blue("OpenNext Edge plugin"));
|
|
30
|
-
build.onResolve({ filter: /\.(mjs|wasm)$/
|
|
30
|
+
build.onResolve({ filter: /\.(mjs|wasm)$/ }, () => {
|
|
31
31
|
return {
|
|
32
32
|
external: true,
|
|
33
33
|
};
|
package/dist/types/global.d.ts
CHANGED
|
@@ -185,5 +185,10 @@ declare global {
|
|
|
185
185
|
* Only available in main functions.
|
|
186
186
|
*/
|
|
187
187
|
var __next_route_preloader: (stage: "waitUntil" | "start" | "warmerEvent" | "onDemand") => Promise<void>;
|
|
188
|
+
/**
|
|
189
|
+
* This is the relative package path of the monorepo. It will be an empty string "" in normal repos.
|
|
190
|
+
* ex. `packages/web`
|
|
191
|
+
*/
|
|
192
|
+
var monorepoPackagePath: string;
|
|
188
193
|
}
|
|
189
194
|
export {};
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
import path from "node:path";
|
|
1
2
|
export function normalizePath(path) {
|
|
2
3
|
return path.replace(/\\/g, "/");
|
|
3
4
|
}
|
|
5
|
+
// See: https://github.com/vercel/next.js/blob/3ecf087f10fdfba4426daa02b459387bc9c3c54f/packages/next/src/shared/lib/utils.ts#L348
|
|
6
|
+
export function normalizeRepeatedSlashes(url) {
|
|
7
|
+
const urlNoQuery = url.host + url.pathname;
|
|
8
|
+
return `${url.protocol}//${urlNoQuery
|
|
9
|
+
.replace(/\\/g, "/")
|
|
10
|
+
.replace(/\/\/+/g, "/")}${url.search}`;
|
|
11
|
+
}
|
|
12
|
+
export function getMonorepoRelativePath(relativePath = "../..") {
|
|
13
|
+
return path.join(globalThis.monorepoPackagePath
|
|
14
|
+
.split("/")
|
|
15
|
+
.filter(Boolean)
|
|
16
|
+
.map(() => "..")
|
|
17
|
+
.join("/"), relativePath);
|
|
18
|
+
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"access": "public"
|
|
4
4
|
},
|
|
5
5
|
"name": "@opennextjs/aws",
|
|
6
|
-
"version": "3.6.
|
|
6
|
+
"version": "3.6.2",
|
|
7
7
|
"bin": {
|
|
8
8
|
"open-next": "./dist/index.js"
|
|
9
9
|
},
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"main": "./dist/index.js",
|
|
15
15
|
"exports": {
|
|
16
16
|
"./*": {
|
|
17
|
-
"
|
|
18
|
-
"
|
|
17
|
+
"types": "./dist/*.d.ts",
|
|
18
|
+
"default": "./dist/*"
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"typesVersions": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@tsconfig/node18": "^1.0.1",
|
|
45
45
|
"aws4fetch": "^1.0.18",
|
|
46
46
|
"chalk": "^5.3.0",
|
|
47
|
-
"esbuild": "0.
|
|
47
|
+
"esbuild": "0.25.4",
|
|
48
48
|
"express": "5.0.1",
|
|
49
49
|
"path-to-regexp": "^6.3.0",
|
|
50
50
|
"urlpattern-polyfill": "^10.0.0",
|