Skip to content

Commit 5f661b5

Browse files
conico974vicb
andauthored
Refactor overrides (#579)
* moved wrapper * moved converters * moved queues * moved incremental cache * moved cache type * moved tag cache * moved originResolver * moved warmer overrides * Created dummy overrides everywhere * refactor resolves plugin * review Co-authored-by: Victor Berchet <[email protected]> * Create fuzzy-jeans-draw.md * fix e2e --------- Co-authored-by: Victor Berchet <[email protected]>
1 parent 6c81faa commit 5f661b5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+388
-253
lines changed

.changeset/fuzzy-jeans-draw.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@opennextjs/aws": minor
3+
---
4+
5+
Refactor overrides

examples/app-router/app/image-optimization/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export default function ImageOptimization() {
44
return (
55
<div>
66
<Image
7-
src="https://open-next.js.org/architecture.png"
7+
src="https://opennext.js.org/architecture.png"
88
alt="Open Next architecture"
99
width={300}
1010
height={300}

examples/app-router/next.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const nextConfig = {
1515
remotePatterns: [
1616
{
1717
protocol: "https",
18-
hostname: "open-next.js.org",
18+
hostname: "opennext.js.org",
1919
},
2020
],
2121
},

packages/open-next/src/adapters/cache.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { IncrementalCache } from "../cache/incremental/types.js";
2-
import { TagCache } from "../cache/tag/types.js";
1+
import type { IncrementalCache } from "../overrides/incrementalCache/types.js";
2+
import { TagCache } from "../overrides/tagCache/types.js";
33
import { isBinaryContentType } from "./binary.js";
44
import { debug, error, warn } from "./logger.js";
55

packages/open-next/src/adapters/middleware.ts

Lines changed: 6 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,21 @@
1-
import { InternalEvent, Origin, OriginResolver } from "types/open-next";
1+
import { InternalEvent, Origin } from "types/open-next";
22

3-
import { debug, error } from "../adapters/logger";
3+
import { debug } from "../adapters/logger";
44
import { createGenericHandler } from "../core/createGenericHandler";
55
import {
66
resolveIncrementalCache,
7+
resolveOriginResolver,
78
resolveQueue,
89
resolveTagCache,
910
} from "../core/resolve";
1011
import routingHandler from "../core/routingHandler";
1112

12-
const resolveOriginResolver = () => {
13-
const openNextParams = globalThis.openNextConfig.middleware;
14-
if (typeof openNextParams?.originResolver === "function") {
15-
return openNextParams.originResolver();
16-
}
17-
18-
return Promise.resolve<OriginResolver>({
19-
name: "env",
20-
resolve: async (_path: string) => {
21-
try {
22-
const origin = JSON.parse(
23-
process.env.OPEN_NEXT_ORIGIN ?? "{}",
24-
) as Record<string, Origin>;
25-
for (const [key, value] of Object.entries(
26-
globalThis.openNextConfig.functions ?? {},
27-
).filter(([key]) => key !== "default")) {
28-
if (
29-
value.patterns.some((pattern) => {
30-
// Convert cloudfront pattern to regex
31-
return new RegExp(
32-
// transform glob pattern to regex
33-
"/" +
34-
pattern
35-
.replace(/\*\*/g, "(.*)")
36-
.replace(/\*/g, "([^/]*)")
37-
.replace(/\//g, "\\/")
38-
.replace(/\?/g, "."),
39-
).test(_path);
40-
})
41-
) {
42-
debug("Using origin", key, value.patterns);
43-
return origin[key];
44-
}
45-
}
46-
if (_path.startsWith("/_next/image") && origin["imageOptimizer"]) {
47-
debug("Using origin", "imageOptimizer", _path);
48-
return origin["imageOptimizer"];
49-
}
50-
if (origin["default"]) {
51-
debug("Using default origin", origin["default"], _path);
52-
return origin["default"];
53-
}
54-
return false as const;
55-
} catch (e) {
56-
error("Error while resolving origin", e);
57-
return false as const;
58-
}
59-
},
60-
});
61-
};
62-
6313
globalThis.internalFetch = fetch;
6414

6515
const defaultHandler = async (internalEvent: InternalEvent) => {
66-
const originResolver = await resolveOriginResolver();
16+
const originResolver = await resolveOriginResolver(
17+
globalThis.openNextConfig.middleware?.originResolver,
18+
);
6719

6820
//#override includeCacheInMiddleware
6921
globalThis.tagCache = await resolveTagCache(

packages/open-next/src/adapters/warmer-function.ts

Lines changed: 4 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import { Warmer } from "types/open-next.js";
2-
31
import { createGenericHandler } from "../core/createGenericHandler.js";
4-
import { debug, error } from "./logger.js";
2+
import { resolveWarmerInvoke } from "../core/resolve.js";
53
import { generateUniqueId } from "./util.js";
64

75
export interface WarmerEvent {
@@ -17,88 +15,6 @@ export interface WarmerResponse {
1715
serverId: string;
1816
}
1917

20-
const resolveWarmerInvoke = async () => {
21-
const openNextParams = globalThis.openNextConfig.warmer!;
22-
if (typeof openNextParams?.invokeFunction === "function") {
23-
return await openNextParams.invokeFunction();
24-
} else {
25-
return Promise.resolve<Warmer>({
26-
name: "aws-invoke",
27-
invoke: async (warmerId: string) => {
28-
const { InvokeCommand, LambdaClient } = await import(
29-
"@aws-sdk/client-lambda"
30-
);
31-
const lambda = new LambdaClient({});
32-
const warmParams = JSON.parse(process.env.WARM_PARAMS!) as {
33-
concurrency: number;
34-
function: string;
35-
}[];
36-
37-
for (const warmParam of warmParams) {
38-
const { concurrency: CONCURRENCY, function: FUNCTION_NAME } =
39-
warmParam;
40-
debug({
41-
event: "warmer invoked",
42-
functionName: FUNCTION_NAME,
43-
concurrency: CONCURRENCY,
44-
warmerId,
45-
});
46-
const ret = await Promise.all(
47-
Array.from({ length: CONCURRENCY }, (_v, i) => i).map((i) => {
48-
try {
49-
return lambda.send(
50-
new InvokeCommand({
51-
FunctionName: FUNCTION_NAME,
52-
InvocationType: "RequestResponse",
53-
Payload: Buffer.from(
54-
JSON.stringify({
55-
type: "warmer",
56-
warmerId,
57-
index: i,
58-
concurrency: CONCURRENCY,
59-
delay: 75,
60-
} satisfies WarmerEvent),
61-
),
62-
}),
63-
);
64-
} catch (e) {
65-
error(`failed to warm up #${i}`, e);
66-
// ignore error
67-
}
68-
}),
69-
);
70-
71-
// Print status
72-
73-
const warmedServerIds = ret
74-
.map((r, i) => {
75-
if (r?.StatusCode !== 200 || !r?.Payload) {
76-
error(`failed to warm up #${i}:`, r?.Payload?.toString());
77-
return;
78-
}
79-
const payload = JSON.parse(
80-
Buffer.from(r.Payload).toString(),
81-
) as WarmerResponse;
82-
return {
83-
statusCode: r.StatusCode,
84-
payload,
85-
type: "warmer" as const,
86-
};
87-
})
88-
.filter((r): r is Exclude<typeof r, undefined> => !!r);
89-
90-
debug({
91-
event: "warmer result",
92-
sent: CONCURRENCY,
93-
success: warmedServerIds.length,
94-
uniqueServersWarmed: [...new Set(warmedServerIds)].length,
95-
});
96-
}
97-
},
98-
});
99-
}
100-
};
101-
10218
export const handler = await createGenericHandler({
10319
handler: defaultHandler,
10420
type: "warmer",
@@ -107,7 +23,9 @@ export const handler = await createGenericHandler({
10723
async function defaultHandler() {
10824
const warmerId = `warmer-${generateUniqueId()}`;
10925

110-
const invokeFn = await resolveWarmerInvoke();
26+
const invokeFn = await resolveWarmerInvoke(
27+
globalThis.openNextConfig.warmer?.invokeFunction,
28+
);
11129

11230
await invokeFn.invoke(warmerId);
11331

packages/open-next/src/core/createMainHandler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { DetachedPromiseRunner } from "utils/promise";
55

66
import { debug } from "../adapters/logger";
77
import { generateUniqueId } from "../adapters/util";
8-
import type { IncrementalCache } from "../cache/incremental/types";
9-
import type { Queue } from "../queue/types";
8+
import type { IncrementalCache } from "../overrides/incrementalCache/types";
9+
import type { Queue } from "../overrides/queue/types";
1010
import { openNextHandler } from "./requestHandler.js";
1111
import {
1212
resolveConverter,

packages/open-next/src/core/resolve.ts

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import {
66
InternalEvent,
77
InternalResult,
88
LazyLoadedOverride,
9+
OriginResolver,
910
OverrideOptions,
11+
Warmer,
1012
Wrapper,
1113
} from "types/open-next.js";
1214

13-
import { TagCache } from "../cache/tag/types.js";
15+
import { TagCache } from "../overrides/tagCache/types.js";
1416

1517
export async function resolveConverter<
1618
E extends BaseEventOrResult = InternalEvent,
@@ -21,7 +23,7 @@ export async function resolveConverter<
2123
if (typeof converter === "function") {
2224
return converter();
2325
} else {
24-
const m_1 = await import(`../converters/aws-apigw-v2.js`);
26+
const m_1 = await import(`../overrides/converters/aws-apigw-v2.js`);
2527
// @ts-expect-error
2628
return m_1.default;
2729
}
@@ -35,7 +37,7 @@ export async function resolveWrapper<
3537
return wrapper();
3638
} else {
3739
// This will be replaced by the bundler
38-
const m_1 = await import("../wrappers/aws-lambda.js");
40+
const m_1 = await import("../overrides/wrappers/aws-lambda.js");
3941
// @ts-expect-error
4042
return m_1.default;
4143
}
@@ -54,7 +56,7 @@ export async function resolveTagCache(
5456
return tagCache();
5557
} else {
5658
// This will be replaced by the bundler
57-
const m_1 = await import("../cache/tag/dynamodb.js");
59+
const m_1 = await import("../overrides/tagCache/dynamodb.js");
5860
return m_1.default;
5961
}
6062
}
@@ -69,7 +71,7 @@ export async function resolveQueue(queue: OverrideOptions["queue"]) {
6971
if (typeof queue === "function") {
7072
return queue();
7173
} else {
72-
const m_1 = await import("../queue/sqs.js");
74+
const m_1 = await import("../overrides/queue/sqs.js");
7375
return m_1.default;
7476
}
7577
}
@@ -86,7 +88,7 @@ export async function resolveIncrementalCache(
8688
if (typeof incrementalCache === "function") {
8789
return incrementalCache();
8890
} else {
89-
const m_1 = await import("../cache/incremental/s3.js");
91+
const m_1 = await import("../overrides/incrementalCache/s3.js");
9092
return m_1.default;
9193
}
9294
}
@@ -106,3 +108,32 @@ export async function resolveImageLoader(
106108
return m_1.default;
107109
}
108110
}
111+
112+
/**
113+
* @returns
114+
* @__PURE__
115+
*/
116+
export async function resolveOriginResolver(
117+
originResolver?: LazyLoadedOverride<OriginResolver> | string,
118+
) {
119+
if (typeof originResolver === "function") {
120+
return originResolver();
121+
} else {
122+
const m_1 = await import("../overrides/originResolver/pattern-env.js");
123+
return m_1.default;
124+
}
125+
}
126+
127+
/**
128+
* @__PURE__
129+
*/
130+
export async function resolveWarmerInvoke(
131+
warmer?: LazyLoadedOverride<Warmer> | "aws-lambda",
132+
) {
133+
if (typeof warmer === "function") {
134+
return warmer();
135+
} else {
136+
const m_1 = await import("../overrides/warmer/aws-lambda.js");
137+
return m_1.default;
138+
}
139+
}

packages/open-next/src/core/routing/cacheInterceptor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { InternalEvent, InternalResult } from "types/open-next";
55
import { emptyReadableStream, toReadableStream } from "utils/stream";
66

77
import { debug } from "../../adapters/logger";
8-
import { CacheValue } from "../../cache/incremental/types";
8+
import { CacheValue } from "../../overrides/incrementalCache/types";
99
import { localizePath } from "./i18n";
1010
import { generateMessageGroupId } from "./util";
1111

packages/open-next/src/converters/aws-apigw-v1.ts renamed to packages/open-next/src/overrides/converters/aws-apigw-v1.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";
1+
import type { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";
22
import type { Converter, InternalEvent, InternalResult } from "types/open-next";
33
import { fromReadableStream } from "utils/stream";
44

5-
import { debug } from "../adapters/logger";
5+
import { debug } from "../../adapters/logger";
66
import { removeUndefinedFromQuery } from "./utils";
77

88
function normalizeAPIGatewayProxyEventHeaders(

packages/open-next/src/converters/aws-apigw-v2.ts renamed to packages/open-next/src/overrides/converters/aws-apigw-v2.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from "aws-lambda";
1+
import type {
2+
APIGatewayProxyEventV2,
3+
APIGatewayProxyResultV2,
4+
} from "aws-lambda";
25
import { parseCookies } from "http/util";
36
import type { Converter, InternalEvent, InternalResult } from "types/open-next";
47
import { fromReadableStream } from "utils/stream";
58

6-
import { debug } from "../adapters/logger";
7-
import { convertToQuery } from "../core/routing/util";
9+
import { debug } from "../../adapters/logger";
10+
import { convertToQuery } from "../../core/routing/util";
811
import { removeUndefinedFromQuery } from "./utils";
912

1013
// Not sure which one is reallly needed as this is not documented anywhere but server actions redirect are not working without this, it causes a 500 error from cloudfront itself with a 'x-amzErrortype: InternalFailure' header

packages/open-next/src/converters/aws-cloudfront.ts renamed to packages/open-next/src/overrides/converters/aws-cloudfront.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
1-
import {
1+
import type { OutgoingHttpHeader } from "node:http";
2+
3+
import type {
24
CloudFrontCustomOrigin,
35
CloudFrontHeaders,
46
CloudFrontRequest,
57
CloudFrontRequestEvent,
68
CloudFrontRequestResult,
79
} from "aws-lambda";
8-
import { OutgoingHttpHeader } from "http";
910
import { parseCookies } from "http/util";
1011
import type { Converter, InternalEvent, InternalResult } from "types/open-next";
1112
import { fromReadableStream } from "utils/stream";
1213

13-
import { debug } from "../adapters/logger";
14+
import { debug } from "../../adapters/logger";
1415
import {
1516
convertRes,
1617
convertToQuery,
1718
convertToQueryString,
1819
createServerResponse,
1920
proxyRequest,
20-
} from "../core/routing/util";
21-
import { MiddlewareOutputEvent } from "../core/routingHandler";
21+
} from "../../core/routing/util";
22+
import type { MiddlewareOutputEvent } from "../../core/routingHandler";
2223

2324
const CloudFrontBlacklistedHeaders = [
2425
// Disallowed headers, see: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-function-restrictions-all.html#function-restrictions-disallowed-headers

packages/open-next/src/converters/dummy.ts renamed to packages/open-next/src/overrides/converters/dummy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Converter } from "types/open-next";
1+
import type { Converter } from "types/open-next";
22

33
type DummyEventOrResult = {
44
type: "dummy";

0 commit comments

Comments
 (0)