react-bun-ssr 0.1.1 → 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/README.md +25 -17
- package/framework/cli/commands.ts +104 -246
- package/framework/cli/dev-client-watch.ts +288 -0
- package/framework/cli/dev-route-table.ts +71 -0
- package/framework/cli/dev-runtime.ts +382 -0
- package/framework/cli/internal.ts +142 -0
- package/framework/cli/main.ts +27 -31
- package/framework/runtime/build-tools.ts +134 -13
- package/framework/runtime/bun-route-adapter.ts +20 -7
- package/framework/runtime/client-runtime.tsx +150 -159
- package/framework/runtime/client-transition-core.ts +159 -0
- package/framework/runtime/config.ts +7 -2
- package/framework/runtime/index.ts +1 -1
- package/framework/runtime/link.tsx +3 -11
- package/framework/runtime/markdown-routes.ts +1 -14
- package/framework/runtime/matcher.ts +11 -11
- package/framework/runtime/module-loader.ts +75 -25
- package/framework/runtime/render.tsx +150 -22
- package/framework/runtime/route-api.ts +1 -1
- package/framework/runtime/router.ts +75 -4
- package/framework/runtime/server.ts +57 -106
- package/framework/runtime/tree.tsx +24 -2
- package/framework/runtime/types.ts +13 -2
- package/framework/runtime/utils.ts +3 -0
- package/package.json +13 -7
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
`react-bun-ssr` is a Bun-native SSR React framework with file-based routing, loaders, actions, middleware, streaming, soft navigation, and first-class markdown routes.
|
|
4
4
|
|
|
5
|
-
- Documentation: https://react-bun-ssr.
|
|
6
|
-
- API reference: https://react-bun-ssr.
|
|
7
|
-
- Blog: https://react-bun-ssr.
|
|
5
|
+
- Documentation: https://react-bun-ssr.dev/docs
|
|
6
|
+
- API reference: https://react-bun-ssr.dev/docs/api/overview
|
|
7
|
+
- Blog: https://react-bun-ssr.dev/blog
|
|
8
8
|
- Repository: https://github.com/react-formation/react-bun-ssr
|
|
9
9
|
|
|
10
10
|
## Why react-bun-ssr?
|
|
@@ -50,7 +50,7 @@ http://127.0.0.1:3000
|
|
|
50
50
|
|
|
51
51
|
For the full setup walkthrough, read the installation guide:
|
|
52
52
|
|
|
53
|
-
- https://react-bun-ssr.
|
|
53
|
+
- https://react-bun-ssr.dev/docs/start/installation
|
|
54
54
|
|
|
55
55
|
## What `rbssr init` gives you
|
|
56
56
|
|
|
@@ -75,7 +75,7 @@ rbssr.config.ts
|
|
|
75
75
|
|
|
76
76
|
The quickest follow-up is:
|
|
77
77
|
|
|
78
|
-
- https://react-bun-ssr.
|
|
78
|
+
- https://react-bun-ssr.dev/docs/start/quick-start
|
|
79
79
|
|
|
80
80
|
## How it works
|
|
81
81
|
|
|
@@ -85,7 +85,7 @@ Routes live under `app/routes`. Page routes, API routes, dynamic params, and mar
|
|
|
85
85
|
|
|
86
86
|
Read more:
|
|
87
87
|
|
|
88
|
-
- https://react-bun-ssr.
|
|
88
|
+
- https://react-bun-ssr.dev/docs/routing/file-based-routing
|
|
89
89
|
|
|
90
90
|
### Request pipeline
|
|
91
91
|
|
|
@@ -93,8 +93,8 @@ For a page request, the framework resolves the matching route, runs global and n
|
|
|
93
93
|
|
|
94
94
|
Read more:
|
|
95
95
|
|
|
96
|
-
- https://react-bun-ssr.
|
|
97
|
-
- https://react-bun-ssr.
|
|
96
|
+
- https://react-bun-ssr.dev/docs/routing/middleware
|
|
97
|
+
- https://react-bun-ssr.dev/docs/data/loaders
|
|
98
98
|
|
|
99
99
|
### Rendering model
|
|
100
100
|
|
|
@@ -102,8 +102,8 @@ SSR is the default model. HTML responses stream, deferred loader data is support
|
|
|
102
102
|
|
|
103
103
|
Read more:
|
|
104
104
|
|
|
105
|
-
- https://react-bun-ssr.
|
|
106
|
-
- https://react-bun-ssr.
|
|
105
|
+
- https://react-bun-ssr.dev/docs/rendering/streaming-deferred
|
|
106
|
+
- https://react-bun-ssr.dev/docs/routing/navigation
|
|
107
107
|
|
|
108
108
|
### Bun-first runtime
|
|
109
109
|
|
|
@@ -111,7 +111,7 @@ Bun provides the runtime, server, bundler, markdown support, and file APIs that
|
|
|
111
111
|
|
|
112
112
|
Read more:
|
|
113
113
|
|
|
114
|
-
- https://react-bun-ssr.
|
|
114
|
+
- https://react-bun-ssr.dev/docs/api/bun-runtime-apis
|
|
115
115
|
|
|
116
116
|
## Core commands
|
|
117
117
|
|
|
@@ -132,7 +132,7 @@ Repository maintenance commands:
|
|
|
132
132
|
|
|
133
133
|
CLI reference:
|
|
134
134
|
|
|
135
|
-
- https://react-bun-ssr.
|
|
135
|
+
- https://react-bun-ssr.dev/docs/tooling/cli
|
|
136
136
|
|
|
137
137
|
## Working on this repository
|
|
138
138
|
|
|
@@ -147,16 +147,24 @@ bun run docs:dev
|
|
|
147
147
|
|
|
148
148
|
That starts the docs site locally using the framework itself.
|
|
149
149
|
|
|
150
|
+
Dependency ownership is split intentionally:
|
|
151
|
+
|
|
152
|
+
- the repo-root `package.json` is the published framework manifest
|
|
153
|
+
- [`app/package.json`](/Users/react-formation/code/my-app/app/package.json) owns docs-app runtime dependencies
|
|
154
|
+
|
|
155
|
+
Contributors should still use the repo-root commands; the workspace split is there to keep npm package metadata accurate, not to change the day-to-day workflow.
|
|
156
|
+
|
|
150
157
|
## Project layout
|
|
151
158
|
|
|
152
159
|
- `framework/`: runtime, renderer, route handling, build tooling, and CLI internals
|
|
153
160
|
- `bin/rbssr.ts`: CLI entrypoint
|
|
154
161
|
- `app/`: docs site routes, layouts, middleware, blog, and styles
|
|
162
|
+
- `app/package.json`: private docs-app dependency manifest
|
|
155
163
|
- `app/routes/docs/**/*.md`: authored documentation pages
|
|
156
164
|
- `app/routes/blog/*.md`: authored blog posts
|
|
157
165
|
- `scripts/`: generators and validation scripts
|
|
158
|
-
- `tests/`: unit and
|
|
159
|
-
- `
|
|
166
|
+
- `tests/framework/`: framework runtime, CLI, build, unit/integration, and framework Playwright tests
|
|
167
|
+
- `tests/docs-app/`: docs site, blog, analytics, and docs-app Playwright tests
|
|
160
168
|
|
|
161
169
|
## Contributing
|
|
162
170
|
|
|
@@ -184,6 +192,6 @@ fly deploy
|
|
|
184
192
|
|
|
185
193
|
Full deployment docs:
|
|
186
194
|
|
|
187
|
-
- https://react-bun-ssr.
|
|
188
|
-
- https://react-bun-ssr.
|
|
189
|
-
- https://react-bun-ssr.
|
|
195
|
+
- https://react-bun-ssr.dev/docs/deployment/bun-deployment
|
|
196
|
+
- https://react-bun-ssr.dev/docs/deployment/configuration
|
|
197
|
+
- https://react-bun-ssr.dev/docs/deployment/troubleshooting
|
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
import { watch, type FSWatcher } from "node:fs";
|
|
2
1
|
import path from "node:path";
|
|
3
2
|
import {
|
|
4
3
|
buildRouteManifest,
|
|
5
4
|
bundleClientEntries,
|
|
6
5
|
copyDirRecursive,
|
|
7
6
|
createBuildManifest,
|
|
8
|
-
discoverFileSignature,
|
|
9
7
|
ensureCleanDirectory,
|
|
10
8
|
generateClientEntries,
|
|
11
9
|
} from "../runtime/build-tools";
|
|
12
10
|
import { loadUserConfig, resolveConfig } from "../runtime/config";
|
|
13
|
-
import { ensureDir, existsPath,
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
11
|
+
import { ensureDir, existsPath, writeText, writeTextIfChanged } from "../runtime/io";
|
|
12
|
+
import type { FrameworkConfig, ResolvedConfig } from "../runtime/types";
|
|
13
|
+
import {
|
|
14
|
+
createDevHotEntrypointSource,
|
|
15
|
+
createProductionServerEntrypointSource,
|
|
16
|
+
createTestCommands,
|
|
17
|
+
createTypecheckCommand,
|
|
18
|
+
parseFlags,
|
|
19
|
+
RBSSR_DEV_RESTART_EXIT_CODE,
|
|
20
|
+
} from "./internal";
|
|
16
21
|
import { scaffoldApp } from "./scaffold";
|
|
17
22
|
|
|
18
23
|
function log(message: string): void {
|
|
@@ -20,10 +25,19 @@ function log(message: string): void {
|
|
|
20
25
|
console.log(`[rbssr] ${message}`);
|
|
21
26
|
}
|
|
22
27
|
|
|
23
|
-
function
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
async function withNodeEnv<T>(nodeEnv: "development" | "production", run: () => Promise<T>): Promise<T> {
|
|
29
|
+
const previousNodeEnv = process.env.NODE_ENV;
|
|
30
|
+
process.env.NODE_ENV = nodeEnv;
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
return await run();
|
|
34
|
+
} finally {
|
|
35
|
+
if (previousNodeEnv === undefined) {
|
|
36
|
+
delete process.env.NODE_ENV;
|
|
37
|
+
} else {
|
|
38
|
+
process.env.NODE_ENV = previousNodeEnv;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
27
41
|
}
|
|
28
42
|
|
|
29
43
|
async function getConfig(cwd: string): Promise<{ userConfig: FrameworkConfig; resolved: ResolvedConfig }> {
|
|
@@ -37,29 +51,7 @@ async function writeProductionServerEntrypoint(options: { distDir: string }): Pr
|
|
|
37
51
|
await ensureDir(serverDir);
|
|
38
52
|
|
|
39
53
|
const serverEntryPath = path.join(serverDir, "server.mjs");
|
|
40
|
-
|
|
41
|
-
import config from "../../rbssr.config.ts";
|
|
42
|
-
import { startHttpServer } from "../../framework/runtime/index.ts";
|
|
43
|
-
|
|
44
|
-
const rootDir = path.resolve(path.dirname(Bun.fileURLToPath(import.meta.url)), "../..");
|
|
45
|
-
process.chdir(rootDir);
|
|
46
|
-
|
|
47
|
-
const manifestPath = path.resolve(rootDir, "dist/manifest.json");
|
|
48
|
-
const manifest = await Bun.file(manifestPath).json();
|
|
49
|
-
|
|
50
|
-
startHttpServer({
|
|
51
|
-
config: {
|
|
52
|
-
...(config ?? {}),
|
|
53
|
-
mode: "production",
|
|
54
|
-
},
|
|
55
|
-
runtimeOptions: {
|
|
56
|
-
dev: false,
|
|
57
|
-
buildManifest: manifest,
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
`;
|
|
61
|
-
|
|
62
|
-
await writeText(serverEntryPath, content);
|
|
54
|
+
await writeText(serverEntryPath, createProductionServerEntrypointSource());
|
|
63
55
|
}
|
|
64
56
|
|
|
65
57
|
export async function runInit(args: string[], cwd = process.cwd()): Promise<void> {
|
|
@@ -71,238 +63,109 @@ export async function runInit(args: string[], cwd = process.cwd()): Promise<void
|
|
|
71
63
|
}
|
|
72
64
|
|
|
73
65
|
export async function runBuild(cwd = process.cwd()): Promise<void> {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
ensureCleanDirectory(resolved.distDir),
|
|
81
|
-
ensureCleanDirectory(generatedDir),
|
|
82
|
-
]);
|
|
83
|
-
|
|
84
|
-
const routeManifest = await buildRouteManifest(resolved);
|
|
85
|
-
const entries = await generateClientEntries({
|
|
86
|
-
config: resolved,
|
|
87
|
-
manifest: routeManifest,
|
|
88
|
-
generatedDir,
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
const routeAssets = await bundleClientEntries({
|
|
92
|
-
entries,
|
|
93
|
-
outDir: distClientDir,
|
|
94
|
-
dev: false,
|
|
95
|
-
publicPrefix: "/client/",
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
await copyDirRecursive(resolved.publicDir, distClientDir);
|
|
99
|
-
|
|
100
|
-
const buildManifest = createBuildManifest(routeAssets);
|
|
101
|
-
await writeText(
|
|
102
|
-
path.join(resolved.distDir, "manifest.json"),
|
|
103
|
-
JSON.stringify(buildManifest, null, 2),
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
await writeProductionServerEntrypoint({ distDir: resolved.distDir });
|
|
107
|
-
|
|
108
|
-
log(`build complete: ${resolved.distDir}`);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export async function runDev(cwd = process.cwd()): Promise<void> {
|
|
112
|
-
const { userConfig, resolved } = await getConfig(cwd);
|
|
113
|
-
const generatedDir = path.resolve(cwd, ".rbssr/generated/client-entries");
|
|
114
|
-
const devClientDir = path.resolve(cwd, ".rbssr/dev/client");
|
|
115
|
-
const serverSnapshotsRoot = path.resolve(cwd, ".rbssr/dev/server-snapshots");
|
|
116
|
-
const docsSourceDir = path.resolve(cwd, "docs");
|
|
117
|
-
const docsSnapshotDir = path.join(serverSnapshotsRoot, "docs");
|
|
118
|
-
|
|
119
|
-
await Promise.all([
|
|
120
|
-
ensureDir(generatedDir),
|
|
121
|
-
ensureDir(devClientDir),
|
|
122
|
-
ensureCleanDirectory(serverSnapshotsRoot),
|
|
123
|
-
]);
|
|
124
|
-
|
|
125
|
-
let routeAssets: Record<string, BuildRouteAsset> = {};
|
|
126
|
-
let signature = "";
|
|
127
|
-
let version = 0;
|
|
128
|
-
let currentServerSnapshotDir = resolved.appDir;
|
|
129
|
-
const reloadListeners = new Set<(nextVersion: number) => void>();
|
|
130
|
-
const docsDir = path.resolve(cwd, "docs");
|
|
131
|
-
|
|
132
|
-
const watchedRoots = [resolved.appDir];
|
|
133
|
-
if (await existsPath(docsDir)) {
|
|
134
|
-
watchedRoots.push(docsDir);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const getSourceSignature = async (): Promise<string> => {
|
|
138
|
-
const signatures = await Promise.all(
|
|
139
|
-
watchedRoots.map(root => discoverFileSignature(root)),
|
|
140
|
-
);
|
|
141
|
-
return signatures.join(":");
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
const notifyReload = (): void => {
|
|
145
|
-
for (const listener of reloadListeners) {
|
|
146
|
-
listener(version);
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
const rebuildIfNeeded = async (force = false): Promise<void> => {
|
|
151
|
-
const nextSignature = await getSourceSignature();
|
|
152
|
-
if (!force && nextSignature === signature) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
66
|
+
await withNodeEnv("production", async () => {
|
|
67
|
+
const userConfig = await loadUserConfig(cwd);
|
|
68
|
+
const resolved = resolveConfig({
|
|
69
|
+
...userConfig,
|
|
70
|
+
mode: "production",
|
|
71
|
+
}, cwd);
|
|
155
72
|
|
|
156
|
-
|
|
73
|
+
const distClientDir = path.join(resolved.distDir, "client");
|
|
74
|
+
const generatedDir = path.resolve(cwd, ".rbssr/generated/client-entries");
|
|
157
75
|
|
|
158
|
-
const snapshotDir = path.join(serverSnapshotsRoot, `v${version + 1}`);
|
|
159
|
-
const hasDocsSourceDir = await existsPath(docsSourceDir);
|
|
160
76
|
await Promise.all([
|
|
161
|
-
(
|
|
162
|
-
|
|
163
|
-
await copyDirRecursive(resolved.appDir, snapshotDir);
|
|
164
|
-
})(),
|
|
165
|
-
hasDocsSourceDir
|
|
166
|
-
? (async () => {
|
|
167
|
-
await ensureCleanDirectory(docsSnapshotDir);
|
|
168
|
-
await copyDirRecursive(docsSourceDir, docsSnapshotDir);
|
|
169
|
-
})()
|
|
170
|
-
: removePath(docsSnapshotDir),
|
|
77
|
+
ensureCleanDirectory(resolved.distDir),
|
|
78
|
+
ensureCleanDirectory(generatedDir),
|
|
171
79
|
]);
|
|
172
80
|
|
|
173
|
-
const
|
|
174
|
-
...resolved,
|
|
175
|
-
appDir: snapshotDir,
|
|
176
|
-
routesDir: path.join(snapshotDir, "routes"),
|
|
177
|
-
rootModule: path.join(snapshotDir, "root.tsx"),
|
|
178
|
-
middlewareFile: path.join(snapshotDir, "middleware.ts"),
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
const manifest = await buildRouteManifest(snapshotConfig);
|
|
81
|
+
const routeManifest = await buildRouteManifest(resolved);
|
|
182
82
|
const entries = await generateClientEntries({
|
|
183
|
-
config:
|
|
184
|
-
manifest,
|
|
83
|
+
config: resolved,
|
|
84
|
+
manifest: routeManifest,
|
|
185
85
|
generatedDir,
|
|
186
86
|
});
|
|
187
87
|
|
|
188
|
-
await
|
|
189
|
-
|
|
190
|
-
routeAssets = await bundleClientEntries({
|
|
88
|
+
const routeAssets = await bundleClientEntries({
|
|
191
89
|
entries,
|
|
192
|
-
outDir:
|
|
193
|
-
dev:
|
|
194
|
-
publicPrefix: "/
|
|
90
|
+
outDir: distClientDir,
|
|
91
|
+
dev: false,
|
|
92
|
+
publicPrefix: "/client/",
|
|
195
93
|
});
|
|
196
94
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const staleVersions = (await listEntries(serverSnapshotsRoot))
|
|
200
|
-
.filter(entry => entry.isDirectory && /^v\d+$/.test(entry.name))
|
|
201
|
-
.map(entry => entry.name)
|
|
202
|
-
.sort((a, b) => {
|
|
203
|
-
const aNum = Number(a.slice(1));
|
|
204
|
-
const bNum = Number(b.slice(1));
|
|
205
|
-
return bNum - aNum;
|
|
206
|
-
})
|
|
207
|
-
.slice(3);
|
|
208
|
-
await Promise.all(staleVersions.map(stale => removePath(path.join(serverSnapshotsRoot, stale))));
|
|
209
|
-
|
|
210
|
-
version += 1;
|
|
211
|
-
notifyReload();
|
|
212
|
-
log(`rebuilt client assets (version ${version})`);
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
let rebuildQueue: Promise<void> = Promise.resolve();
|
|
216
|
-
const enqueueRebuild = (force = false): Promise<void> => {
|
|
217
|
-
const task = rebuildQueue.then(() => rebuildIfNeeded(force));
|
|
218
|
-
rebuildQueue = task.catch(error => {
|
|
219
|
-
// eslint-disable-next-line no-console
|
|
220
|
-
console.error("[rbssr] rebuild failed", error);
|
|
221
|
-
});
|
|
222
|
-
return task;
|
|
223
|
-
};
|
|
95
|
+
await copyDirRecursive(resolved.publicDir, distClientDir);
|
|
224
96
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
clearTimeout(rebuildTimer);
|
|
231
|
-
}
|
|
97
|
+
const buildManifest = createBuildManifest(routeAssets);
|
|
98
|
+
await writeText(
|
|
99
|
+
path.join(resolved.distDir, "manifest.json"),
|
|
100
|
+
JSON.stringify(buildManifest, null, 2),
|
|
101
|
+
);
|
|
232
102
|
|
|
233
|
-
|
|
234
|
-
rebuildTimer = undefined;
|
|
235
|
-
void enqueueRebuild(false);
|
|
236
|
-
}, 75);
|
|
237
|
-
};
|
|
103
|
+
await writeProductionServerEntrypoint({ distDir: resolved.distDir });
|
|
238
104
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const watcher = watch(root, { recursive: true }, () => {
|
|
243
|
-
scheduleRebuild();
|
|
244
|
-
});
|
|
245
|
-
watchers.push(watcher);
|
|
246
|
-
} catch {
|
|
247
|
-
log(`recursive file watching unavailable for ${root}; relying on request-time rebuild checks`);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
105
|
+
log(`build complete: ${resolved.distDir}`);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
250
108
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
109
|
+
export async function runDev(cwd = process.cwd()): Promise<void> {
|
|
110
|
+
await getConfig(cwd);
|
|
111
|
+
|
|
112
|
+
const generatedDevDir = path.resolve(cwd, ".rbssr/generated/dev");
|
|
113
|
+
const generatedEntryPath = path.join(generatedDevDir, "entry.ts");
|
|
114
|
+
await ensureDir(generatedDevDir);
|
|
115
|
+
await writeTextIfChanged(generatedEntryPath, createDevHotEntrypointSource({
|
|
116
|
+
cwd,
|
|
117
|
+
runtimeModulePath: path.resolve(import.meta.dir, "dev-runtime.ts"),
|
|
118
|
+
}));
|
|
119
|
+
|
|
120
|
+
let activeChild: Bun.Subprocess<"inherit", "inherit", "inherit"> | null = null;
|
|
121
|
+
let shuttingDown = false;
|
|
122
|
+
|
|
123
|
+
const forwardSignal = (signal: NodeJS.Signals): void => {
|
|
124
|
+
shuttingDown = true;
|
|
125
|
+
activeChild?.kill(signal);
|
|
259
126
|
};
|
|
260
127
|
|
|
261
128
|
process.once("SIGINT", () => {
|
|
262
|
-
|
|
263
|
-
process.exit(0);
|
|
129
|
+
forwardSignal("SIGINT");
|
|
264
130
|
});
|
|
265
131
|
|
|
266
132
|
process.once("SIGTERM", () => {
|
|
267
|
-
|
|
268
|
-
process.exit(0);
|
|
133
|
+
forwardSignal("SIGTERM");
|
|
269
134
|
});
|
|
270
135
|
|
|
271
|
-
|
|
272
|
-
{
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
reloadListeners.delete(listener);
|
|
284
|
-
};
|
|
136
|
+
while (true) {
|
|
137
|
+
activeChild = Bun.spawn({
|
|
138
|
+
cmd: ["bun", "--hot", generatedEntryPath],
|
|
139
|
+
cwd,
|
|
140
|
+
stdin: "inherit",
|
|
141
|
+
stdout: "inherit",
|
|
142
|
+
stderr: "inherit",
|
|
143
|
+
env: {
|
|
144
|
+
...process.env,
|
|
145
|
+
NODE_ENV: "development",
|
|
146
|
+
RBSSR_DEV_LAUNCHER: "1",
|
|
147
|
+
RBSSR_DEV_CHILD: "1",
|
|
285
148
|
},
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
middlewareFile: path.join(currentServerSnapshotDir, "middleware.ts"),
|
|
291
|
-
}),
|
|
292
|
-
onBeforeRequest: () => {
|
|
293
|
-
return enqueueRebuild(false);
|
|
294
|
-
},
|
|
295
|
-
},
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
const bunServer = Bun.serve({
|
|
299
|
-
hostname: resolved.host,
|
|
300
|
-
port: resolved.port,
|
|
301
|
-
fetch: server.fetch,
|
|
302
|
-
development: true,
|
|
303
|
-
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const exitCode = await activeChild.exited;
|
|
152
|
+
activeChild = null;
|
|
304
153
|
|
|
305
|
-
|
|
154
|
+
if (shuttingDown) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (exitCode === RBSSR_DEV_RESTART_EXIT_CODE) {
|
|
159
|
+
log("restarting dev child after config change");
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (exitCode !== 0) {
|
|
164
|
+
process.exit(exitCode);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
306
169
|
}
|
|
307
170
|
|
|
308
171
|
export async function runStart(cwd = process.cwd()): Promise<void> {
|
|
@@ -328,16 +191,11 @@ function runSubprocess(cmd: string[]): void {
|
|
|
328
191
|
}
|
|
329
192
|
|
|
330
193
|
export async function runTypecheck(): Promise<void> {
|
|
331
|
-
runSubprocess(
|
|
194
|
+
runSubprocess(createTypecheckCommand());
|
|
332
195
|
}
|
|
333
196
|
|
|
334
197
|
export async function runTest(extraArgs: string[]): Promise<void> {
|
|
335
|
-
|
|
336
|
-
runSubprocess(
|
|
337
|
-
return;
|
|
198
|
+
for (const cmd of createTestCommands(extraArgs)) {
|
|
199
|
+
runSubprocess(cmd);
|
|
338
200
|
}
|
|
339
|
-
|
|
340
|
-
runSubprocess(["bun", "test", "./tests/unit"]);
|
|
341
|
-
runSubprocess(["bun", "test", "./tests/integration"]);
|
|
342
|
-
runSubprocess(["bun", "x", "playwright", "test"]);
|
|
343
201
|
}
|