@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,36 @@
1
+ import { NextConfig } from "../../../adapters/config/index.js";
2
+ import { debug } from "../../../adapters/logger.js";
3
+ import { acceptLanguage } from "./accept-header";
4
+ function isLocalizedPath(path) {
5
+ return (NextConfig.i18n?.locales.includes(path.split("/")[1].toLowerCase()) ?? false);
6
+ }
7
+ // https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/i18n/get-locale-redirect.ts
8
+ function getLocaleFromCookie(cookies) {
9
+ const i18n = NextConfig.i18n;
10
+ const nextLocale = cookies.NEXT_LOCALE?.toLowerCase();
11
+ return nextLocale
12
+ ? i18n?.locales.find((locale) => nextLocale === locale.toLowerCase())
13
+ : undefined;
14
+ }
15
+ function detectLocale(internalEvent, i18n) {
16
+ const cookiesLocale = getLocaleFromCookie(internalEvent.cookies);
17
+ const preferredLocale = acceptLanguage(internalEvent.headers["accept-language"], i18n?.locales);
18
+ debug({
19
+ cookiesLocale,
20
+ preferredLocale,
21
+ defaultLocale: i18n.defaultLocale,
22
+ });
23
+ return cookiesLocale ?? preferredLocale ?? i18n.defaultLocale;
24
+ // TODO: handle domain based locale detection
25
+ }
26
+ export function localizePath(internalEvent) {
27
+ const i18n = NextConfig.i18n;
28
+ if (!i18n) {
29
+ return internalEvent.rawPath;
30
+ }
31
+ if (isLocalizedPath(internalEvent.rawPath)) {
32
+ return internalEvent.rawPath;
33
+ }
34
+ const detectedLocale = detectLocale(internalEvent, i18n);
35
+ return `/${detectedLocale}${internalEvent.rawPath}`;
36
+ }
@@ -0,0 +1,25 @@
1
+ /// <reference types="node" />
2
+ import type { Header, PrerenderManifest, RedirectDefinition, RewriteDefinition } from "../../types/next-types";
3
+ import { InternalEvent, InternalResult } from "../../types/open-next";
4
+ export declare function addNextConfigHeaders(event: InternalEvent, configHeaders?: Header[] | undefined): Record<string, string | undefined>;
5
+ export declare function handleRewrites<T extends RewriteDefinition>(event: InternalEvent, rewrites: T[]): {
6
+ internalEvent: {
7
+ rawPath: string;
8
+ url: string;
9
+ method: string;
10
+ body?: Buffer | undefined;
11
+ headers: Record<string, string>;
12
+ query: Record<string, string | string[]>;
13
+ cookies: Record<string, string>;
14
+ remoteAddress: string;
15
+ type: "core";
16
+ };
17
+ __rewrite: T | undefined;
18
+ isExternalRewrite: boolean;
19
+ };
20
+ export declare function handleRedirects(event: InternalEvent, redirects: RedirectDefinition[]): InternalResult | undefined;
21
+ export declare function fixDataPage(internalEvent: InternalEvent, buildId: string): InternalEvent | InternalResult;
22
+ export declare function handleFallbackFalse(internalEvent: InternalEvent, prerenderManifest: PrerenderManifest): {
23
+ event: InternalEvent;
24
+ isISR: boolean;
25
+ };
@@ -0,0 +1,294 @@
1
+ import { NextConfig } from "../../adapters/config/index";
2
+ import { compile, match, } from "path-to-regexp";
3
+ import { emptyReadableStream, toReadableStream } from "../../utils/stream";
4
+ import { debug } from "../../adapters/logger";
5
+ import { localizePath } from "./i18n";
6
+ import { convertFromQueryString, convertToQueryString, escapeRegex, getUrlParts, isExternal, unescapeRegex, } from "./util";
7
+ const routeHasMatcher = (headers, cookies, query) => (redirect) => {
8
+ switch (redirect.type) {
9
+ case "header":
10
+ return (!!headers?.[redirect.key.toLowerCase()] &&
11
+ new RegExp(redirect.value ?? "").test(headers[redirect.key.toLowerCase()] ?? ""));
12
+ case "cookie":
13
+ return (!!cookies?.[redirect.key] &&
14
+ new RegExp(redirect.value ?? "").test(cookies[redirect.key] ?? ""));
15
+ case "query":
16
+ return query[redirect.key] && Array.isArray(redirect.value)
17
+ ? redirect.value.reduce((prev, current) => prev || new RegExp(current).test(query[redirect.key]), false)
18
+ : new RegExp(redirect.value ?? "").test(query[redirect.key] ?? "");
19
+ case "host":
20
+ return (headers?.host !== "" &&
21
+ new RegExp(redirect.value ?? "").test(headers.host));
22
+ default:
23
+ return false;
24
+ }
25
+ };
26
+ function checkHas(matcher, has, inverted = false) {
27
+ return has
28
+ ? has.reduce((acc, cur) => {
29
+ if (acc === false)
30
+ return false;
31
+ return inverted ? !matcher(cur) : matcher(cur);
32
+ }, true)
33
+ : true;
34
+ }
35
+ const getParamsFromSource = (source) => (value) => {
36
+ debug("value", value);
37
+ const _match = source(value);
38
+ return _match ? _match.params : {};
39
+ };
40
+ const computeParamHas = (headers, cookies, query) => (has) => {
41
+ if (!has.value)
42
+ return {};
43
+ const matcher = new RegExp(`^${has.value}$`);
44
+ const fromSource = (value) => {
45
+ const matches = value.match(matcher);
46
+ return matches?.groups ?? {};
47
+ };
48
+ switch (has.type) {
49
+ case "header":
50
+ return fromSource(headers[has.key.toLowerCase()] ?? "");
51
+ case "cookie":
52
+ return fromSource(cookies[has.key] ?? "");
53
+ case "query":
54
+ return Array.isArray(query[has.key])
55
+ ? fromSource(query[has.key].join(","))
56
+ : fromSource(query[has.key] ?? "");
57
+ case "host":
58
+ return fromSource(headers.host ?? "");
59
+ }
60
+ };
61
+ function convertMatch(match, toDestination, destination) {
62
+ if (match) {
63
+ const { params } = match;
64
+ const isUsingParams = Object.keys(params).length > 0;
65
+ if (isUsingParams) {
66
+ return toDestination(params);
67
+ }
68
+ else {
69
+ return destination;
70
+ }
71
+ }
72
+ else {
73
+ return destination;
74
+ }
75
+ }
76
+ export function addNextConfigHeaders(event, configHeaders) {
77
+ const addedHeaders = {};
78
+ if (!configHeaders)
79
+ return addedHeaders;
80
+ const { rawPath, headers, query, cookies } = event;
81
+ const matcher = routeHasMatcher(headers, cookies, query);
82
+ const requestHeaders = {};
83
+ const localizedRawPath = localizePath(event);
84
+ for (const { headers, has, missing, regex, source, locale, } of configHeaders) {
85
+ const path = locale === false ? rawPath : localizedRawPath;
86
+ if (new RegExp(regex).test(path) &&
87
+ checkHas(matcher, has) &&
88
+ checkHas(matcher, missing, true)) {
89
+ const fromSource = match(source);
90
+ const _match = fromSource(path);
91
+ headers.forEach((h) => {
92
+ try {
93
+ const key = convertMatch(_match, compile(h.key), h.key);
94
+ const value = convertMatch(_match, compile(h.value), h.value);
95
+ requestHeaders[key] = value;
96
+ }
97
+ catch {
98
+ debug("Error matching header ", h.key, " with value ", h.value);
99
+ requestHeaders[h.key] = h.value;
100
+ }
101
+ });
102
+ }
103
+ }
104
+ return requestHeaders;
105
+ }
106
+ export function handleRewrites(event, rewrites) {
107
+ const { rawPath, headers, query, cookies } = event;
108
+ const localizedRawPath = localizePath(event);
109
+ const matcher = routeHasMatcher(headers, cookies, query);
110
+ const computeHas = computeParamHas(headers, cookies, query);
111
+ const rewrite = rewrites.find((route) => {
112
+ const path = route.locale === false ? rawPath : localizedRawPath;
113
+ return (new RegExp(route.regex).test(path) &&
114
+ checkHas(matcher, route.has) &&
115
+ checkHas(matcher, route.missing, true));
116
+ });
117
+ let finalQuery = query;
118
+ let rewrittenUrl = rawPath;
119
+ const isExternalRewrite = isExternal(rewrite?.destination);
120
+ debug("isExternalRewrite", isExternalRewrite);
121
+ if (rewrite) {
122
+ const { pathname, protocol, hostname, queryString } = getUrlParts(rewrite.destination, isExternalRewrite);
123
+ // We need to use a localized path if the rewrite is not locale specific
124
+ const pathToUse = rewrite.locale === false ? rawPath : localizedRawPath;
125
+ debug("urlParts", { pathname, protocol, hostname, queryString });
126
+ const toDestinationPath = compile(escapeRegex(pathname ?? "") ?? "");
127
+ const toDestinationHost = compile(escapeRegex(hostname ?? "") ?? "");
128
+ const toDestinationQuery = compile(escapeRegex(queryString ?? "") ?? "");
129
+ let params = {
130
+ // params for the source
131
+ ...getParamsFromSource(match(escapeRegex(rewrite?.source) ?? ""))(pathToUse),
132
+ // params for the has
133
+ ...rewrite.has?.reduce((acc, cur) => {
134
+ return { ...acc, ...computeHas(cur) };
135
+ }, {}),
136
+ // params for the missing
137
+ ...rewrite.missing?.reduce((acc, cur) => {
138
+ return { ...acc, ...computeHas(cur) };
139
+ }, {}),
140
+ };
141
+ const isUsingParams = Object.keys(params).length > 0;
142
+ let rewrittenQuery = queryString;
143
+ let rewrittenHost = hostname;
144
+ let rewrittenPath = pathname;
145
+ if (isUsingParams) {
146
+ rewrittenPath = unescapeRegex(toDestinationPath(params));
147
+ rewrittenHost = unescapeRegex(toDestinationHost(params));
148
+ rewrittenQuery = unescapeRegex(toDestinationQuery(params));
149
+ }
150
+ rewrittenUrl = isExternalRewrite
151
+ ? `${protocol}//${rewrittenHost}${rewrittenPath}`
152
+ : `/${rewrittenPath}`;
153
+ // Should we merge the query params or use only the ones from the rewrite?
154
+ finalQuery = {
155
+ ...query,
156
+ ...convertFromQueryString(rewrittenQuery),
157
+ };
158
+ debug("rewrittenUrl", { rewrittenUrl, finalQuery, isUsingParams });
159
+ }
160
+ return {
161
+ internalEvent: {
162
+ ...event,
163
+ rawPath: rewrittenUrl,
164
+ url: `${rewrittenUrl}${convertToQueryString(finalQuery)}`,
165
+ },
166
+ __rewrite: rewrite,
167
+ isExternalRewrite,
168
+ };
169
+ }
170
+ function handleTrailingSlashRedirect(event) {
171
+ const url = new URL(event.url, "http://localhost");
172
+ const emptyBody = emptyReadableStream();
173
+ if (
174
+ // Someone is trying to redirect to a different origin, let's not do that
175
+ url.host !== "localhost" ||
176
+ NextConfig.skipTrailingSlashRedirect ||
177
+ // We should not apply trailing slash redirect to API routes
178
+ event.rawPath.startsWith("/api/")) {
179
+ return false;
180
+ }
181
+ if (NextConfig.trailingSlash &&
182
+ !event.headers["x-nextjs-data"] &&
183
+ !event.rawPath.endsWith("/") &&
184
+ !event.rawPath.match(/[\w-]+\.[\w]+$/g)) {
185
+ const headersLocation = event.url.split("?");
186
+ return {
187
+ type: event.type,
188
+ statusCode: 308,
189
+ headers: {
190
+ Location: `${headersLocation[0]}/${headersLocation[1] ? `?${headersLocation[1]}` : ""}`,
191
+ },
192
+ body: emptyBody,
193
+ isBase64Encoded: false,
194
+ };
195
+ // eslint-disable-next-line sonarjs/elseif-without-else
196
+ }
197
+ else if (!NextConfig.trailingSlash &&
198
+ event.rawPath.endsWith("/") &&
199
+ event.rawPath !== "/") {
200
+ const headersLocation = event.url.split("?");
201
+ return {
202
+ type: event.type,
203
+ statusCode: 308,
204
+ headers: {
205
+ Location: `${headersLocation[0].replace(/\/$/, "")}${headersLocation[1] ? `?${headersLocation[1]}` : ""}`,
206
+ },
207
+ body: emptyBody,
208
+ isBase64Encoded: false,
209
+ };
210
+ }
211
+ else
212
+ return false;
213
+ }
214
+ export function handleRedirects(event, redirects) {
215
+ const trailingSlashRedirect = handleTrailingSlashRedirect(event);
216
+ if (trailingSlashRedirect)
217
+ return trailingSlashRedirect;
218
+ const { internalEvent, __rewrite } = handleRewrites(event, redirects.filter((r) => !r.internal));
219
+ if (__rewrite && !__rewrite.internal) {
220
+ return {
221
+ type: event.type,
222
+ statusCode: __rewrite.statusCode ?? 308,
223
+ headers: {
224
+ Location: internalEvent.url,
225
+ },
226
+ body: emptyReadableStream(),
227
+ isBase64Encoded: false,
228
+ };
229
+ }
230
+ }
231
+ export function fixDataPage(internalEvent, buildId) {
232
+ const { rawPath, query } = internalEvent;
233
+ const dataPattern = `/_next/data/${buildId}`;
234
+ // Return 404 for data requests that don't match the buildId
235
+ if (rawPath.startsWith("/_next/data") && !rawPath.startsWith(dataPattern)) {
236
+ return {
237
+ type: internalEvent.type,
238
+ statusCode: 404,
239
+ body: toReadableStream("{}"),
240
+ headers: {
241
+ "Content-Type": "application/json",
242
+ },
243
+ isBase64Encoded: false,
244
+ };
245
+ }
246
+ if (rawPath.startsWith(dataPattern) && rawPath.endsWith(".json")) {
247
+ let newPath = rawPath.replace(dataPattern, "").replace(/\.json$/, "");
248
+ newPath = newPath === "/index" ? "/" : newPath;
249
+ query.__nextDataReq = "1";
250
+ return {
251
+ ...internalEvent,
252
+ rawPath: newPath,
253
+ query,
254
+ url: `${newPath}${convertToQueryString(query)}`,
255
+ };
256
+ }
257
+ return internalEvent;
258
+ }
259
+ export function handleFallbackFalse(internalEvent, prerenderManifest) {
260
+ const { rawPath } = internalEvent;
261
+ const { dynamicRoutes, routes } = prerenderManifest;
262
+ const routeFallback = Object.entries(dynamicRoutes)
263
+ .filter(([, { fallback }]) => fallback === false)
264
+ .some(([, { routeRegex }]) => {
265
+ const routeRegexExp = new RegExp(routeRegex);
266
+ return routeRegexExp.test(rawPath);
267
+ });
268
+ const locales = NextConfig.i18n?.locales;
269
+ const routesAlreadyHaveLocale = (locales !== undefined && locales.includes(rawPath.split("/")[1])) ||
270
+ // If we don't use locales, we don't need to add the default locale
271
+ locales === undefined;
272
+ const localizedPath = routesAlreadyHaveLocale
273
+ ? rawPath
274
+ : `/${NextConfig.i18n?.defaultLocale}${rawPath}`;
275
+ const isPregenerated = Object.keys(routes).includes(localizedPath);
276
+ if (routeFallback && !isPregenerated) {
277
+ return {
278
+ event: {
279
+ ...internalEvent,
280
+ rawPath: "/404",
281
+ url: "/404",
282
+ headers: {
283
+ ...internalEvent.headers,
284
+ "x-invoke-status": "404",
285
+ },
286
+ },
287
+ isISR: false,
288
+ };
289
+ }
290
+ return {
291
+ event: internalEvent,
292
+ isISR: routeFallback || isPregenerated,
293
+ };
294
+ }
@@ -0,0 +1,7 @@
1
+ import { InternalEvent, InternalResult } from "../../types/open-next.js";
2
+ type MiddlewareOutputEvent = InternalEvent & {
3
+ responseHeaders?: Record<string, string | string[]>;
4
+ externalRewrite?: boolean;
5
+ };
6
+ export declare function handleMiddleware(internalEvent: InternalEvent): Promise<MiddlewareOutputEvent | InternalResult>;
7
+ export {};
@@ -0,0 +1,167 @@
1
+ import { MiddlewareManifest, NextConfig } from "../../adapters/config/index.js";
2
+ import { emptyReadableStream } from "../../utils/stream.js";
3
+ import { localizePath } from "./i18n/index.js";
4
+ //NOTE: we should try to avoid importing stuff from next as much as possible
5
+ // every release of next could break this
6
+ // const { run } = require("next/dist/server/web/sandbox");
7
+ // const { getCloneableBody } = require("next/dist/server/body-streams");
8
+ // const {
9
+ // signalFromNodeResponse,
10
+ // } = require("next/dist/server/web/spec-extension/adapters/next-request");
11
+ import { convertBodyToReadableStream, convertToQueryString, getMiddlewareMatch, isExternal, } from "./util.js";
12
+ const middlewareManifest = MiddlewareManifest;
13
+ const middleMatch = getMiddlewareMatch(middlewareManifest);
14
+ // NOTE: As of Nextjs 13.4.13+, the middleware is handled outside the next-server.
15
+ // OpenNext will run the middleware in a sandbox and set the appropriate req headers
16
+ // and res.body prior to processing the next-server.
17
+ // @returns undefined | res.end()
18
+ // if res.end() is return, the parent needs to return and not process next server
19
+ export async function handleMiddleware(internalEvent) {
20
+ const { query } = internalEvent;
21
+ const normalizedPath = localizePath(internalEvent);
22
+ // We only need the normalizedPath to check if the middleware should run
23
+ const hasMatch = middleMatch.some((r) => r.test(normalizedPath));
24
+ if (!hasMatch)
25
+ return internalEvent;
26
+ // We bypass the middleware if the request is internal
27
+ if (internalEvent.headers["x-isr"])
28
+ return internalEvent;
29
+ const host = internalEvent.headers.host
30
+ ? `https://${internalEvent.headers.host}`
31
+ : "http://localhost:3000";
32
+ const initialUrl = new URL(normalizedPath, host);
33
+ initialUrl.search = convertToQueryString(query);
34
+ const url = initialUrl.toString();
35
+ // console.log("url", url, normalizedPath);
36
+ // @ts-expect-error - This is bundled
37
+ const middleware = await import("./middleware.mjs");
38
+ const result = await middleware.default({
39
+ geo: {
40
+ city: internalEvent.headers["x-open-next-city"],
41
+ country: internalEvent.headers["x-open-next-country"],
42
+ region: internalEvent.headers["x-open-next-region"],
43
+ latitude: internalEvent.headers["x-open-next-latitude"],
44
+ longitude: internalEvent.headers["x-open-next-longitude"],
45
+ },
46
+ headers: internalEvent.headers,
47
+ method: internalEvent.method || "GET",
48
+ nextConfig: {
49
+ basePath: NextConfig.basePath,
50
+ i18n: NextConfig.i18n,
51
+ trailingSlash: NextConfig.trailingSlash,
52
+ },
53
+ url,
54
+ body: convertBodyToReadableStream(internalEvent.method, internalEvent.body),
55
+ });
56
+ const statusCode = result.status;
57
+ /* Apply override headers from middleware
58
+ NextResponse.next({
59
+ request: {
60
+ headers: new Headers(request.headers),
61
+ }
62
+ })
63
+ Nextjs will set `x-middleware-override-headers` as a comma separated list of keys.
64
+ All the keys will be prefixed with `x-middleware-request-<key>`
65
+
66
+ We can delete `x-middleware-override-headers` and check if the key starts with
67
+ x-middleware-request- to set the req headers
68
+ */
69
+ const responseHeaders = result.headers;
70
+ const reqHeaders = {};
71
+ const resHeaders = {};
72
+ responseHeaders.delete("x-middleware-override-headers");
73
+ const xMiddlewareKey = "x-middleware-request-";
74
+ responseHeaders.forEach((value, key) => {
75
+ if (key.startsWith(xMiddlewareKey)) {
76
+ const k = key.substring(xMiddlewareKey.length);
77
+ reqHeaders[k] = value;
78
+ }
79
+ else {
80
+ if (key.toLowerCase() === "set-cookie") {
81
+ resHeaders[key] = resHeaders[key]
82
+ ? [...resHeaders[key], value]
83
+ : [value];
84
+ }
85
+ else {
86
+ resHeaders[key] = value;
87
+ }
88
+ }
89
+ });
90
+ // If the middleware returned a Redirect, we set the `Location` header with
91
+ // the redirected url and end the response.
92
+ if (statusCode >= 300 && statusCode < 400) {
93
+ resHeaders.location =
94
+ responseHeaders
95
+ .get("location")
96
+ ?.replace("http://localhost:3000", `https://${internalEvent.headers.host}`) ?? resHeaders.location;
97
+ // res.setHeader("Location", location);
98
+ return {
99
+ body: emptyReadableStream(),
100
+ type: internalEvent.type,
101
+ statusCode: statusCode,
102
+ headers: resHeaders,
103
+ isBase64Encoded: false,
104
+ };
105
+ }
106
+ // If the middleware returned a Rewrite, set the `url` to the pathname of the rewrite
107
+ // NOTE: the header was added to `req` from above
108
+ const rewriteUrl = responseHeaders.get("x-middleware-rewrite");
109
+ let rewritten = false;
110
+ let externalRewrite = false;
111
+ let middlewareQueryString = internalEvent.query;
112
+ let newUrl = internalEvent.url;
113
+ if (rewriteUrl) {
114
+ // If not a string, it should probably throw
115
+ if (isExternal(rewriteUrl, internalEvent.headers.host)) {
116
+ newUrl = rewriteUrl;
117
+ rewritten = true;
118
+ externalRewrite = true;
119
+ }
120
+ else {
121
+ const rewriteUrlObject = new URL(rewriteUrl);
122
+ newUrl = rewriteUrlObject.pathname;
123
+ // Reset the query params if the middleware is a rewrite
124
+ if (middlewareQueryString["__nextDataReq"]) {
125
+ middlewareQueryString = {
126
+ __nextDataReq: middlewareQueryString["__nextDataReq"],
127
+ };
128
+ }
129
+ else {
130
+ middlewareQueryString = {};
131
+ }
132
+ rewriteUrlObject.searchParams.forEach((v, k) => {
133
+ middlewareQueryString[k] = v;
134
+ });
135
+ rewritten = true;
136
+ }
137
+ }
138
+ // If the middleware returned a `NextResponse`, pipe the body to res. This will return
139
+ // the body immediately to the client.
140
+ if (result.body) {
141
+ // transfer response body to res
142
+ const body = result.body;
143
+ // await pipeReadable(result.response.body, res);
144
+ return {
145
+ type: internalEvent.type,
146
+ statusCode: statusCode,
147
+ headers: resHeaders,
148
+ body,
149
+ isBase64Encoded: false,
150
+ };
151
+ }
152
+ return {
153
+ responseHeaders: resHeaders,
154
+ url: newUrl,
155
+ rawPath: rewritten
156
+ ? newUrl ?? internalEvent.rawPath
157
+ : internalEvent.rawPath,
158
+ type: internalEvent.type,
159
+ headers: { ...internalEvent.headers, ...reqHeaders },
160
+ body: internalEvent.body,
161
+ method: internalEvent.method,
162
+ query: middlewareQueryString,
163
+ cookies: internalEvent.cookies,
164
+ remoteAddress: internalEvent.remoteAddress,
165
+ externalRewrite,
166
+ };
167
+ }
@@ -0,0 +1,105 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { OutgoingHttpHeaders } from "node:http";
4
+ import type { IncomingMessage, StreamCreator } from "../../http/index.js";
5
+ import { OpenNextNodeResponse } from "../../http/openNextResponse.js";
6
+ import type { MiddlewareManifest } from "../../types/next-types";
7
+ import { InternalEvent, InternalResult } from "../../types/open-next.js";
8
+ /**
9
+ *
10
+ * @__PURE__
11
+ */
12
+ export declare function isExternal(url?: string, host?: string): boolean;
13
+ export declare function convertFromQueryString(query: string): Record<string, string>;
14
+ /**
15
+ *
16
+ * @__PURE__
17
+ */
18
+ export declare function getUrlParts(url: string, isExternal: boolean): {
19
+ hostname: string;
20
+ pathname: string;
21
+ protocol: string;
22
+ queryString: string;
23
+ };
24
+ /**
25
+ *
26
+ * @__PURE__
27
+ */
28
+ export declare function convertRes(res: OpenNextNodeResponse): InternalResult;
29
+ /**
30
+ * Make sure that multi-value query parameters are transformed to
31
+ * ?key=value1&key=value2&... so that Next converts those parameters
32
+ * to an array when reading the query parameters
33
+ * @__PURE__
34
+ */
35
+ export declare function convertToQueryString(query: Record<string, string | string[]>): string;
36
+ /**
37
+ * Given a raw query string, returns a record with key value-array pairs
38
+ * similar to how multiValueQueryStringParameters are structured
39
+ * @__PURE__
40
+ */
41
+ export declare function convertToQuery(querystring: string): Record<string, string | string[]>;
42
+ /**
43
+ *
44
+ * @__PURE__
45
+ */
46
+ export declare function getMiddlewareMatch(middlewareManifest: MiddlewareManifest): RegExp[];
47
+ /**
48
+ *
49
+ * @__PURE__
50
+ */
51
+ export declare function escapeRegex(str: string): string;
52
+ /**
53
+ *
54
+ * @__PURE__
55
+ */
56
+ export declare function unescapeRegex(str: string): string;
57
+ /**
58
+ * @__PURE__
59
+ */
60
+ export declare function convertBodyToReadableStream(method: string, body?: string | Buffer): ReadableStream<any> | undefined;
61
+ /**
62
+ *
63
+ * @__PURE__
64
+ */
65
+ export declare function proxyRequest(internalEvent: InternalEvent, res: OpenNextNodeResponse): Promise<void>;
66
+ declare global {
67
+ var openNextDebug: boolean;
68
+ var openNextVersion: string;
69
+ var lastModified: Record<string, number>;
70
+ }
71
+ /**
72
+ *
73
+ * @__PURE__
74
+ */
75
+ export declare function fixCacheHeaderForHtmlPages(rawPath: string, headers: OutgoingHttpHeaders): void;
76
+ /**
77
+ *
78
+ * @__PURE__
79
+ */
80
+ export declare function fixSWRCacheHeader(headers: OutgoingHttpHeaders): void;
81
+ /**
82
+ *
83
+ * @__PURE__
84
+ */
85
+ export declare function addOpenNextHeader(headers: OutgoingHttpHeaders): void;
86
+ /**
87
+ *
88
+ * @__PURE__
89
+ */
90
+ export declare function revalidateIfRequired(host: string, rawPath: string, headers: OutgoingHttpHeaders, req?: IncomingMessage): Promise<void>;
91
+ export declare function generateMessageGroupId(rawPath: string): string;
92
+ /**
93
+ *
94
+ * @__PURE__
95
+ */
96
+ export declare function fixISRHeaders(headers: OutgoingHttpHeaders): void;
97
+ /**
98
+ *
99
+ * @param internalEvent
100
+ * @param headers
101
+ * @param responseStream
102
+ * @returns
103
+ * @__PURE__
104
+ */
105
+ export declare function createServerResponse(internalEvent: InternalEvent, headers: Record<string, string | string[] | undefined>, responseStream?: StreamCreator): OpenNextNodeResponse;