create-sprinkles 0.2.4 → 0.3.0
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.
- package/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/bin.mjs +24 -8
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +14 -6
- package/package.json +1 -1
- package/templates/react-router-rsc-sea/scripts/build-exe.ts.hbs +53 -0
- package/templates/react-router-rsc-sea/server.ts.hbs +52 -0
- package/templates/react-shared/public/favicon.ico +0 -0
- package/templates/react-shared/react-router.config.ts.hbs +3 -0
- package/templates/shared/vite.config.ts.hbs +37 -0
- /package/templates/{react-router-rsc → react-router-rsc-cloudflare}/workers/entry.rsc.tsx +0 -0
- /package/templates/{react-router-rsc → react-router-rsc-cloudflare}/workers/entry.ssr.tsx +0 -0
- /package/templates/{react-router-rsc → react-router-rsc-cloudflare}/wrangler.rsc.jsonc.hbs +0 -0
- /package/templates/{react-router-rsc → react-router-rsc-cloudflare}/wrangler.ssr.jsonc.hbs +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mark Malstrom
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# create-sprinkles
|
|
2
|
+
|
|
3
|
+
Get started with development by creating projects from templates quickly.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
create-sprinkles requires [Vite+](https://viteplus.dev). Install it with Homebrew on macOS:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
brew install markmals/tap/vite-plus
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or use the official installer script:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
# macOS/Linux
|
|
17
|
+
curl -fsSL https://vite.plus | bash
|
|
18
|
+
|
|
19
|
+
# Windows
|
|
20
|
+
irm https://vite.plus/ps1 | iex
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
vp create sprinkles
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The interactive prompts will guide you through:
|
|
30
|
+
|
|
31
|
+
1. **Directory** — where to create the project
|
|
32
|
+
2. **Project kind** — choose a template (see below)
|
|
33
|
+
3. **Optional features** — add-ons specific to the chosen template
|
|
34
|
+
4. **GitHub owner** — your GitHub user or organization
|
|
35
|
+
|
|
36
|
+
## Templates
|
|
37
|
+
|
|
38
|
+
### React Router — SPA
|
|
39
|
+
|
|
40
|
+
Single-page app with React Router, Tailwind CSS, and Vite+.
|
|
41
|
+
|
|
42
|
+
- Optional: [Convex](https://convex.dev) backend
|
|
43
|
+
|
|
44
|
+
### React Router — SSR
|
|
45
|
+
|
|
46
|
+
Server-rendered app with React Router, Tailwind CSS, Vite+, and Cloudflare deployment.
|
|
47
|
+
|
|
48
|
+
- Optional: [Convex](https://convex.dev) backend
|
|
49
|
+
|
|
50
|
+
### React Router — RSC
|
|
51
|
+
|
|
52
|
+
React Server Components with React Router, Tailwind CSS, Vite+, and Cloudflare deployment.
|
|
53
|
+
|
|
54
|
+
- Optional: Content-layer plugin for MDX-based content
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
|
|
58
|
+
MIT
|
package/dist/bin.mjs
CHANGED
|
@@ -16,6 +16,7 @@ function buildContext(opts) {
|
|
|
16
16
|
...opts,
|
|
17
17
|
hasContentLayer: isRSC && Boolean(opts.contentLayer),
|
|
18
18
|
hasConvex: (isSPA || isSSR) && Boolean(opts.convex),
|
|
19
|
+
hasSEA: isRSC && Boolean(opts.sea),
|
|
19
20
|
isPackage: opts.kind === "ts-package",
|
|
20
21
|
isRSC,
|
|
21
22
|
isReactRouter: opts.kind !== "ts-package",
|
|
@@ -65,12 +66,16 @@ function buildDependencyCommands(context) {
|
|
|
65
66
|
commands.push("vp add react react-dom react-router");
|
|
66
67
|
commands.push("vp add -D @types/react @types/react-dom @react-router/dev @tailwindcss/vite tailwindcss vite-plugin-devtools-json");
|
|
67
68
|
commands.push("vp add -D @rolldown/plugin-babel @vitejs/plugin-react babel-plugin-react-compiler");
|
|
68
|
-
commands.push("vp add -D @cloudflare/vite-plugin wrangler");
|
|
69
|
+
if (!context.hasSEA) commands.push("vp add -D @cloudflare/vite-plugin wrangler");
|
|
69
70
|
commands.push("vp add -D eslint-plugin-perfectionist eslint-plugin-react-hooks");
|
|
70
71
|
}
|
|
71
72
|
if (context.isReactRouter) commands.push("vp add @react-router/node isbot");
|
|
72
73
|
if (context.hasConvex) commands.push("vp add convex @convex-dev/react-query @tanstack/react-query");
|
|
73
74
|
if (context.isRSC) commands.push("vp add -D @vitejs/plugin-rsc");
|
|
75
|
+
if (context.hasSEA) {
|
|
76
|
+
commands.push("vp add @remix-run/node-fetch-server mime");
|
|
77
|
+
commands.push("vp add -D tsdown");
|
|
78
|
+
}
|
|
74
79
|
if (context.hasContentLayer) {
|
|
75
80
|
commands.push("vp add jsr:@std/jsonc jsr:@std/yaml gray-matter github-slugger @remix-run/data-schema");
|
|
76
81
|
commands.push("vp add -D @mdx-js/rollup");
|
|
@@ -89,7 +94,7 @@ function buildScripts(context) {
|
|
|
89
94
|
commands: phase0Commands,
|
|
90
95
|
phase: 0
|
|
91
96
|
});
|
|
92
|
-
if (context.isRSC) scripts.push({
|
|
97
|
+
if (context.isRSC && !context.hasSEA) scripts.push({
|
|
93
98
|
commands: ["vpx wrangler types -c wrangler.rsc.jsonc"],
|
|
94
99
|
phase: 1
|
|
95
100
|
});
|
|
@@ -122,7 +127,8 @@ function buildScripts(context) {
|
|
|
122
127
|
function buildSuggestions(context) {
|
|
123
128
|
const suggestions = [];
|
|
124
129
|
if (context.hasConvex) suggestions.push("Open the Convex dashboard: https://dashboard.convex.dev");
|
|
125
|
-
if (context.isSSR || context.isRSC) suggestions.push("Log in to Cloudflare: vpx wrangler login");
|
|
130
|
+
if ((context.isSSR || context.isRSC) && !context.hasSEA) suggestions.push("Log in to Cloudflare: vpx wrangler login");
|
|
131
|
+
if (context.hasSEA) suggestions.push("Build the executable: vp run build");
|
|
126
132
|
if (context.isReactRouter) suggestions.push("Start the dev server: vp dev");
|
|
127
133
|
else suggestions.push("Start development: vp run dev");
|
|
128
134
|
return suggestions;
|
|
@@ -150,6 +156,8 @@ async function collectAddonLayers(context) {
|
|
|
150
156
|
if (context.isPackage && context.sea) addons.push(await tryHandlebars("ts-package-sea", context));
|
|
151
157
|
if (context.hasConvex) addons.push(await tryHandlebars("react-router-convex", context));
|
|
152
158
|
if (context.isSSR && context.hasConvex) addons.push(await tryHandlebars("react-router-ssr-convex", context));
|
|
159
|
+
if (context.isRSC && !context.hasSEA) addons.push(await tryHandlebars("react-router-rsc-cloudflare", context));
|
|
160
|
+
if (context.hasSEA) addons.push(await tryHandlebars("react-router-rsc-sea", context));
|
|
153
161
|
if (context.hasContentLayer) addons.push(await tryHandlebars("react-router-rsc-content-layer", context));
|
|
154
162
|
return addons;
|
|
155
163
|
}
|
|
@@ -225,12 +233,20 @@ if (kind === "react-router-spa" || kind === "react-router-ssr") {
|
|
|
225
233
|
convex = answer;
|
|
226
234
|
}
|
|
227
235
|
if (kind === "react-router-rsc") {
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
236
|
+
const features = await prompts.multiselect({
|
|
237
|
+
message: "Include optional features?",
|
|
238
|
+
options: [{
|
|
239
|
+
label: "Content-layer plugin",
|
|
240
|
+
value: "contentLayer"
|
|
241
|
+
}, {
|
|
242
|
+
label: "Single Executable Application (SEA)",
|
|
243
|
+
value: "sea"
|
|
244
|
+
}],
|
|
245
|
+
required: false
|
|
231
246
|
});
|
|
232
|
-
if (prompts.isCancel(
|
|
233
|
-
contentLayer =
|
|
247
|
+
if (prompts.isCancel(features)) process.exit(0);
|
|
248
|
+
contentLayer = features.includes("contentLayer");
|
|
249
|
+
sea = features.includes("sea");
|
|
234
250
|
}
|
|
235
251
|
if (kind === "ts-package") {
|
|
236
252
|
const features = await prompts.multiselect({
|
package/dist/index.d.mts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -11,6 +11,7 @@ function buildContext(opts) {
|
|
|
11
11
|
...opts,
|
|
12
12
|
hasContentLayer: isRSC && Boolean(opts.contentLayer),
|
|
13
13
|
hasConvex: (isSPA || isSSR) && Boolean(opts.convex),
|
|
14
|
+
hasSEA: isRSC && Boolean(opts.sea),
|
|
14
15
|
isPackage: opts.kind === "ts-package",
|
|
15
16
|
isRSC,
|
|
16
17
|
isReactRouter: opts.kind !== "ts-package",
|
|
@@ -20,9 +21,6 @@ function buildContext(opts) {
|
|
|
20
21
|
};
|
|
21
22
|
}
|
|
22
23
|
//#endregion
|
|
23
|
-
//#region src/metadata.ts
|
|
24
|
-
const NAME = "create-sprinkles";
|
|
25
|
-
//#endregion
|
|
26
24
|
//#region src/merge.ts
|
|
27
25
|
function isDirectory(value) {
|
|
28
26
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -37,6 +35,9 @@ function mergeFiles(...layers) {
|
|
|
37
35
|
return result;
|
|
38
36
|
}
|
|
39
37
|
//#endregion
|
|
38
|
+
//#region src/metadata.ts
|
|
39
|
+
const NAME = "create-sprinkles";
|
|
40
|
+
//#endregion
|
|
40
41
|
//#region src/options.ts
|
|
41
42
|
const kind = z.enum([
|
|
42
43
|
"react-router-spa",
|
|
@@ -63,12 +64,16 @@ function buildDependencyCommands(context) {
|
|
|
63
64
|
commands.push("vp add react react-dom react-router");
|
|
64
65
|
commands.push("vp add -D @types/react @types/react-dom @react-router/dev @tailwindcss/vite tailwindcss vite-plugin-devtools-json");
|
|
65
66
|
commands.push("vp add -D @rolldown/plugin-babel @vitejs/plugin-react babel-plugin-react-compiler");
|
|
66
|
-
commands.push("vp add -D @cloudflare/vite-plugin wrangler");
|
|
67
|
+
if (!context.hasSEA) commands.push("vp add -D @cloudflare/vite-plugin wrangler");
|
|
67
68
|
commands.push("vp add -D eslint-plugin-perfectionist eslint-plugin-react-hooks");
|
|
68
69
|
}
|
|
69
70
|
if (context.isReactRouter) commands.push("vp add @react-router/node isbot");
|
|
70
71
|
if (context.hasConvex) commands.push("vp add convex @convex-dev/react-query @tanstack/react-query");
|
|
71
72
|
if (context.isRSC) commands.push("vp add -D @vitejs/plugin-rsc");
|
|
73
|
+
if (context.hasSEA) {
|
|
74
|
+
commands.push("vp add @remix-run/node-fetch-server mime");
|
|
75
|
+
commands.push("vp add -D tsdown");
|
|
76
|
+
}
|
|
72
77
|
if (context.hasContentLayer) {
|
|
73
78
|
commands.push("vp add jsr:@std/jsonc jsr:@std/yaml gray-matter github-slugger @remix-run/data-schema");
|
|
74
79
|
commands.push("vp add -D @mdx-js/rollup");
|
|
@@ -87,7 +92,7 @@ function buildScripts(context) {
|
|
|
87
92
|
commands: phase0Commands,
|
|
88
93
|
phase: 0
|
|
89
94
|
});
|
|
90
|
-
if (context.isRSC) scripts.push({
|
|
95
|
+
if (context.isRSC && !context.hasSEA) scripts.push({
|
|
91
96
|
commands: ["vpx wrangler types -c wrangler.rsc.jsonc"],
|
|
92
97
|
phase: 1
|
|
93
98
|
});
|
|
@@ -120,7 +125,8 @@ function buildScripts(context) {
|
|
|
120
125
|
function buildSuggestions(context) {
|
|
121
126
|
const suggestions = [];
|
|
122
127
|
if (context.hasConvex) suggestions.push("Open the Convex dashboard: https://dashboard.convex.dev");
|
|
123
|
-
if (context.isSSR || context.isRSC) suggestions.push("Log in to Cloudflare: vpx wrangler login");
|
|
128
|
+
if ((context.isSSR || context.isRSC) && !context.hasSEA) suggestions.push("Log in to Cloudflare: vpx wrangler login");
|
|
129
|
+
if (context.hasSEA) suggestions.push("Build the executable: vp run build");
|
|
124
130
|
if (context.isReactRouter) suggestions.push("Start the dev server: vp dev");
|
|
125
131
|
else suggestions.push("Start development: vp run dev");
|
|
126
132
|
return suggestions;
|
|
@@ -148,6 +154,8 @@ async function collectAddonLayers(context) {
|
|
|
148
154
|
if (context.isPackage && context.sea) addons.push(await tryHandlebars("ts-package-sea", context));
|
|
149
155
|
if (context.hasConvex) addons.push(await tryHandlebars("react-router-convex", context));
|
|
150
156
|
if (context.isSSR && context.hasConvex) addons.push(await tryHandlebars("react-router-ssr-convex", context));
|
|
157
|
+
if (context.isRSC && !context.hasSEA) addons.push(await tryHandlebars("react-router-rsc-cloudflare", context));
|
|
158
|
+
if (context.hasSEA) addons.push(await tryHandlebars("react-router-rsc-sea", context));
|
|
151
159
|
if (context.hasContentLayer) addons.push(await tryHandlebars("react-router-rsc-content-layer", context));
|
|
152
160
|
return addons;
|
|
153
161
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { readdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join, relative } from "node:path";
|
|
3
|
+
import { build } from "tsdown";
|
|
4
|
+
|
|
5
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
6
|
+
|
|
7
|
+
const CLIENT_DIR = "dist/client";
|
|
8
|
+
|
|
9
|
+
// ── Collect every file under dist/client/ ──────────────────────
|
|
10
|
+
function collectFiles(dir: string, base = dir) {
|
|
11
|
+
const files = [] as string[];
|
|
12
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
13
|
+
const full = join(dir, entry.name);
|
|
14
|
+
if (entry.isDirectory()) {
|
|
15
|
+
files.push(...collectFiles(full, base));
|
|
16
|
+
} else {
|
|
17
|
+
// Key = path relative to CLIENT_DIR, e.g. "assets/index-abc123.js"
|
|
18
|
+
files.push(relative(base, full));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return files;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let clientFiles = collectFiles(CLIENT_DIR);
|
|
25
|
+
|
|
26
|
+
// ── Write manifest so server.ts knows which keys exist ──────────
|
|
27
|
+
writeFileSync("dist/asset-manifest.json", JSON.stringify(clientFiles, null, 2));
|
|
28
|
+
|
|
29
|
+
// ── Build the SEA asset map: key → file path on disk ────────────
|
|
30
|
+
// node:sea's getAsset(key) uses these keys at runtime
|
|
31
|
+
let assets = Object.fromEntries(clientFiles.map(file => [file, join(CLIENT_DIR, file)]));
|
|
32
|
+
|
|
33
|
+
console.log(`Embedding ${clientFiles.length} client assets into executable`);
|
|
34
|
+
|
|
35
|
+
// ── Run tsdown with exe enabled ─────────────────────────────────
|
|
36
|
+
await build({
|
|
37
|
+
entry: ["server.ts"],
|
|
38
|
+
outDir: "build",
|
|
39
|
+
format: "esm",
|
|
40
|
+
target: "node25",
|
|
41
|
+
// Bundle everything — the React Router server build, @remix-run/node-fetch-server, etc.
|
|
42
|
+
noExternal: [/.*/],
|
|
43
|
+
exe: {
|
|
44
|
+
fileName: packageJson.name,
|
|
45
|
+
seaConfig: {
|
|
46
|
+
disableExperimentalSEAWarning: true,
|
|
47
|
+
useCodeCache: false,
|
|
48
|
+
assets, // ← every client file, keyed by its URL path
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
console.log(`Done — executable written to build/${packageJson.name}`);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createRequestListener } from "@remix-run/node-fetch-server";
|
|
2
|
+
import mime from "mime";
|
|
3
|
+
import * as http from "node:http";
|
|
4
|
+
import sea from "node:sea";
|
|
5
|
+
|
|
6
|
+
// @ts-expect-error: tsdown bundles this — it's the output of `vp build`
|
|
7
|
+
import app from "./dist/server/index.js";
|
|
8
|
+
|
|
9
|
+
// Generated by scripts/build-exe.ts before tsdown runs
|
|
10
|
+
import assetManifest from "./dist/asset-manifest.json" with { type: "json" };
|
|
11
|
+
|
|
12
|
+
function mimeType(path: string): string {
|
|
13
|
+
let ext = path.substring(path.lastIndexOf("."));
|
|
14
|
+
return mime.getType(ext) ?? "application/octet-stream";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Set of embedded asset paths for O(1) lookup
|
|
18
|
+
let embeddedAssets = new Set<string>(assetManifest);
|
|
19
|
+
|
|
20
|
+
async function handler(request: Request): Promise<Response> {
|
|
21
|
+
let url = new URL(request.url);
|
|
22
|
+
// Strip leading slash to match SEA asset keys
|
|
23
|
+
let assetPath = url.pathname.slice(1);
|
|
24
|
+
|
|
25
|
+
// Serve embedded client assets straight from the binary
|
|
26
|
+
if (sea.isSea() && embeddedAssets.has(assetPath)) {
|
|
27
|
+
let body = sea.getAsset(assetPath); // ArrayBuffer
|
|
28
|
+
|
|
29
|
+
// Vite fingerprints asset filenames, so anything under /assets/
|
|
30
|
+
// is safe to cache forever. Everything else gets a shorter TTL.
|
|
31
|
+
let immutable = assetPath.startsWith("assets/");
|
|
32
|
+
|
|
33
|
+
return new Response(body, {
|
|
34
|
+
headers: {
|
|
35
|
+
"Content-Type": mimeType(assetPath),
|
|
36
|
+
"Cache-Control": immutable
|
|
37
|
+
? "public, max-age=31536000, immutable"
|
|
38
|
+
: "public, max-age=3600",
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Everything else → React Router RSC
|
|
44
|
+
return app.fetch(request);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const port = Number.parseInt(process.env.PORT || "1612");
|
|
48
|
+
const server = http.createServer(createRequestListener(handler));
|
|
49
|
+
|
|
50
|
+
server.listen(port, () => {
|
|
51
|
+
console.log(`Listening on http://localhost:${port}`);
|
|
52
|
+
});
|
|
Binary file
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{{#if isRSC}}
|
|
2
|
+
{{#unless hasSEA}}
|
|
2
3
|
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
4
|
+
{{/unless}}
|
|
3
5
|
{{#if hasContentLayer}}
|
|
4
6
|
import mdx from "@mdx-js/rollup";
|
|
5
7
|
{{/if}}
|
|
@@ -26,7 +28,9 @@ import { defineConfig } from "vite-plus";
|
|
|
26
28
|
{{/if}}
|
|
27
29
|
|
|
28
30
|
{{#if isReactRouter}}
|
|
31
|
+
{{#unless hasSEA}}
|
|
29
32
|
const IS_TEST = Boolean(process.env.VITEST);
|
|
33
|
+
{{/unless}}
|
|
30
34
|
|
|
31
35
|
{{/if}}
|
|
32
36
|
export default defineConfig({
|
|
@@ -107,7 +111,9 @@ export default defineConfig({
|
|
|
107
111
|
node: true,
|
|
108
112
|
},
|
|
109
113
|
{{#if isRSC}}
|
|
114
|
+
{{#unless hasSEA}}
|
|
110
115
|
ignorePatterns: ["**/worker-configuration.d.ts"],
|
|
116
|
+
{{/unless}}
|
|
111
117
|
{{/if}}
|
|
112
118
|
{{#if isReactRouter}}
|
|
113
119
|
jsPlugins: [
|
|
@@ -281,6 +287,19 @@ export default defineConfig({
|
|
|
281
287
|
},
|
|
282
288
|
{{/if}}
|
|
283
289
|
{{#if isRSC}}
|
|
290
|
+
{{#if hasSEA}}
|
|
291
|
+
plugins: [
|
|
292
|
+
{{#if hasContentLayer}}
|
|
293
|
+
contentLayer(),
|
|
294
|
+
mdx(),
|
|
295
|
+
{{/if}}
|
|
296
|
+
reactRouter(),
|
|
297
|
+
rsc(),
|
|
298
|
+
reactCompiler(),
|
|
299
|
+
tailwindcss(),
|
|
300
|
+
devtoolsJson(),
|
|
301
|
+
],
|
|
302
|
+
{{else}}
|
|
284
303
|
plugins: [
|
|
285
304
|
{{#if hasContentLayer}}
|
|
286
305
|
contentLayer(),
|
|
@@ -307,6 +326,7 @@ export default defineConfig({
|
|
|
307
326
|
tailwindcss(),
|
|
308
327
|
devtoolsJson(),
|
|
309
328
|
],
|
|
329
|
+
{{/if}}
|
|
310
330
|
{{else if isSSR}}
|
|
311
331
|
plugins: [
|
|
312
332
|
tailwindcss(),
|
|
@@ -338,6 +358,22 @@ export default defineConfig({
|
|
|
338
358
|
run: {
|
|
339
359
|
tasks: {
|
|
340
360
|
{{#if isRSC}}
|
|
361
|
+
{{#if hasSEA}}
|
|
362
|
+
build: {
|
|
363
|
+
// Compound command — each half is cached independently.
|
|
364
|
+
// vp build runs React Router's production build,
|
|
365
|
+
// then the script bundles everything into a SEA.
|
|
366
|
+
command: "vp build && node scripts/build-exe.ts",
|
|
367
|
+
env: ["NODE_ENV"],
|
|
368
|
+
},
|
|
369
|
+
typecheck: {
|
|
370
|
+
command: "tsgo --noEmit",
|
|
371
|
+
dependsOn: ["typegen:react-router"],
|
|
372
|
+
},
|
|
373
|
+
"typegen:react-router": {
|
|
374
|
+
command: "react-router typegen",
|
|
375
|
+
},
|
|
376
|
+
{{else}}
|
|
341
377
|
deploy: {
|
|
342
378
|
cache: false,
|
|
343
379
|
command: "vp build && wrangler deploy",
|
|
@@ -352,6 +388,7 @@ export default defineConfig({
|
|
|
352
388
|
"typegen:react-router": {
|
|
353
389
|
command: "react-router typegen",
|
|
354
390
|
},
|
|
391
|
+
{{/if}}
|
|
355
392
|
{{else if isReactRouter}}
|
|
356
393
|
deploy: {
|
|
357
394
|
cache: false,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|