tina4-nodejs 3.11.2 → 3.11.4
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/package.json
CHANGED
|
@@ -37,48 +37,13 @@ export async function serveProject(options: ServeOptions): Promise<void> {
|
|
|
37
37
|
staticDir,
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
// so we only need to touch the router when a .ts/.js route file actually
|
|
44
|
-
// changes. Clearing the router on every edit (including templates) leaves a
|
|
45
|
-
// brief window where the router is empty — any request hitting that window
|
|
46
|
-
// gets a 404 whose response path bypasses the dev toolbar injection, so the
|
|
47
|
-
// toolbar appears to "vanish" after a hot reload. Route-file-only clearing
|
|
48
|
-
// matches the behaviour of Python's DevReload and the fix made in PHP v3.10.87.
|
|
49
|
-
const noReload = ["true", "1", "yes"].includes((process.env.TINA4_NO_RELOAD ?? "").toLowerCase());
|
|
50
|
-
const watchDirs = [routesDir, ormDir, modelsDir, templatesDir].filter((d) => existsSync(d));
|
|
51
|
-
let watcher: { close: () => void } | null = null;
|
|
52
|
-
if (!noReload) {
|
|
53
|
-
watcher = watchForChanges(watchDirs, async ({ code }) => {
|
|
54
|
-
if (!code) {
|
|
55
|
-
// Template/CSS/JS asset change — nothing to do in the server. The
|
|
56
|
-
// browser will re-fetch on its own reload cycle and the request will
|
|
57
|
-
// be served against the existing route set with the toolbar intact.
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
try {
|
|
61
|
-
// Re-discover routes. discoverRoutes() cache-busts imports via ?t=<timestamp>,
|
|
62
|
-
// so the new modules are loaded fresh. Build the new list first, then
|
|
63
|
-
// replace the router's state in one back-to-back block to minimise the
|
|
64
|
-
// window where the router is empty.
|
|
65
|
-
const { discoverRoutes } = await import("../../../core/src/index.js");
|
|
66
|
-
const routes = await discoverRoutes(routesDir);
|
|
67
|
-
server.router.clear();
|
|
68
|
-
for (const route of routes) {
|
|
69
|
-
server.router.addRoute(route);
|
|
70
|
-
}
|
|
71
|
-
console.log(` Reloaded ${routes.length} route(s)`);
|
|
72
|
-
} catch (err) {
|
|
73
|
-
console.error(" Error reloading routes:", err);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
}
|
|
40
|
+
// File watching is handled by the Rust CLI (tina4 serve). The framework
|
|
41
|
+
// only needs POST /__dev/api/reload to update the mtime counter for browser polling.
|
|
42
|
+
// No internal file watcher.
|
|
77
43
|
|
|
78
44
|
// Graceful shutdown
|
|
79
45
|
const shutdown = () => {
|
|
80
46
|
console.log("\n Shutting down...");
|
|
81
|
-
watcher?.close();
|
|
82
47
|
server.close();
|
|
83
48
|
process.exit(0);
|
|
84
49
|
};
|
|
@@ -437,6 +437,9 @@ export class DevAdmin {
|
|
|
437
437
|
// Dashboard
|
|
438
438
|
{ method: "GET", pattern: "/__dev", handler: handleDashboard },
|
|
439
439
|
{ method: "GET", pattern: "/__dev/", handler: handleDashboard },
|
|
440
|
+
// Reload — called by Rust CLI on file changes
|
|
441
|
+
{ method: "GET", pattern: "/__dev/api/mtime", handler: handleMtime },
|
|
442
|
+
{ method: "POST", pattern: "/__dev/api/reload", handler: handleReload },
|
|
440
443
|
// Status & system
|
|
441
444
|
{ method: "GET", pattern: "/__dev/api/status", handler: handleStatus(router) },
|
|
442
445
|
{ method: "GET", pattern: "/__dev/api/system", handler: handleSystem },
|
|
@@ -526,6 +529,23 @@ const handleDashboard: RouteHandler = (_req, res) => {
|
|
|
526
529
|
res.raw.end(spa);
|
|
527
530
|
};
|
|
528
531
|
|
|
532
|
+
// Reload mtime counter — updated by POST /__dev/api/reload from Rust CLI
|
|
533
|
+
let _reloadMtime = 0;
|
|
534
|
+
let _reloadFile = "";
|
|
535
|
+
|
|
536
|
+
const handleMtime: RouteHandler = async (_req, res) => {
|
|
537
|
+
res.json({ mtime: _reloadMtime, file: _reloadFile });
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
const handleReload: RouteHandler = async (req, res) => {
|
|
541
|
+
_reloadMtime = Math.floor(Date.now() / 1000);
|
|
542
|
+
const body = req.body as Record<string, unknown> | undefined;
|
|
543
|
+
_reloadFile = (body?.file as string) || "";
|
|
544
|
+
const reloadType = (body?.type as string) || "reload";
|
|
545
|
+
console.log(` External reload trigger: ${reloadType}${_reloadFile ? ` (${_reloadFile})` : ""}`);
|
|
546
|
+
res.json({ ok: true, type: reloadType });
|
|
547
|
+
};
|
|
548
|
+
|
|
529
549
|
function handleStatus(router: Router): RouteHandler {
|
|
530
550
|
return async (_req, res) => {
|
|
531
551
|
const mem = process.memoryUsage();
|