@rpcbase/server 0.448.0 → 0.450.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.
@@ -1 +1 @@
1
- {"version":3,"file":"applyRouteLoaders.d.ts","sourceRoot":"","sources":["../src/applyRouteLoaders.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,OAAO,EAAC,MAAM,SAAS,CAAA;AAC/B,OAAO,EACL,oBAAoB,EAMrB,MAAM,iBAAiB,CAAA;AAoExB,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,UAAU,EAAE,GAAG,EAAE,GAChB,OAAO,CAAC,oBAAoB,CAAC,CAqH/B"}
1
+ {"version":3,"file":"applyRouteLoaders.d.ts","sourceRoot":"","sources":["../src/applyRouteLoaders.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,OAAO,EAAC,MAAM,SAAS,CAAA;AAC/B,OAAO,EACL,oBAAoB,EAMrB,MAAM,iBAAiB,CAAA;AAqExB,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,UAAU,EAAE,GAAG,EAAE,GAChB,OAAO,CAAC,oBAAoB,CAAC,CAsI/B"}
package/dist/index.js CHANGED
@@ -363,6 +363,7 @@ function getShortCircuitMatches(routes) {
363
363
  };
364
364
  }
365
365
  const NOT_FOUND_STATUS = 404;
366
+ const LOADER_TIMEOUT_MS = 4e3;
366
367
  const getErrorStatus = (error) => {
367
368
  if (!error) return void 0;
368
369
  const candidate = error?.reason ?? error;
@@ -408,22 +409,36 @@ async function applyRouteLoaders(req, dataRoutes) {
408
409
  statusCode: 200
409
410
  };
410
411
  }
411
- const loaderPromisesResults = await Promise.allSettled(
412
- matches.map(async (match) => {
413
- const { route, params } = match;
414
- if (!route.loader) return null;
412
+ const runLoaderWithTimeout = async (route, params) => {
413
+ if (!route.loader) return null;
414
+ let timeoutId;
415
+ const timeoutPromise = new Promise((_, reject) => {
416
+ timeoutId = setTimeout(() => {
417
+ const err = new Error(`Loader timeout after ${LOADER_TIMEOUT_MS}ms`);
418
+ err.status = 504;
419
+ console.error("[rpcbase timeout][server loader]", { routeId: route.id, ms: LOADER_TIMEOUT_MS, url: req.originalUrl });
420
+ reject({ id: route.id, reason: err });
421
+ }, LOADER_TIMEOUT_MS);
422
+ });
423
+ const loaderPromise = (async () => {
415
424
  try {
416
- return {
417
- id: route.id,
418
- data: await route.loader({
419
- params,
420
- ctx: { req }
421
- })
422
- };
425
+ const data = await route.loader({
426
+ params,
427
+ ctx: { req }
428
+ });
429
+ return { id: route.id, data };
423
430
  } catch (error) {
424
431
  throw { id: route.id, reason: error };
432
+ } finally {
433
+ if (timeoutId) {
434
+ clearTimeout(timeoutId);
435
+ }
425
436
  }
426
- })
437
+ })();
438
+ return Promise.race([loaderPromise, timeoutPromise]);
439
+ };
440
+ const loaderPromisesResults = await Promise.allSettled(
441
+ matches.map((match) => runLoaderWithTimeout(match.route, match.params))
427
442
  );
428
443
  const loaderData = {};
429
444
  let errors = null;
@@ -502,6 +517,8 @@ async function renderSSR(req, dataRoutes) {
502
517
  const ABORT_DELAY_MS = 1e4;
503
518
  const APP_HTML_PLACEHOLDER = "<!--app-html-->";
504
519
  const DEFAULT_SERVER_ERROR_MESSAGE = "We couldn't render this page on the server. Please refresh and try again.";
520
+ const FALLBACK_ERROR_TEMPLATE_START = `<!doctype html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>Server error</title><style>body{margin:0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:#0b1021;color:#eef1f7;display:flex;align-items:center;justify-content:center;min-height:100vh;}main{max-width:420px;padding:32px;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);border-radius:14px;box-shadow:0 25px 50px rgba(0,0,0,0.35);}h1{font-size:24px;margin:0 0 8px;}p{margin:0 0 12px;line-height:1.5;}code{background:rgba(255,255,255,0.08);padding:2px 6px;border-radius:6px;font-size:12px;}</style></head><body><main>`;
521
+ const FALLBACK_ERROR_TEMPLATE_END = "</main></body></html>";
505
522
  const isProduction = env.NODE_ENV === "production";
506
523
  const templateHtml = isProduction ? readFileSync("./build/dist/client/src/client/index.html", "utf-8") : "";
507
524
  const formatErrorDetails = (error) => {
@@ -519,22 +536,6 @@ const formatErrorDetails = (error) => {
519
536
  return void 0;
520
537
  }
521
538
  };
522
- const formatPlainErrorBody = (error) => {
523
- if (isProduction) {
524
- return "Server error";
525
- }
526
- if (error instanceof Error) {
527
- return error.stack || error.message;
528
- }
529
- if (typeof error === "string") {
530
- return error;
531
- }
532
- try {
533
- return JSON.stringify(error, null, 2);
534
- } catch {
535
- return "Unknown error";
536
- }
537
- };
538
539
  const sendErrorResponse = ({
539
540
  res,
540
541
  htmlStart,
@@ -546,10 +547,8 @@ const sendErrorResponse = ({
546
547
  errorExtraComponent
547
548
  }) => {
548
549
  if (res.headersSent) return;
549
- if (!htmlStart || !htmlEnd) {
550
- res.status(status).end(formatPlainErrorBody(error));
551
- return;
552
- }
550
+ const start = htmlStart ?? FALLBACK_ERROR_TEMPLATE_START;
551
+ const end = htmlEnd ?? FALLBACK_ERROR_TEMPLATE_END;
553
552
  res.status(status);
554
553
  res.set({ "Content-Type": "text/html" });
555
554
  const details = formatErrorDetails(error);
@@ -573,7 +572,7 @@ const sendErrorResponse = ({
573
572
  ...state,
574
573
  details: isProduction ? void 0 : details
575
574
  })};<\/script>`;
576
- res.end(`${htmlStart}${markup}${serializedState}${htmlEnd}`);
575
+ res.end(`${start}${markup}${serializedState}${end}`);
577
576
  };
578
577
  const ssrMiddleware = ({
579
578
  viteInstance,
@@ -1 +1 @@
1
- {"version":3,"file":"ssrMiddleware.d.ts","sourceRoot":"","sources":["../src/ssrMiddleware.ts"],"names":[],"mappings":"AAKA,OAAO,EAAwE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AACjI,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,EAA6B,KAAK,aAAa,EAAE,MAAM,OAAO,CAAA;AAErE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAKzD,KAAK,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC;AAyG9D,eAAO,MAAM,aAAa,GAAI,yEAK3B;IACD,YAAY,EAAE,aAAa,CAAC;IAC5B,UAAU,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACxC,mBAAmB,CAAC,EAAE,aAAa,CAAC;QAAE,KAAK,CAAC,EAAE,oBAAoB,CAAA;KAAE,CAAC,CAAC;IACtE,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAChF,MAAW,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBA0H1D,CAAA"}
1
+ {"version":3,"file":"ssrMiddleware.d.ts","sourceRoot":"","sources":["../src/ssrMiddleware.ts"],"names":[],"mappings":"AAKA,OAAO,EAAwE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AACjI,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,EAA6B,KAAK,aAAa,EAAE,MAAM,OAAO,CAAA;AAErE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAKzD,KAAK,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC;AAwF9D,eAAO,MAAM,aAAa,GAAI,yEAK3B;IACD,YAAY,EAAE,aAAa,CAAC;IAC5B,UAAU,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACxC,mBAAmB,CAAC,EAAE,aAAa,CAAC;QAAE,KAAK,CAAC,EAAE,oBAAoB,CAAA;KAAE,CAAC,CAAC;IACtE,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAChF,MAAW,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBA0H1D,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpcbase/server",
3
- "version": "0.448.0",
3
+ "version": "0.450.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"