redweb 0.13.3 → 0.14.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/CHANGELOG.md +24 -1
- package/README.md +23 -33
- package/bin/redweb.js +1 -1
- package/docs/APPLICATION.md +98 -0
- package/docs/CLI.md +1 -1
- package/docs/COVERAGE_SCOPE_AUDIT.md +7 -0
- package/docs/DEFINE_APP_VERIFICATION.md +101 -0
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/GETTING_STARTED.md +1 -1
- package/docs/LIVE_HTML.md +2 -2
- package/docs/MIGRATION.md +1 -1
- package/docs/MULTIPLAYER_OPERATIONS.md +6 -0
- package/docs/RELEASE_TRUST.md +4 -4
- package/docs/RUNTIME_DIAGNOSTICS.md +1 -1
- package/docs/SOCKET_CONTRACTS.md +2 -2
- package/docs/STARTER_LIFECYCLE_VERIFICATION.md +9 -0
- package/docs/generated.json +327 -273
- package/docs/guides/http-websocket.md +4 -4
- package/docs/guides/jsx-without-react.md +1 -1
- package/docs/reference.json +40 -1
- package/docs/releases/0.13.4.json +2154 -0
- package/docs/releases/0.13.5.json +2154 -0
- package/docs/releases/0.14.0.json +2208 -0
- package/docs/topics.json +1 -0
- package/examples/live-html/cards.js +87 -86
- package/examples/live-html/cards.ts +3 -2
- package/examples/live-html/chatroom.js +210 -207
- package/examples/live-html/chatroom.tsx +6 -2
- package/examples/live-html/components.js +103 -102
- package/examples/live-html/components.ts +3 -2
- package/examples/live-html/counter.js +74 -73
- package/examples/live-html/counter.ts +3 -2
- package/examples/live-html/jsx-page.js +2 -1
- package/examples/live-html/jsx-page.tsx +3 -2
- package/index.d.ts +53 -5
- package/index.js +3 -0
- package/package.json +5 -4
- package/recipes/chat/app.test.cjs +3 -1
- package/recipes/chat/app.tsx +4 -7
- package/recipes/dashboard/README.md +3 -3
- package/recipes/dashboard/app.test.cjs +41 -11
- package/recipes/dashboard/app.tsx +50 -30
- package/recipes/dashboard/auth.ts +6 -4
- package/recipes/dashboard/rate-window.test.cjs +4 -4
- package/recipes/http-ws/README.md +1 -1
- package/recipes/http-ws/app.test.cjs +8 -10
- package/recipes/http-ws/app.tsx +9 -20
- package/recipes/realtime/app.tsx +3 -6
- package/recipes/shared/README.md +3 -1
- package/recipes/shared/lifecycle.test.cjs +81 -0
- package/recipes/shared/network.cjs +10 -5
- package/recipes/site/app.tsx +3 -6
- package/recipes/socket/app.tsx +3 -10
- package/src/Application.js +239 -0
- package/src/StartupCleanup.js +24 -0
- package/src/cli/SourceInspector.js +5 -0
- package/src/cli/templates.js +3 -4
- package/src/htmx/LiveHtmlServer.js +14 -5
- package/src/htmx/PageManager.js +3 -1
- package/src/ws/BaseSocketServer.js +13 -13
- package/src/ws/SocketRoute.js +6 -2
- package/recipes/shared/run-app.test.cjs +0 -158
- package/recipes/shared/run-app.ts +0 -50
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import type { Server } from 'node:http';
|
|
2
|
-
|
|
3
|
-
interface Application { server: Server; shutdown(): Promise<void>; }
|
|
4
|
-
|
|
5
|
-
/** Entry-point policy only: importing a recipe never installs process handlers. */
|
|
6
|
-
export function runApp<T extends Application>(createApp: () => T, shutdownTimeoutMs = 5000): T | undefined {
|
|
7
|
-
if (!Number.isInteger(shutdownTimeoutMs) || shutdownTimeoutMs < 1 || shutdownTimeoutMs > 2147483647) {
|
|
8
|
-
throw new RangeError('Application shutdown timeout must be a positive timer-safe integer.');
|
|
9
|
-
}
|
|
10
|
-
const fail = (message: string) => {
|
|
11
|
-
console.error(message);
|
|
12
|
-
if (Number(process.exitCode ?? 0) === 0) process.exitCode = 1;
|
|
13
|
-
};
|
|
14
|
-
let app: T;
|
|
15
|
-
try { app = createApp(); }
|
|
16
|
-
catch { fail('Application startup failed.'); return undefined; }
|
|
17
|
-
|
|
18
|
-
let closing: Promise<void> | undefined;
|
|
19
|
-
const stop = () => {
|
|
20
|
-
if (!closing) {
|
|
21
|
-
let failed = false;
|
|
22
|
-
const deadline = setTimeout(() => {
|
|
23
|
-
fail('Application cleanup exceeded its deadline; terminating the process.');
|
|
24
|
-
process.exit();
|
|
25
|
-
}, shutdownTimeoutMs);
|
|
26
|
-
closing = Promise.resolve().then(() => app.shutdown()).catch(() => {
|
|
27
|
-
failed = true;
|
|
28
|
-
fail('Application cleanup failed.');
|
|
29
|
-
}).finally(() => {
|
|
30
|
-
// Failed cleanup may leave live handles. Permit natural exit if none
|
|
31
|
-
// remain, but still force a bounded exit when resources were leaked.
|
|
32
|
-
if (failed) { deadline.unref(); return; }
|
|
33
|
-
clearTimeout(deadline);
|
|
34
|
-
process.off('SIGINT', stop);
|
|
35
|
-
process.off('SIGTERM', stop);
|
|
36
|
-
app.server.off('error', onError);
|
|
37
|
-
app.server.off('close', stop);
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
return closing;
|
|
41
|
-
};
|
|
42
|
-
const onError = () => { fail('Application listener failed.'); void stop(); };
|
|
43
|
-
// Persistent handlers keep repeated signals from bypassing active cleanup.
|
|
44
|
-
process.on('SIGINT', stop);
|
|
45
|
-
process.on('SIGTERM', stop);
|
|
46
|
-
app.server.on('error', onError);
|
|
47
|
-
// Native close can precede database/worker cleanup: it starts, never ends, shutdown.
|
|
48
|
-
app.server.once('close', stop);
|
|
49
|
-
return app;
|
|
50
|
-
}
|