@opennextjs/aws 3.6.1 → 3.6.3
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/README.md +2 -0
- package/dist/adapters/config/index.d.ts +1 -0
- package/dist/adapters/config/index.js +2 -2
- package/dist/adapters/config/util.d.ts +1 -1
- package/dist/build/compileConfig.js +4 -0
- package/dist/build/copyTracedFiles.d.ts +2 -2
- package/dist/build/createMiddleware.js +2 -1
- package/dist/core/routing/cacheInterceptor.js +28 -0
- package/dist/core/routing/matcher.js +28 -1
- package/dist/core/routing/routeMatcher.d.ts +0 -1
- package/dist/core/routing/routeMatcher.js +29 -4
- package/dist/core/routingHandler.js +11 -9
- package/dist/overrides/converters/node.js +2 -1
- package/dist/overrides/imageLoader/fs-dev.js +5 -1
- package/dist/overrides/wrappers/express-dev.js +4 -2
- package/dist/plugins/edge.js +1 -1
- package/dist/utils/normalize-path.d.ts +1 -0
- package/dist/utils/normalize-path.js +7 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -96,6 +96,8 @@ To run `OpenNext` locally:
|
|
|
96
96
|
path/to/opennextjs-aws/packages/open-next/dist/index.js build
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
There is also a way to run OpenNext locally. You can read a guide about it [here](https://opennext.js.org/aws/contribute/local_run). Its mostly used for development/debugging purposes.
|
|
100
|
+
|
|
99
101
|
### Coldstart
|
|
100
102
|
|
|
101
103
|
OpenNext provide you with a warmer function that can be used to reduce cold start.
|
|
@@ -23,6 +23,7 @@ export declare const RoutesManifest: {
|
|
|
23
23
|
};
|
|
24
24
|
export declare const ConfigHeaders: import("../../types/next-types").Header[] | undefined;
|
|
25
25
|
export declare const PrerenderManifest: import("../../types/next-types").PrerenderManifest;
|
|
26
|
+
export declare const PagesManifest: Record<string, string>;
|
|
26
27
|
export declare const AppPathsManifestKeys: string[];
|
|
27
28
|
export declare const MiddlewareManifest: import("../../types/next-types").MiddlewareManifest;
|
|
28
29
|
export declare const AppPathsManifest: Record<string, string>;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { debug } from "../logger";
|
|
3
|
-
import { loadAppPathRoutesManifest, loadAppPathsManifest, loadAppPathsManifestKeys, loadBuildId, loadConfig, loadConfigHeaders, loadFunctionsConfigManifest, loadHtmlPages, loadMiddlewareManifest, loadPrerenderManifest, loadRoutesManifest, } from "./util.js";
|
|
3
|
+
import { loadAppPathRoutesManifest, loadAppPathsManifest, loadAppPathsManifestKeys, loadBuildId, loadConfig, loadConfigHeaders, loadFunctionsConfigManifest, loadHtmlPages, loadMiddlewareManifest, loadPagesManifest, loadPrerenderManifest, loadRoutesManifest, } from "./util.js";
|
|
4
4
|
export const NEXT_DIR = path.join(__dirname, ".next");
|
|
5
5
|
export const OPEN_NEXT_DIR = path.join(__dirname, ".open-next");
|
|
6
6
|
debug({ NEXT_DIR, OPEN_NEXT_DIR });
|
|
7
|
-
//TODO: inject these values at build time
|
|
8
7
|
export const NextConfig = /* @__PURE__ */ loadConfig(NEXT_DIR);
|
|
9
8
|
export const BuildId = /* @__PURE__ */ loadBuildId(NEXT_DIR);
|
|
10
9
|
export const HtmlPages = /* @__PURE__ */ loadHtmlPages(NEXT_DIR);
|
|
@@ -13,6 +12,7 @@ export const RoutesManifest = /* @__PURE__ */ loadRoutesManifest(NEXT_DIR);
|
|
|
13
12
|
export const ConfigHeaders = /* @__PURE__ */ loadConfigHeaders(NEXT_DIR);
|
|
14
13
|
export const PrerenderManifest =
|
|
15
14
|
/* @__PURE__ */ loadPrerenderManifest(NEXT_DIR);
|
|
15
|
+
export const PagesManifest = /* @__PURE__ */ loadPagesManifest(NEXT_DIR);
|
|
16
16
|
export const AppPathsManifestKeys =
|
|
17
17
|
/* @__PURE__ */ loadAppPathsManifestKeys(NEXT_DIR);
|
|
18
18
|
export const MiddlewareManifest =
|
|
@@ -2,7 +2,7 @@ import type { FunctionsConfigManifest, MiddlewareManifest, NextConfig, Prerender
|
|
|
2
2
|
import type { PublicFiles } from "../../build";
|
|
3
3
|
export declare function loadConfig(nextDir: string): NextConfig;
|
|
4
4
|
export declare function loadBuildId(nextDir: string): string;
|
|
5
|
-
export declare function loadPagesManifest(nextDir: string):
|
|
5
|
+
export declare function loadPagesManifest(nextDir: string): Record<string, string>;
|
|
6
6
|
export declare function loadHtmlPages(nextDir: string): string[];
|
|
7
7
|
export declare function loadPublicAssets(openNextDir: string): PublicFiles;
|
|
8
8
|
export declare function loadRoutesManifest(nextDir: string): {
|
|
@@ -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
|
}
|
|
@@ -10,7 +10,7 @@ export declare function getManifests(nextDir: string): {
|
|
|
10
10
|
buildId: string;
|
|
11
11
|
config: import("../types/next-types.js").NextConfig;
|
|
12
12
|
prerenderManifest: import("../types/next-types.js").PrerenderManifest;
|
|
13
|
-
pagesManifest:
|
|
13
|
+
pagesManifest: Record<string, string>;
|
|
14
14
|
appPathsManifest: Record<string, string>;
|
|
15
15
|
middlewareManifest: import("../types/next-types.js").MiddlewareManifest;
|
|
16
16
|
functionsConfigManifest: import("../types/next-types.js").FunctionsConfigManifest;
|
|
@@ -22,7 +22,7 @@ export declare function copyTracedFiles({ buildOutputPath, packagePath, outputDi
|
|
|
22
22
|
buildId: string;
|
|
23
23
|
config: import("../types/next-types.js").NextConfig;
|
|
24
24
|
prerenderManifest: import("../types/next-types.js").PrerenderManifest;
|
|
25
|
-
pagesManifest:
|
|
25
|
+
pagesManifest: Record<string, string>;
|
|
26
26
|
appPathsManifest: Record<string, string>;
|
|
27
27
|
middlewareManifest: import("../types/next-types.js").MiddlewareManifest;
|
|
28
28
|
functionsConfigManifest: import("../types/next-types.js").FunctionsConfigManifest;
|
|
@@ -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));
|
|
@@ -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,6 +140,8 @@ export async function cacheInterceptor(event) {
|
|
|
114
140
|
}
|
|
115
141
|
// We also need to remove trailing slash
|
|
116
142
|
localizedPath = localizedPath.replace(/\/$/, "");
|
|
143
|
+
// Then we decode the path params
|
|
144
|
+
localizedPath = decodePathParams(localizedPath);
|
|
117
145
|
debug("Checking cache for", localizedPath, PrerenderManifest);
|
|
118
146
|
const isISR = Object.keys(PrerenderManifest.routes).includes(localizedPath ?? "/") ||
|
|
119
147
|
Object.values(PrerenderManifest.dynamicRoutes).some((dr) => new RegExp(dr.routeRegex).test(localizedPath));
|
|
@@ -1,5 +1,6 @@
|
|
|
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";
|
|
@@ -169,6 +170,25 @@ export function handleRewrites(event, rewrites) {
|
|
|
169
170
|
isExternalRewrite,
|
|
170
171
|
};
|
|
171
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
|
+
}
|
|
172
192
|
function handleTrailingSlashRedirect(event) {
|
|
173
193
|
// When rawPath is `//domain`, `url.host` would be `domain`.
|
|
174
194
|
// https://github.com/opennextjs/opennextjs-aws/issues/355
|
|
@@ -215,6 +235,9 @@ function handleTrailingSlashRedirect(event) {
|
|
|
215
235
|
return false;
|
|
216
236
|
}
|
|
217
237
|
export function handleRedirects(event, redirects) {
|
|
238
|
+
const repeatedSlashRedirect = handleRepeatedSlashRedirect(event);
|
|
239
|
+
if (repeatedSlashRedirect)
|
|
240
|
+
return repeatedSlashRedirect;
|
|
218
241
|
const trailingSlashRedirect = handleTrailingSlashRedirect(event);
|
|
219
242
|
if (trailingSlashRedirect)
|
|
220
243
|
return trailingSlashRedirect;
|
|
@@ -279,7 +302,11 @@ export function handleFallbackFalse(internalEvent, prerenderManifest) {
|
|
|
279
302
|
? rawPath
|
|
280
303
|
: `/${NextConfig.i18n?.defaultLocale}${rawPath}`;
|
|
281
304
|
// We need to remove the trailing slash if it exists
|
|
282
|
-
if (
|
|
305
|
+
if (
|
|
306
|
+
// Not if localizedPath is "/" tho, because that would not make it find `isPregenerated` below since it would be try to match an empty string.
|
|
307
|
+
localizedPath !== "/" &&
|
|
308
|
+
NextConfig.trailingSlash &&
|
|
309
|
+
localizedPath.endsWith("/")) {
|
|
283
310
|
localizedPath = localizedPath.slice(0, -1);
|
|
284
311
|
}
|
|
285
312
|
const matchedStaticRoute = staticRouteMatcher(localizedPath);
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { AppPathRoutesManifest, RoutesManifest } from "../../adapters/config/index";
|
|
1
|
+
import { AppPathRoutesManifest, PagesManifest, RoutesManifest, } from "../../adapters/config/index";
|
|
2
2
|
// Add the locale prefix to the regex so we correctly match the rawPath
|
|
3
3
|
const optionalLocalePrefixRegex = `^/(?:${RoutesManifest.locales.map((locale) => `${locale}/?`).join("|")})?`;
|
|
4
4
|
// Add the basepath prefix to the regex so we correctly match the rawPath
|
|
5
5
|
const optionalBasepathPrefixRegex = RoutesManifest.basePath
|
|
6
6
|
? `^${RoutesManifest.basePath}/?`
|
|
7
7
|
: "^/";
|
|
8
|
-
// Add the basePath prefix to the api routes
|
|
9
|
-
export const apiPrefix = `${RoutesManifest.basePath ?? ""}/api`;
|
|
10
8
|
const optionalPrefix = optionalLocalePrefixRegex.replace("^/", optionalBasepathPrefixRegex);
|
|
11
9
|
function routeMatcher(routeDefinitions) {
|
|
12
10
|
const regexp = routeDefinitions.map((route) => ({
|
|
@@ -41,5 +39,32 @@ function routeMatcher(routeDefinitions) {
|
|
|
41
39
|
});
|
|
42
40
|
};
|
|
43
41
|
}
|
|
44
|
-
export const staticRouteMatcher = routeMatcher(
|
|
42
|
+
export const staticRouteMatcher = routeMatcher([
|
|
43
|
+
...RoutesManifest.routes.static,
|
|
44
|
+
...getStaticAPIRoutes(),
|
|
45
|
+
]);
|
|
45
46
|
export const dynamicRouteMatcher = routeMatcher(RoutesManifest.routes.dynamic);
|
|
47
|
+
/**
|
|
48
|
+
* Returns static API routes for both app and pages router cause Next will filter them out in staticRoutes in `routes-manifest.json`.
|
|
49
|
+
* We also need to filter out page files that are under `app/api/*` as those would not be present in the routes manifest either.
|
|
50
|
+
* This line from Next.js skips it:
|
|
51
|
+
* https://github.com/vercel/next.js/blob/ded56f952154a40dcfe53bdb38c73174e9eca9e5/packages/next/src/build/index.ts#L1299
|
|
52
|
+
*
|
|
53
|
+
* Without it handleFallbackFalse will 404 on static API routes if there is a catch-all route on root level.
|
|
54
|
+
*/
|
|
55
|
+
function getStaticAPIRoutes() {
|
|
56
|
+
const createRouteDefinition = (route) => ({
|
|
57
|
+
page: route,
|
|
58
|
+
regex: `^${route}(?:/)?$`,
|
|
59
|
+
});
|
|
60
|
+
const dynamicRoutePages = new Set(RoutesManifest.routes.dynamic.map(({ page }) => page));
|
|
61
|
+
const pagesStaticAPIRoutes = Object.keys(PagesManifest)
|
|
62
|
+
.filter((route) => route.startsWith("/api/") && !dynamicRoutePages.has(route))
|
|
63
|
+
.map(createRouteDefinition);
|
|
64
|
+
// We filter out both static API and page routes from the app paths manifest
|
|
65
|
+
const appPathsStaticAPIRoutes = Object.values(AppPathRoutesManifest)
|
|
66
|
+
.filter((route) => route.startsWith("/api/") ||
|
|
67
|
+
(route === "/api" && !dynamicRoutePages.has(route)))
|
|
68
|
+
.map(createRouteDefinition);
|
|
69
|
+
return [...pagesStaticAPIRoutes, ...appPathsStaticAPIRoutes];
|
|
70
|
+
}
|
|
@@ -4,7 +4,7 @@ import { cacheInterceptor } from "./routing/cacheInterceptor";
|
|
|
4
4
|
import { detectLocale } from "./routing/i18n";
|
|
5
5
|
import { fixDataPage, getNextConfigHeaders, handleFallbackFalse, handleRedirects, handleRewrites, } from "./routing/matcher";
|
|
6
6
|
import { handleMiddleware } from "./routing/middleware";
|
|
7
|
-
import {
|
|
7
|
+
import { dynamicRouteMatcher, staticRouteMatcher, } from "./routing/routeMatcher";
|
|
8
8
|
import { constructNextUrl } from "./routing/util";
|
|
9
9
|
export const MIDDLEWARE_HEADER_PREFIX = "x-middleware-response-";
|
|
10
10
|
export const MIDDLEWARE_HEADER_PREFIX_LEN = MIDDLEWARE_HEADER_PREFIX.length;
|
|
@@ -55,6 +55,9 @@ export default async function routingHandler(event) {
|
|
|
55
55
|
}
|
|
56
56
|
const redirect = handleRedirects(internalEvent, RoutesManifest.redirects);
|
|
57
57
|
if (redirect) {
|
|
58
|
+
// We need to encode the value in the Location header to make sure it is valid according to RFC
|
|
59
|
+
// https://stackoverflow.com/a/7654605/16587222
|
|
60
|
+
redirect.headers.Location = new URL(redirect.headers.Location).href;
|
|
58
61
|
debug("redirect", redirect);
|
|
59
62
|
return redirect;
|
|
60
63
|
}
|
|
@@ -85,9 +88,14 @@ export default async function routingHandler(event) {
|
|
|
85
88
|
internalEvent = afterRewrites.internalEvent;
|
|
86
89
|
isExternalRewrite = afterRewrites.isExternalRewrite;
|
|
87
90
|
}
|
|
91
|
+
let isISR = false;
|
|
88
92
|
// We want to run this just before the dynamic route check
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
// We can skip it if its an external rewrite
|
|
94
|
+
if (!isExternalRewrite) {
|
|
95
|
+
const fallbackResult = handleFallbackFalse(internalEvent, PrerenderManifest);
|
|
96
|
+
internalEvent = fallbackResult.event;
|
|
97
|
+
isISR = fallbackResult.isISR;
|
|
98
|
+
}
|
|
91
99
|
const foundDynamicRoute = dynamicRouteMatcher(internalEvent.rawPath);
|
|
92
100
|
const isDynamicRoute = !isExternalRewrite && foundDynamicRoute.length > 0;
|
|
93
101
|
if (!(isDynamicRoute || isStaticRoute || isExternalRewrite)) {
|
|
@@ -96,17 +104,11 @@ export default async function routingHandler(event) {
|
|
|
96
104
|
internalEvent = fallbackRewrites.internalEvent;
|
|
97
105
|
isExternalRewrite = fallbackRewrites.isExternalRewrite;
|
|
98
106
|
}
|
|
99
|
-
// Api routes are not present in the routes manifest except if they're not behind /api
|
|
100
|
-
// /api even if it's a page route doesn't get generated in the manifest
|
|
101
|
-
// Ideally we would need to properly check api routes here
|
|
102
|
-
const isApiRoute = internalEvent.rawPath === apiPrefix ||
|
|
103
|
-
internalEvent.rawPath.startsWith(`${apiPrefix}/`);
|
|
104
107
|
const isNextImageRoute = internalEvent.rawPath.startsWith("/_next/image");
|
|
105
108
|
const isRouteFoundBeforeAllRewrites = isStaticRoute || isDynamicRoute || isExternalRewrite;
|
|
106
109
|
// If we still haven't found a route, we show the 404 page
|
|
107
110
|
// We need to ensure that rewrites are applied before showing the 404 page
|
|
108
111
|
if (!(isRouteFoundBeforeAllRewrites ||
|
|
109
|
-
isApiRoute ||
|
|
110
112
|
isNextImageRoute ||
|
|
111
113
|
// We need to check again once all rewrites have been applied
|
|
112
114
|
staticRouteMatcher(internalEvent.rawPath).length > 0 ||
|
|
@@ -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,10 +1,14 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { NextConfig } from "../../adapters/config/index";
|
|
3
4
|
import { getMonorepoRelativePath } from "../../utils/normalize-path";
|
|
4
5
|
export default {
|
|
5
6
|
name: "fs-dev",
|
|
6
7
|
load: async (url) => {
|
|
7
|
-
const
|
|
8
|
+
const urlWithoutBasePath = NextConfig.basePath
|
|
9
|
+
? url.slice(NextConfig.basePath.length)
|
|
10
|
+
: url;
|
|
11
|
+
const imagePath = path.join(getMonorepoRelativePath(), "assets", urlWithoutBasePath);
|
|
8
12
|
const body = fs.createReadStream(imagePath);
|
|
9
13
|
const contentType = url.endsWith(".png") ? "image/png" : "image/jpeg";
|
|
10
14
|
return {
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import express from "express";
|
|
3
|
+
import { NextConfig } from "../../adapters/config/index";
|
|
3
4
|
import { getMonorepoRelativePath } from "../../utils/normalize-path";
|
|
4
5
|
const wrapper = async (handler, converter) => {
|
|
5
6
|
const app = express();
|
|
6
7
|
// To serve static assets
|
|
7
|
-
|
|
8
|
+
const basePath = NextConfig.basePath ?? "";
|
|
9
|
+
app.use(basePath, express.static(path.join(getMonorepoRelativePath(), "assets")));
|
|
8
10
|
const imageHandlerPath = path.join(getMonorepoRelativePath(), "image-optimization-function/index.mjs");
|
|
9
11
|
const imageHandler = await import(imageHandlerPath).then((m) => m.handler);
|
|
10
|
-
app.all("/_next/image
|
|
12
|
+
app.all(`${NextConfig.basePath ?? ""}/_next/image`, async (req, res) => {
|
|
11
13
|
const internalEvent = await converter.convertFrom(req);
|
|
12
14
|
const streamCreator = {
|
|
13
15
|
writeHeaders: (prelude) => {
|
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
|
};
|
|
@@ -2,6 +2,13 @@ import path from "node:path";
|
|
|
2
2
|
export function normalizePath(path) {
|
|
3
3
|
return path.replace(/\\/g, "/");
|
|
4
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
|
+
}
|
|
5
12
|
export function getMonorepoRelativePath(relativePath = "../..") {
|
|
6
13
|
return path.join(globalThis.monorepoPackagePath
|
|
7
14
|
.split("/")
|
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.3",
|
|
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",
|