-
Notifications
You must be signed in to change notification settings - Fork 203
Expand file tree
/
Copy pathwithCloudflare.ts
More file actions
118 lines (112 loc) · 2.88 KB
/
withCloudflare.ts
File metadata and controls
118 lines (112 loc) · 2.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import type {
FunctionOptions,
OpenNextConfig,
RouteTemplate,
SplittedFunctionOptions,
} from "types/open-next";
type CloudflareCompatibleFunction<Placement extends "regional" | "global"> =
Placement extends "regional"
? FunctionOptions & {
placement: "regional";
}
: { placement: "global" };
type CloudflareCompatibleRoutes<Placement extends "regional" | "global"> =
Placement extends "regional"
? {
placement: "regional";
routes: RouteTemplate[];
patterns: string[];
}
: {
placement: "global";
routes: `app/${string}/route`;
patterns: string;
};
type CloudflareCompatibleSplittedFunction<
Placement extends "regional" | "global" = "regional",
> = CloudflareCompatibleRoutes<Placement> &
CloudflareCompatibleFunction<Placement>;
type CloudflareConfig<
Fn extends Record<
string,
CloudflareCompatibleSplittedFunction<"global" | "regional">
>,
> = {
default: CloudflareCompatibleFunction<"regional">;
functions?: Fn;
} & Omit<OpenNextConfig, "default" | "functions" | "middleware">;
type InterpolatedSplittedFunctionOptions<
Fn extends Record<
string,
CloudflareCompatibleSplittedFunction<"global" | "regional">
>,
> = {
[K in keyof Fn]: SplittedFunctionOptions;
};
/**
* This function makes it easier to use Cloudflare with OpenNext.
* All options are already restricted to Cloudflare compatible options.
* @example
* ```ts
export default withCloudflare({
default: {
placement: "regional",
runtime: "node",
},
functions: {
api: {
placement: "regional",
runtime: "node",
routes: ["app/api/test/route", "page/api/otherApi"],
patterns: ["/api/*"],
},
global: {
placement: "global",
runtime: "edge",
routes: "app/test/page",
patterns: "/page",
},
},
});
* ```
*/
export function withCloudflare<
Fn extends Record<
string,
CloudflareCompatibleSplittedFunction<"global" | "regional">
>,
Key extends keyof Fn,
>(config: CloudflareConfig<Fn>) {
const functions = Object.entries(config.functions ?? {}).reduce(
(acc, [name, fn]) => {
const _name = name as Key;
acc[_name] =
fn.placement === "global"
? {
placement: "global",
runtime: "edge",
routes: [fn.routes],
patterns: [fn.patterns],
override: {
wrapper: "cloudflare-edge",
converter: "edge",
},
}
: { ...fn, placement: "regional" };
return acc;
},
{} as InterpolatedSplittedFunctionOptions<Fn>,
);
return {
default: config.default,
functions: functions,
middleware: {
external: true,
originResolver: "pattern-env",
override: {
wrapper: "cloudflare-edge",
converter: "edge",
},
},
} satisfies OpenNextConfig;
}