@pylonsync/functions 0.3.306 → 0.3.308
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 +1 -1
- package/src/ssr-client-bundler.ts +42 -0
package/package.json
CHANGED
|
@@ -1220,9 +1220,11 @@ async function _doBuildInner(
|
|
|
1220
1220
|
// Tailwind v4 compile. Optional — only fires if the project has
|
|
1221
1221
|
// `app/globals.css`. Adds the stylesheet to every route's css
|
|
1222
1222
|
// array so SSR head injection emits `<link rel="stylesheet">`.
|
|
1223
|
+
let stylesRel: string | null = null;
|
|
1223
1224
|
try {
|
|
1224
1225
|
const styles = await buildTailwind(fs, path, cwd, outdir, appDirRel);
|
|
1225
1226
|
if (styles) {
|
|
1227
|
+
stylesRel = styles;
|
|
1226
1228
|
for (const r of Object.values(manifest.routes)) {
|
|
1227
1229
|
r.css = [styles];
|
|
1228
1230
|
}
|
|
@@ -1252,6 +1254,46 @@ async function _doBuildInner(
|
|
|
1252
1254
|
console.warn(`[pylon ssr] font build failed: ${fErr?.message ?? fErr}`);
|
|
1253
1255
|
}
|
|
1254
1256
|
|
|
1257
|
+
// App-overridable rate-limit page. The rate limiter short-circuits in the
|
|
1258
|
+
// Rust layer BEFORE SSR, so it can't render a route per (shed) request —
|
|
1259
|
+
// instead pre-render `app/rate-limit.tsx` ONCE here to a self-contained
|
|
1260
|
+
// static HTML (compiled CSS inlined, so it needs no asset fetch) that the
|
|
1261
|
+
// runtime serves on 429 for browser navigations. FULLY GATED: any failure
|
|
1262
|
+
// just skips the override and the framework's built-in default 429 page is
|
|
1263
|
+
// used — a broken/absent rate-limit.tsx never affects the build.
|
|
1264
|
+
try {
|
|
1265
|
+
const rlPath = path.join(cwd, appDirRel, "rate-limit.tsx");
|
|
1266
|
+
if (fs.existsSync(rlPath)) {
|
|
1267
|
+
const ReactMod: any = await import("react");
|
|
1268
|
+
const React = ReactMod.default ?? ReactMod;
|
|
1269
|
+
const { renderToStaticMarkup }: any = await import("react-dom/server");
|
|
1270
|
+
const mod: any = await import(rlPath);
|
|
1271
|
+
const Comp = mod.default;
|
|
1272
|
+
if (typeof Comp === "function") {
|
|
1273
|
+
const inner = renderToStaticMarkup(React.createElement(Comp));
|
|
1274
|
+
const css = stylesRel
|
|
1275
|
+
? fs.readFileSync(path.join(outdir, stylesRel), "utf8")
|
|
1276
|
+
: "";
|
|
1277
|
+
const html =
|
|
1278
|
+
`<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">` +
|
|
1279
|
+
`<meta name="viewport" content="width=device-width, initial-scale=1">` +
|
|
1280
|
+
`<title>Too many requests</title>` +
|
|
1281
|
+
(css ? `<style>${css}</style>` : "") +
|
|
1282
|
+
`</head><body>${inner}</body></html>`;
|
|
1283
|
+
fs.writeFileSync(path.join(outdir, "rate-limit.html"), html, "utf8");
|
|
1284
|
+
// eslint-disable-next-line no-console
|
|
1285
|
+
console.log(
|
|
1286
|
+
"[pylon ssr] pre-rendered app/rate-limit.tsx → rate-limit.html",
|
|
1287
|
+
);
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
} catch (rlErr: any) {
|
|
1291
|
+
// eslint-disable-next-line no-console
|
|
1292
|
+
console.warn(
|
|
1293
|
+
`[pylon ssr] rate-limit.tsx pre-render skipped: ${rlErr?.message ?? rlErr}`,
|
|
1294
|
+
);
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1255
1297
|
const manifestPath = path.join(outdir, "manifest.json");
|
|
1256
1298
|
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf8");
|
|
1257
1299
|
|