-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Expand file tree
/
Copy pathreact-router.ts
More file actions
256 lines (246 loc) · 6.53 KB
/
Copy pathreact-router.ts
File metadata and controls
256 lines (246 loc) · 6.53 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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
import path from "path";
import { ComponentResourceOptions, Output } from "@pulumi/pulumi";
import { VisibleError } from "../error.js";
import { Plan, SsrSite, SsrSiteArgs } from "./ssr-site.js";
import { existsAsync } from "../../util/fs.js";
import {
validateFrameworkConfig,
validateNoWranglerFile,
} from "./helpers/validation.js";
export interface ReactRouterArgs extends SsrSiteArgs {
/**
* Configure how this component works in `sst dev`.
*
* :::note
* In `sst dev` your React Router app is run in dev mode; it's not deployed.
* :::
*
* Instead of deploying your React Router app, this starts it in dev mode. It's run
* as a separate process in the `sst dev` multiplexer. Read more about
* [`sst dev`](/docs/reference/cli/#dev).
*
* To disable dev mode, pass in `false`.
*/
dev?: SsrSiteArgs["dev"];
/**
* Path to the directory where your React Router app is located. This path is relative to your `sst.config.ts`.
*
* By default it assumes your React Router app is in the root of your SST app.
* @default `"."`
*
* @example
*
* If your React Router app is in a package in your monorepo.
*
* ```js
* {
* path: "packages/web"
* }
* ```
*/
path?: SsrSiteArgs["path"];
/**
* [Link resources](/docs/linking/) to your React Router app. This will:
*
* 1. Grant the permissions needed to access the resources.
* 2. Allow you to access it in your app using the [SDK](/docs/reference/sdk/).
*
* @example
*
* Takes a list of resources to link to the app.
*
* ```js
* {
* link: [bucket, stripeKey]
* }
* ```
*
* You can access the linked resources in your React Router app.
*
* ```ts
* import { Resource } from "sst";
*
* console.log(Resource.MyBucket.name);
* ```
*/
link?: SsrSiteArgs["link"];
/**
* Set environment variables in your React Router app. These are made available:
*
* 1. In `vite build`, they are loaded into the build.
* 2. At runtime as Worker bindings.
* 3. Locally while running `vite dev` through `sst dev`.
*
* :::tip
* You can also `link` resources to your React Router app and access them in a type-safe way with the [SDK](/docs/reference/sdk/). We recommend linking since it's more secure.
* :::
*
* @example
* ```js
* {
* environment: {
* API_URL: api.url,
* PUBLIC_STRIPE_PUBLISHABLE_KEY: "pk_test_123"
* }
* }
* ```
*
* You can access the environment variables in your React Router app as follows:
*
* ```ts
* export function loader({ context }: Route.LoaderArgs) {
* return { apiUrl: context.cloudflare.env.API_URL };
* }
* ```
*/
environment?: SsrSiteArgs["environment"];
/**
* Set a custom domain for your React Router app.
*
* @example
*
* ```js
* {
* domain: "my-app.com"
* }
* ```
*/
domain?: SsrSiteArgs["domain"];
/**
* The command used internally to build your React Router app.
*
* @default `"npm run build"`
*
* @example
*
* If you want to use a different build command.
* ```js
* {
* buildCommand: "yarn build"
* }
* ```
*/
buildCommand?: SsrSiteArgs["buildCommand"];
}
/**
* The `ReactRouter` component lets you deploy a [React Router v7](https://reactrouter.com) app to Cloudflare.
*
* :::note
* Create a Cloudflare-compatible app with `npm create cloudflare@latest -- my-react-router-app --framework=react-router`.
* :::
*
* @example
*
* #### Minimal example
*
* Deploy the React Router app that's in the project root.
*
* ```js title="sst.config.ts"
* new sst.cloudflare.ReactRouter("MyWeb");
* ```
*
* #### Change the path
*
* Deploys the React Router app in the `my-app/` directory.
*
* ```js {2} title="sst.config.ts"
* new sst.cloudflare.ReactRouter("MyWeb", {
* path: "my-app/"
* });
* ```
*
* #### Add a custom domain
*
* Set a custom domain for your React Router app.
*
* ```js {2} title="sst.config.ts"
* new sst.cloudflare.ReactRouter("MyWeb", {
* domain: "my-app.com"
* });
* ```
*
* #### Link resources
*
* [Link resources](/docs/linking/) to your React Router app. This will grant permissions
* to the resources and allow you to access it in your app.
*
* ```ts {4} title="sst.config.ts"
* const bucket = new sst.cloudflare.Bucket("MyBucket");
*
* new sst.cloudflare.ReactRouter("MyWeb", {
* link: [bucket]
* });
* ```
*
* Use `sst/resource` for linked resources.
*
* ```ts title="app/routes/home.tsx"
* import { Resource } from "sst/resource";
*
* export async function loader() {
* const files = await Resource.MyBucket.list();
* return { files };
* }
* ```
*/
export class ReactRouter extends SsrSite {
constructor(
name: string,
args: ReactRouterArgs = {},
opts: ComponentResourceOptions = {},
) {
super(__pulumiType, name, args, opts);
}
protected validate(sitePath: string): void {
validateFrameworkConfig({
sitePath,
configName: "vite.config",
componentName: "ReactRouter",
packageName: "@cloudflare/vite-plugin",
minVersion: "1.33.0",
});
validateNoWranglerFile(sitePath, "ReactRouter");
}
protected buildPlan(outputPath: Output<string>): Output<Plan> {
return outputPath.apply(async (outputPath) => {
const serverPath = path.join(outputPath, "build", "server", "index.js");
const assetsPath = path.join(outputPath, "build", "client");
if (!(await existsAsync(serverPath))) {
throw new VisibleError(
[
`React Router server bundle not found at:\n "${serverPath}".`,
"",
"Make sure the Cloudflare Vite plugin is configured in your `vite.config.ts`.",
"If your React Router project is entirely pre-rendered, use `sst.cloudflare.StaticSite` instead.",
].join("\n"),
);
}
if (!(await existsAsync(assetsPath))) {
throw new VisibleError(
`React Router assets directory not found at:\n "${assetsPath}".`,
);
}
return {
server: "./build/server/index.js",
assets: "./build/client",
};
});
}
protected buildWrangler(sitePath: string) {
return {
main: path.resolve(sitePath, "workers/app.ts"),
};
}
/**
* The URL of the React Router app.
*
* If the `domain` is set, this is the URL with the custom domain.
* Otherwise, it's the auto-generated Worker URL.
*/
public get url() {
return super.url;
}
}
const __pulumiType = "sst:cloudflare:ReactRouter";
// @ts-expect-error
ReactRouter.__pulumiType = __pulumiType;