@opennextjs/aws 3.7.2 → 3.7.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.
@@ -1,4 +1,5 @@
1
1
  import type { CacheHandlerValue, IncrementalCacheContext, IncrementalCacheValue } from "../types/cache";
2
+ export declare const SOFT_TAG_PREFIX = "_N_T_/";
2
3
  export default class Cache {
3
4
  get(key: string, options?: boolean | {
4
5
  fetchCache?: boolean;
@@ -1,6 +1,7 @@
1
1
  import { getTagsFromValue, hasBeenRevalidated, writeTags } from "../utils/cache";
2
2
  import { isBinaryContentType } from "../utils/binary";
3
3
  import { debug, error, warn } from "./logger";
4
+ export const SOFT_TAG_PREFIX = "_N_T_/";
4
5
  function isFetchCache(options) {
5
6
  if (typeof options === "boolean") {
6
7
  return options;
@@ -34,18 +35,22 @@ export default class Cache {
34
35
  return null;
35
36
  const _tags = [...(tags ?? []), ...(softTags ?? [])];
36
37
  const _lastModified = cachedEntry.lastModified ?? Date.now();
37
- const _hasBeenRevalidated = await hasBeenRevalidated(key, _tags, cachedEntry);
38
+ const _hasBeenRevalidated = cachedEntry.shouldBypassTagCache
39
+ ? false
40
+ : await hasBeenRevalidated(key, _tags, cachedEntry);
38
41
  if (_hasBeenRevalidated)
39
42
  return null;
40
43
  // For cases where we don't have tags, we need to ensure that the soft tags are not being revalidated
41
44
  // We only need to check for the path as it should already contain all the tags
42
45
  if ((tags ?? []).length === 0) {
43
46
  // Then we need to find the path for the given key
44
- const path = softTags?.find((tag) => tag.startsWith("_N_T_/") &&
47
+ const path = softTags?.find((tag) => tag.startsWith(SOFT_TAG_PREFIX) &&
45
48
  !tag.endsWith("layout") &&
46
49
  !tag.endsWith("page"));
47
50
  if (path) {
48
- const hasPathBeenUpdated = await hasBeenRevalidated(path.replace("_N_T_/", ""), [], cachedEntry);
51
+ const hasPathBeenUpdated = cachedEntry.shouldBypassTagCache
52
+ ? false
53
+ : await hasBeenRevalidated(path.replace(SOFT_TAG_PREFIX, ""), [], cachedEntry);
49
54
  if (hasPathBeenUpdated) {
50
55
  // In case the path has been revalidated, we don't want to use the fetch cache
51
56
  return null;
@@ -73,7 +78,9 @@ export default class Cache {
73
78
  const meta = cacheData.meta;
74
79
  const tags = getTagsFromValue(cacheData);
75
80
  const _lastModified = cachedEntry.lastModified ?? Date.now();
76
- const _hasBeenRevalidated = await hasBeenRevalidated(key, tags, cachedEntry);
81
+ const _hasBeenRevalidated = cachedEntry.shouldBypassTagCache
82
+ ? false
83
+ : await hasBeenRevalidated(key, tags, cachedEntry);
77
84
  if (_hasBeenRevalidated)
78
85
  return null;
79
86
  const store = globalThis.__openNextAls.getStore();
@@ -274,11 +281,11 @@ export default class Cache {
274
281
  tag,
275
282
  }));
276
283
  // If the tag is a soft tag, we should also revalidate the hard tags
277
- if (tag.startsWith("_N_T_/")) {
284
+ if (tag.startsWith(SOFT_TAG_PREFIX)) {
278
285
  for (const path of paths) {
279
286
  // We need to find all hard tags for a given path
280
287
  const _tags = await globalThis.tagCache.getByPath(path);
281
- const hardTags = _tags.filter((t) => !t.startsWith("_N_T_/"));
288
+ const hardTags = _tags.filter((t) => !t.startsWith(SOFT_TAG_PREFIX));
282
289
  // For every hard tag, we need to find all paths and revalidate them
283
290
  for (const hardTag of hardTags) {
284
291
  const _paths = await globalThis.tagCache.getByTag(hardTag);
@@ -296,7 +303,7 @@ export default class Cache {
296
303
  // This only applies to `revalidateTag`, not to `res.revalidate()`
297
304
  const uniquePaths = Array.from(new Set(toInsert
298
305
  // We need to filter fetch cache key as they are not in the CDN
299
- .filter((t) => t.tag.startsWith("_N_T_/"))
306
+ .filter((t) => t.tag.startsWith(SOFT_TAG_PREFIX))
300
307
  .map((t) => `/${t.path}`)));
301
308
  if (uniquePaths.length > 0) {
302
309
  await globalThis.cdnInvalidationHandler.invalidatePaths(uniquePaths.map((path) => ({
@@ -8,7 +8,13 @@ export default {
8
8
  // We first check if we have a pending write for this cache key
9
9
  // If we do, we return the pending promise instead of fetching the cache
10
10
  if (pendingWritePromiseMap.has(cacheKey)) {
11
- return pendingWritePromiseMap.get(cacheKey);
11
+ const stored = pendingWritePromiseMap.get(cacheKey);
12
+ if (stored) {
13
+ return stored.then((entry) => ({
14
+ ...entry,
15
+ value: toReadableStream(entry.value),
16
+ }));
17
+ }
12
18
  }
13
19
  const result = await globalThis.incrementalCache.get(cacheKey, "composable");
14
20
  if (!result?.value?.value) {
@@ -18,13 +24,17 @@ export default {
18
24
  // We need to check if the tags associated with this entry has been revalidated
19
25
  if (globalThis.tagCache.mode === "nextMode" &&
20
26
  result.value.tags.length > 0) {
21
- const hasBeenRevalidated = await globalThis.tagCache.hasBeenRevalidated(result.value.tags, result.lastModified);
27
+ const hasBeenRevalidated = result.shouldBypassTagCache
28
+ ? false
29
+ : await globalThis.tagCache.hasBeenRevalidated(result.value.tags, result.lastModified);
22
30
  if (hasBeenRevalidated)
23
31
  return undefined;
24
32
  }
25
33
  else if (globalThis.tagCache.mode === "original" ||
26
34
  globalThis.tagCache.mode === undefined) {
27
- const hasBeenRevalidated = (await globalThis.tagCache.getLastModified(cacheKey, result.lastModified)) === -1;
35
+ const hasBeenRevalidated = result.shouldBypassTagCache
36
+ ? false
37
+ : (await globalThis.tagCache.getLastModified(cacheKey, result.lastModified)) === -1;
28
38
  if (hasBeenRevalidated)
29
39
  return undefined;
30
40
  }
@@ -39,14 +49,17 @@ export default {
39
49
  }
40
50
  },
41
51
  async set(cacheKey, pendingEntry) {
42
- pendingWritePromiseMap.set(cacheKey, pendingEntry);
43
- const entry = await pendingEntry.finally(() => {
52
+ const promiseEntry = pendingEntry.then(async (entry) => ({
53
+ ...entry,
54
+ value: await fromReadableStream(entry.value),
55
+ }));
56
+ pendingWritePromiseMap.set(cacheKey, promiseEntry);
57
+ const entry = await promiseEntry.finally(() => {
44
58
  pendingWritePromiseMap.delete(cacheKey);
45
59
  });
46
- const valueToStore = await fromReadableStream(entry.value);
47
60
  await globalThis.incrementalCache.set(cacheKey, {
48
61
  ...entry,
49
- value: valueToStore,
62
+ value: entry.value,
50
63
  }, "composable");
51
64
  if (globalThis.tagCache.mode === "original") {
52
65
  const storedTags = await globalThis.tagCache.getByPath(cacheKey);
@@ -3,7 +3,7 @@ import { debug, error } from "../adapters/logger";
3
3
  import { createGenericHandler } from "../core/createGenericHandler";
4
4
  import { resolveAssetResolver, resolveIncrementalCache, resolveOriginResolver, resolveProxyRequest, resolveQueue, resolveTagCache, } from "../core/resolve";
5
5
  import { constructNextUrl } from "../core/routing/util";
6
- import routingHandler, { INTERNAL_EVENT_REQUEST_ID, INTERNAL_HEADER_INITIAL_URL, INTERNAL_HEADER_RESOLVED_ROUTES, } from "../core/routingHandler";
6
+ import routingHandler, { INTERNAL_EVENT_REQUEST_ID, INTERNAL_HEADER_REWRITE_STATUS_CODE, INTERNAL_HEADER_INITIAL_URL, INTERNAL_HEADER_RESOLVED_ROUTES, } from "../core/routingHandler";
7
7
  globalThis.internalFetch = fetch;
8
8
  globalThis.__openNextAls = new AsyncLocalStorage();
9
9
  const defaultHandler = async (internalEvent, options) => {
@@ -39,6 +39,7 @@ const defaultHandler = async (internalEvent, options) => {
39
39
  [INTERNAL_HEADER_INITIAL_URL]: internalEvent.url,
40
40
  [INTERNAL_HEADER_RESOLVED_ROUTES]: JSON.stringify(result.resolvedRoutes),
41
41
  [INTERNAL_EVENT_REQUEST_ID]: requestId,
42
+ [INTERNAL_HEADER_REWRITE_STATUS_CODE]: String(result.rewriteStatusCode),
42
43
  },
43
44
  },
44
45
  isExternalRewrite: result.isExternalRewrite,
@@ -74,7 +74,7 @@ export async function generateOutput(options) {
74
74
  Object.entries(config.functions ?? {}).forEach(async ([key, value]) => {
75
75
  if (value.placement === "global") {
76
76
  edgeFunctions[key] = {
77
- bundle: `.open-next/functions/${key}`,
77
+ bundle: `.open-next/server-functions/${key}`,
78
78
  handler: indexHandler,
79
79
  ...(await extractOverrideFn(value.override)),
80
80
  };
@@ -5,7 +5,7 @@ import { NextConfig } from "../adapters/config/index";
5
5
  import { debug, error } from "../adapters/logger";
6
6
  import { patchAsyncStorage } from "./patchAsyncStorage";
7
7
  import { constructNextUrl, convertRes, convertToQuery, convertToQueryString, createServerResponse, } from "./routing/util";
8
- import routingHandler, { INTERNAL_EVENT_REQUEST_ID, INTERNAL_HEADER_INITIAL_URL, INTERNAL_HEADER_RESOLVED_ROUTES, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_HEADER_PREFIX_LEN, } from "./routingHandler";
8
+ import routingHandler, { INTERNAL_EVENT_REQUEST_ID, INTERNAL_HEADER_REWRITE_STATUS_CODE, INTERNAL_HEADER_INITIAL_URL, INTERNAL_HEADER_RESOLVED_ROUTES, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_HEADER_PREFIX_LEN, } from "./routingHandler";
9
9
  import { requestHandler, setNextjsPrebundledReact } from "./util";
10
10
  // This is used to identify requests in the cache
11
11
  globalThis.__openNextAls = new AsyncLocalStorage();
@@ -37,6 +37,7 @@ export async function openNextHandler(internalEvent, options) {
37
37
  resolvedRoutes: initialHeaders[INTERNAL_HEADER_RESOLVED_ROUTES]
38
38
  ? JSON.parse(initialHeaders[INTERNAL_HEADER_RESOLVED_ROUTES])
39
39
  : [],
40
+ rewriteStatusCode: Number.parseInt(initialHeaders[INTERNAL_HEADER_REWRITE_STATUS_CODE]),
40
41
  };
41
42
  let routingResult = {
42
43
  internalEvent,
@@ -2,6 +2,7 @@ import type { InternalEvent, InternalResult } from "../../types/open-next.js";
2
2
  type MiddlewareEvent = InternalEvent & {
3
3
  responseHeaders?: Record<string, string | string[]>;
4
4
  isExternalRewrite?: boolean;
5
+ rewriteStatusCode?: number;
5
6
  };
6
7
  type Middleware = (request: Request) => Response | Promise<Response>;
7
8
  type MiddlewareLoader = () => Promise<{
@@ -2,10 +2,11 @@ import { FunctionsConfigManifest, MiddlewareManifest, NextConfig, PrerenderManif
2
2
  import { emptyReadableStream } from "../../utils/stream.js";
3
3
  import { getQueryFromSearchParams } from "../../overrides/converters/utils.js";
4
4
  import { localizePath } from "./i18n/index.js";
5
- import { convertBodyToReadableStream, getMiddlewareMatch, isExternal, } from "./util.js";
5
+ import { convertBodyToReadableStream, getMiddlewareMatch, isExternal, normalizeLocationHeader, } from "./util.js";
6
6
  const middlewareManifest = MiddlewareManifest;
7
7
  const functionsConfigManifest = FunctionsConfigManifest;
8
8
  const middleMatch = getMiddlewareMatch(middlewareManifest, functionsConfigManifest);
9
+ const REDIRECTS = new Set([301, 302, 303, 307, 308]);
9
10
  function defaultMiddlewareLoader() {
10
11
  // @ts-expect-error - This is bundled
11
12
  return import("./middleware.mjs");
@@ -94,6 +95,10 @@ export async function handleMiddleware(internalEvent, initialSearch, middlewareL
94
95
  ? [...resHeaders[key], value]
95
96
  : [value];
96
97
  }
98
+ else if (REDIRECTS.has(statusCode) &&
99
+ key.toLowerCase() === "location") {
100
+ resHeaders[key] = normalizeLocationHeader(value, internalEvent.url);
101
+ }
97
102
  else {
98
103
  resHeaders[key] = value;
99
104
  }
@@ -146,5 +151,6 @@ export async function handleMiddleware(internalEvent, initialSearch, middlewareL
146
151
  cookies: internalEvent.cookies,
147
152
  remoteAddress: internalEvent.remoteAddress,
148
153
  isExternalRewrite,
154
+ rewriteStatusCode: statusCode,
149
155
  };
150
156
  }
@@ -104,3 +104,16 @@ export declare function fixISRHeaders(headers: OutgoingHttpHeaders): void;
104
104
  */
105
105
  export declare function createServerResponse(routingResult: RoutingResult, headers: Record<string, string | string[] | undefined>, responseStream?: StreamCreator): OpenNextNodeResponse;
106
106
  export declare function invalidateCDNOnRequest(params: RoutingResult, headers: OutgoingHttpHeaders): Promise<void>;
107
+ /**
108
+ * Normalizes the Location header to either be a relative path or a full URL.
109
+ * If the Location header is relative to the origin, it will return a relative path.
110
+ * If it is an absolute URL, it will return the full URL.
111
+ * Redirects from Next config query parameters are encoded using `stringifyQs`
112
+ * Redirects from the middleware the query parameters are not encoded.
113
+ *
114
+ * @param location The Location header value
115
+ * @param baseUrl The base URL to use for relative paths (i.e the original request URL)
116
+ * @param encodeQuery Optional flag to indicate if query parameters should be encoded in the Location header
117
+ * @returns An absolute or relative Location header value
118
+ */
119
+ export declare function normalizeLocationHeader(location: string, baseUrl: string, encodeQuery?: boolean): string;
@@ -1,4 +1,5 @@
1
1
  import crypto from "node:crypto";
2
+ import { parse as parseQs, stringify as stringifyQs } from "node:querystring";
2
3
  import { Readable } from "node:stream";
3
4
  import { BuildId, HtmlPages, NextConfig } from "../../adapters/config/index.js";
4
5
  import { OpenNextNodeResponse } from "../../http/openNextResponse.js";
@@ -338,7 +339,7 @@ export function createServerResponse(routingResult, headers, responseStream) {
338
339
  }, async (_headers) => {
339
340
  await revalidateIfRequired(internalEvent.headers.host, internalEvent.rawPath, _headers);
340
341
  await invalidateCDNOnRequest(routingResult, _headers);
341
- }, responseStream, headers);
342
+ }, responseStream, headers, routingResult.rewriteStatusCode);
342
343
  }
343
344
  // This function is used only for `res.revalidate()`
344
345
  export async function invalidateCDNOnRequest(params, headers) {
@@ -356,3 +357,35 @@ export async function invalidateCDNOnRequest(params, headers) {
356
357
  ]);
357
358
  }
358
359
  }
360
+ /**
361
+ * Normalizes the Location header to either be a relative path or a full URL.
362
+ * If the Location header is relative to the origin, it will return a relative path.
363
+ * If it is an absolute URL, it will return the full URL.
364
+ * Redirects from Next config query parameters are encoded using `stringifyQs`
365
+ * Redirects from the middleware the query parameters are not encoded.
366
+ *
367
+ * @param location The Location header value
368
+ * @param baseUrl The base URL to use for relative paths (i.e the original request URL)
369
+ * @param encodeQuery Optional flag to indicate if query parameters should be encoded in the Location header
370
+ * @returns An absolute or relative Location header value
371
+ */
372
+ export function normalizeLocationHeader(location, baseUrl, encodeQuery = false) {
373
+ if (!URL.canParse(location)) {
374
+ // If the location is not a valid URL, return it as-is
375
+ return location;
376
+ }
377
+ const locationURL = new URL(location);
378
+ const origin = new URL(baseUrl).origin;
379
+ let search = locationURL.search;
380
+ // If encodeQuery is true, we need to encode the query parameters
381
+ // We could have used URLSearchParams, but that doesn't match what Next does.
382
+ if (encodeQuery && search) {
383
+ search = `?${stringifyQs(parseQs(search.slice(1)))}`;
384
+ }
385
+ const href = `${locationURL.origin}${locationURL.pathname}${search}${locationURL.hash}`;
386
+ // The URL is relative if the origin is the same as the base URL's origin
387
+ if (locationURL.origin === origin) {
388
+ return href.slice(origin.length);
389
+ }
390
+ return href;
391
+ }
@@ -6,6 +6,7 @@ export declare const INTERNAL_HEADER_PREFIX = "x-opennext-";
6
6
  export declare const INTERNAL_HEADER_INITIAL_URL = "x-opennext-initial-url";
7
7
  export declare const INTERNAL_HEADER_LOCALE = "x-opennext-locale";
8
8
  export declare const INTERNAL_HEADER_RESOLVED_ROUTES = "x-opennext-resolved-routes";
9
+ export declare const INTERNAL_HEADER_REWRITE_STATUS_CODE = "x-opennext-rewrite-status-code";
9
10
  export declare const INTERNAL_EVENT_REQUEST_ID = "x-opennext-request-id";
10
11
  export default function routingHandler(event: InternalEvent, { assetResolver }: {
11
12
  assetResolver?: AssetResolver;
@@ -5,13 +5,14 @@ import { detectLocale } from "./routing/i18n";
5
5
  import { fixDataPage, getNextConfigHeaders, handleFallbackFalse, handleRedirects, handleRewrites, } from "./routing/matcher";
6
6
  import { handleMiddleware } from "./routing/middleware";
7
7
  import { dynamicRouteMatcher, staticRouteMatcher, } from "./routing/routeMatcher";
8
- import { constructNextUrl } from "./routing/util";
8
+ import { constructNextUrl, normalizeLocationHeader } 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;
11
11
  export const INTERNAL_HEADER_PREFIX = "x-opennext-";
12
12
  export const INTERNAL_HEADER_INITIAL_URL = `${INTERNAL_HEADER_PREFIX}initial-url`;
13
13
  export const INTERNAL_HEADER_LOCALE = `${INTERNAL_HEADER_PREFIX}locale`;
14
14
  export const INTERNAL_HEADER_RESOLVED_ROUTES = `${INTERNAL_HEADER_PREFIX}resolved-routes`;
15
+ export const INTERNAL_HEADER_REWRITE_STATUS_CODE = `${INTERNAL_HEADER_PREFIX}rewrite-status-code`;
15
16
  export const INTERNAL_EVENT_REQUEST_ID = `${INTERNAL_HEADER_PREFIX}request-id`;
16
17
  // Geolocation headers starting from Nextjs 15
17
18
  // See https://github.com/vercel/vercel/blob/7714b1c/packages/functions/src/headers.ts
@@ -66,8 +67,7 @@ export default async function routingHandler(event, { assetResolver }) {
66
67
  const redirect = handleRedirects(eventOrResult, RoutesManifest.redirects);
67
68
  if (redirect) {
68
69
  // We need to encode the value in the Location header to make sure it is valid according to RFC
69
- // https://stackoverflow.com/a/7654605/16587222
70
- redirect.headers.Location = new URL(redirect.headers.Location).href;
70
+ redirect.headers.Location = normalizeLocationHeader(redirect.headers.Location, event.url, true);
71
71
  debug("redirect", redirect);
72
72
  return redirect;
73
73
  }
@@ -171,6 +171,7 @@ export default async function routingHandler(event, { assetResolver }) {
171
171
  locale: NextConfig.i18n
172
172
  ? detectLocale(eventOrResult, NextConfig.i18n)
173
173
  : undefined,
174
+ rewriteStatusCode: middlewareEventOrResult.rewriteStatusCode,
174
175
  };
175
176
  }
176
177
  catch (e) {
@@ -34,7 +34,7 @@ export declare class OpenNextNodeResponse extends Transform implements ServerRes
34
34
  socket: Socket | null;
35
35
  setTimeout(_msecs: number, _callback?: (() => void) | undefined): this;
36
36
  addTrailers(_headers: OutgoingHttpHeaders | readonly [string, string][]): void;
37
- constructor(fixHeaders: (headers: OutgoingHttpHeaders) => void, onEnd: (headers: OutgoingHttpHeaders) => Promise<void>, streamCreator?: StreamCreator | undefined, initialHeaders?: OutgoingHttpHeaders | undefined);
37
+ constructor(fixHeaders: (headers: OutgoingHttpHeaders) => void, onEnd: (headers: OutgoingHttpHeaders) => Promise<void>, streamCreator?: StreamCreator | undefined, initialHeaders?: OutgoingHttpHeaders | undefined, statusCode?: number);
38
38
  get originalResponse(): this;
39
39
  get finished(): boolean;
40
40
  setHeader(name: string, value: string | string[]): this;
@@ -51,12 +51,20 @@ export class OpenNextNodeResponse extends Transform {
51
51
  addTrailers(_headers) {
52
52
  throw new Error(CANNOT_BE_USED);
53
53
  }
54
- constructor(fixHeaders, onEnd, streamCreator, initialHeaders) {
54
+ constructor(fixHeaders, onEnd, streamCreator, initialHeaders, statusCode) {
55
55
  super();
56
56
  this.fixHeaders = fixHeaders;
57
57
  this.onEnd = onEnd;
58
58
  this.streamCreator = streamCreator;
59
59
  this.initialHeaders = initialHeaders;
60
+ // We only set the status code if it is not a NaN and it is a number
61
+ // Only allow status codes between 100 and 599 https://httpwg.org/specs/rfc9110.html#status.codes
62
+ if (statusCode &&
63
+ Number.isInteger(statusCode) &&
64
+ statusCode >= 100 &&
65
+ statusCode <= 599) {
66
+ this.statusCode = statusCode;
67
+ }
60
68
  }
61
69
  // Necessary for next 12
62
70
  // We might have to implement all the methods here
@@ -20,6 +20,12 @@ const wrapper = async (handler, converter) => {
20
20
  await imageHandler(internalEvent, { streamCreator });
21
21
  });
22
22
  app.all("*paths", async (req, res) => {
23
+ if (req.protocol === "http" && req.hostname === "localhost") {
24
+ // This is used internally by Next.js during redirects in server actions. We need to set it to the origin of the request.
25
+ process.env.__NEXT_PRIVATE_ORIGIN = `${req.protocol}://${req.hostname}`;
26
+ // This is to make `next-auth` and other libraries that rely on this header to work locally out of the box.
27
+ req.headers["x-forwarded-proto"] = req.protocol;
28
+ }
23
29
  const internalEvent = await converter.convertFrom(req);
24
30
  const streamCreator = {
25
31
  writeHeaders: (prelude) => {
@@ -20,6 +20,7 @@ export type InternalResult = {
20
20
  headers: Record<string, string | string[]>;
21
21
  body: ReadableStream;
22
22
  isBase64Encoded: boolean;
23
+ rewriteStatusCode?: number;
23
24
  } & BaseEventOrResult<"core">;
24
25
  export interface StreamCreator {
25
26
  writeHeaders(prelude: {
@@ -92,6 +93,7 @@ export interface RoutingResult {
92
93
  initialURL: string;
93
94
  locale?: string;
94
95
  resolvedRoutes: ResolvedRoute[];
96
+ rewriteStatusCode?: number;
95
97
  }
96
98
  export interface MiddlewareResult extends RoutingResult, BaseEventOrResult<"middleware"> {
97
99
  }
@@ -63,6 +63,11 @@ export type CachedFetchValue = {
63
63
  export type WithLastModified<T> = {
64
64
  lastModified?: number;
65
65
  value?: T;
66
+ /**
67
+ * If set to true, we will not check the tag cache for this entry.
68
+ * `revalidateTag` and `revalidatePath` may not work as expected.
69
+ */
70
+ shouldBypassTagCache?: boolean;
66
71
  };
67
72
  export type CacheEntryType = Extension;
68
73
  export type CacheValue<CacheType extends CacheEntryType> = (CacheType extends "fetch" ? CachedFetchValue : CacheType extends "cache" ? CachedFile : StoredComposableCacheEntry) & {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "access": "public"
4
4
  },
5
5
  "name": "@opennextjs/aws",
6
- "version": "3.7.2",
6
+ "version": "3.7.4",
7
7
  "bin": {
8
8
  "open-next": "./dist/index.js"
9
9
  },