@ereo/server 0.1.23 → 0.1.25

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.
@@ -95,6 +95,14 @@ export declare class BunServer {
95
95
  * Handle a matched route.
96
96
  */
97
97
  private handleRoute;
98
+ /**
99
+ * Execute inline middleware exported from the route module.
100
+ */
101
+ private executeInlineMiddleware;
102
+ /**
103
+ * Inner route handler (after middleware).
104
+ */
105
+ private handleRouteInner;
98
106
  /**
99
107
  * Render a full HTML page with the route component and layouts.
100
108
  */
@@ -102,6 +110,10 @@ export declare class BunServer {
102
110
  /**
103
111
  * Render page using React 18 streaming SSR.
104
112
  * Uses renderToReadableStream for Bun environments with native Web Streams API.
113
+ *
114
+ * Bytes flow progressively: shell head → React chunks as they render → tail.
115
+ * The browser can parse the head (CSS, meta) and start rendering immediately
116
+ * while React continues resolving Suspense boundaries on the server.
105
117
  */
106
118
  private renderStreamingPage;
107
119
  /**
@@ -111,6 +123,9 @@ export declare class BunServer {
111
123
  /**
112
124
  * Render page directly using streaming when layout provides HTML structure.
113
125
  * The layout component is expected to render the full HTML document.
126
+ *
127
+ * React content streams progressively. Hydration scripts are appended
128
+ * after the stream completes (browsers tolerate post-body scripts).
114
129
  */
115
130
  private renderStreamingPageDirect;
116
131
  /**
@@ -137,6 +152,21 @@ export declare class BunServer {
137
152
  * Extract meta tags from meta descriptors (excluding title).
138
153
  */
139
154
  private extractMetaTags;
155
+ /**
156
+ * Build matches data for useMatches hook.
157
+ * Returns array of matched routes from outermost layout to page.
158
+ */
159
+ private buildMatchesData;
160
+ /**
161
+ * Build merged response headers from route and layout headers functions.
162
+ * Cascades from outermost layout → innermost layout → route.
163
+ * Each headers function receives the parent headers from the layout above it.
164
+ */
165
+ private buildRouteHeaders;
166
+ /**
167
+ * Apply custom route headers to a Response, preserving required headers.
168
+ */
169
+ private applyRouteHeaders;
140
170
  /**
141
171
  * Escape HTML special characters.
142
172
  */
@@ -1 +1 @@
1
- {"version":3,"file":"bun-server.d.ts","sourceRoot":"","sources":["../src/bun-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bun-server.d.ts","sourceRoot":"","sources":["../src/bun-server.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  var __require = import.meta.require;
3
3
 
4
4
  // src/bun-server.ts
5
- import { createContext } from "@ereo/core";
5
+ import { createContext, NotFoundError } from "@ereo/core";
6
6
  import { matchWithLayouts } from "@ereo/router";
7
7
 
8
8
  // src/middleware.ts
@@ -422,7 +422,7 @@ function staticMiddleware(options) {
422
422
  }
423
423
 
424
424
  // src/streaming.ts
425
- import { serializeLoaderData } from "@ereo/data";
425
+ import { serializeLoaderData, hasDeferredData, resolveAllDeferred } from "@ereo/data";
426
426
  function createShell(options) {
427
427
  const { shell = {}, scripts = [], styles = [], loaderData } = options;
428
428
  const htmlAttrs = Object.entries(shell.htmlAttrs || {}).map(([k, v]) => `${k}="${v}"`).join(" ");
@@ -435,6 +435,11 @@ function createShell(options) {
435
435
  `);
436
436
  const styleLinks = styles.map((href) => `<link rel="stylesheet" href="${href}">`).join(`
437
437
  `);
438
+ const linkTags = (shell.links || []).map((link) => {
439
+ const attrs = Object.entries(link).filter(([, v]) => v !== undefined).map(([k, v]) => `${k}="${escapeAttr(String(v))}"`).join(" ");
440
+ return `<link ${attrs}>`;
441
+ }).join(`
442
+ `);
438
443
  const scriptTags = scripts.map((src) => `<script type="module" src="${src}"></script>`).join(`
439
444
  `);
440
445
  const loaderScript = loaderData ? `<script>window.__EREO_DATA__=${serializeLoaderData(loaderData)}</script>` : "";
@@ -445,6 +450,7 @@ function createShell(options) {
445
450
  <meta name="viewport" content="width=device-width, initial-scale=1">
446
451
  ${shell.title ? `<title>${shell.title}</title>` : ""}
447
452
  ${metaTags}
453
+ ${linkTags}
448
454
  ${styleLinks}
449
455
  ${shell.head || ""}
450
456
  </head>
@@ -468,6 +474,9 @@ async function renderToStream(element, options) {
468
474
  context: options.context
469
475
  });
470
476
  }
477
+ if (hasDeferredData(loaderData)) {
478
+ loaderData = await resolveAllDeferred(loaderData);
479
+ }
471
480
  const { head, tail } = createShell({ shell, scripts, styles, loaderData });
472
481
  return new Promise((resolve2, reject) => {
473
482
  const { PassThrough } = __require("stream");
@@ -522,6 +531,9 @@ async function renderToString(element, options) {
522
531
  context: options.context
523
532
  });
524
533
  }
534
+ if (hasDeferredData(loaderData)) {
535
+ loaderData = await resolveAllDeferred(loaderData);
536
+ }
525
537
  const { head, tail } = createShell({ shell, scripts, styles, loaderData });
526
538
  const content = reactRenderToString(element);
527
539
  const html = head + content + tail;
@@ -560,8 +572,9 @@ function createSuspenseStream() {
560
572
  }
561
573
 
562
574
  // src/bun-server.ts
563
- import { serializeLoaderData as serializeLoaderData2 } from "@ereo/data";
575
+ import { serializeLoaderData as serializeLoaderData2, hasDeferredData as hasDeferredData2, resolveAllDeferred as resolveAllDeferred2 } from "@ereo/data";
564
576
  import { createElement } from "react";
577
+ import { OutletProvider } from "@ereo/client";
565
578
  async function getStreamingRenderer() {
566
579
  try {
567
580
  const browserServer = await import("react-dom/server.browser");
@@ -679,7 +692,7 @@ class BunServer {
679
692
  if (typeof this.router.loadModule === "function") {
680
693
  await this.router.loadModule(match.route);
681
694
  }
682
- return this.handleRoute(request, { ...match, layouts: [] }, context);
695
+ return this.handleRoute(request, { ...match, layouts: match.layouts || [] }, context);
683
696
  }
684
697
  }
685
698
  if (this.app) {
@@ -713,6 +726,50 @@ class BunServer {
713
726
  if (!module) {
714
727
  return new Response("Route module not loaded", { status: 500 });
715
728
  }
729
+ if (module.middleware && module.middleware.length > 0) {
730
+ return this.executeInlineMiddleware(request, context, module.middleware, () => this.handleRouteInner(request, match, context));
731
+ }
732
+ return this.handleRouteInner(request, match, context);
733
+ }
734
+ async executeInlineMiddleware(request, context, middleware, handler) {
735
+ let index = 0;
736
+ const next = async () => {
737
+ if (index >= middleware.length) {
738
+ return handler();
739
+ }
740
+ const mw = middleware[index++];
741
+ return mw(request, context, next);
742
+ };
743
+ return next();
744
+ }
745
+ async handleRouteInner(request, match, context) {
746
+ const module = match.route.module;
747
+ const httpMethod = request.method.toUpperCase();
748
+ const HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"];
749
+ if (HTTP_METHODS.includes(httpMethod)) {
750
+ const methodHandler = module[httpMethod];
751
+ if (typeof methodHandler === "function") {
752
+ const result = await methodHandler({ request, params: match.params, context });
753
+ if (result instanceof Response) {
754
+ const routeHeaders3 = this.buildRouteHeaders(match);
755
+ return this.applyRouteHeaders(result, routeHeaders3);
756
+ }
757
+ const jsonResponse = new Response(JSON.stringify(result), {
758
+ headers: { "Content-Type": "application/json" }
759
+ });
760
+ const routeHeaders2 = this.buildRouteHeaders(match);
761
+ return this.applyRouteHeaders(jsonResponse, routeHeaders2);
762
+ }
763
+ }
764
+ const layouts = match.layouts || [];
765
+ for (const layout of layouts) {
766
+ if (layout.module?.beforeLoad) {
767
+ await layout.module.beforeLoad({ request, params: match.params, context });
768
+ }
769
+ }
770
+ if (module.beforeLoad) {
771
+ await module.beforeLoad({ request, params: match.params, context });
772
+ }
716
773
  if (request.method !== "GET" && request.method !== "HEAD") {
717
774
  if (module.action) {
718
775
  const result = await module.action({
@@ -721,43 +778,85 @@ class BunServer {
721
778
  context
722
779
  });
723
780
  if (result instanceof Response) {
724
- return result;
781
+ const actionHeaders = new Headers(result.headers);
782
+ const routeHeaders3 = this.buildRouteHeaders(match, actionHeaders);
783
+ return this.applyRouteHeaders(result, routeHeaders3);
725
784
  }
726
- return new Response(JSON.stringify(result), {
785
+ const actionResponse = new Response(JSON.stringify(result), {
727
786
  headers: { "Content-Type": "application/json" }
728
787
  });
788
+ const routeHeaders2 = this.buildRouteHeaders(match);
789
+ return this.applyRouteHeaders(actionResponse, routeHeaders2);
729
790
  }
730
791
  return new Response("Method Not Allowed", { status: 405 });
731
792
  }
732
- let loaderData = null;
733
- if (module.loader) {
734
- loaderData = await module.loader({
735
- request,
736
- params: match.params,
737
- context
738
- });
739
- if (loaderData instanceof Response) {
740
- return loaderData;
793
+ const loaderArgs = { request, params: match.params, context };
794
+ const loaderPromises = [];
795
+ loaderPromises.push(module.loader ? Promise.resolve(module.loader(loaderArgs)) : Promise.resolve(null));
796
+ for (const layout of layouts) {
797
+ loaderPromises.push(layout.module?.loader ? Promise.resolve(layout.module.loader(loaderArgs)) : Promise.resolve(null));
798
+ }
799
+ const loaderResults = await Promise.all(loaderPromises);
800
+ const loaderData = loaderResults[0];
801
+ if (loaderData instanceof Response) {
802
+ return loaderData;
803
+ }
804
+ const layoutLoaderData = new Map;
805
+ for (let i = 0;i < layouts.length; i++) {
806
+ const layoutData = loaderResults[i + 1];
807
+ if (layoutData instanceof Response) {
808
+ return layoutData;
809
+ }
810
+ if (layoutData !== null) {
811
+ layoutLoaderData.set(layouts[i].id, layoutData);
741
812
  }
742
813
  }
814
+ const routeHeaders = this.buildRouteHeaders(match);
743
815
  if (request.headers.get("Accept")?.includes("application/json")) {
744
- return new Response(JSON.stringify({ data: loaderData, params: match.params }), {
816
+ const resolvedLoaderData = hasDeferredData2(loaderData) ? await resolveAllDeferred2(loaderData) : loaderData;
817
+ const jsonPayload = {
818
+ data: resolvedLoaderData,
819
+ params: match.params
820
+ };
821
+ if (layoutLoaderData.size > 0) {
822
+ const layoutDataObj = {};
823
+ for (const [id, data] of layoutLoaderData) {
824
+ layoutDataObj[id] = hasDeferredData2(data) ? await resolveAllDeferred2(data) : data;
825
+ }
826
+ jsonPayload.layoutData = layoutDataObj;
827
+ }
828
+ const module2 = match.route.module;
829
+ const routeLinks = module2?.links ? module2.links() : [];
830
+ const layoutLinksList = (match.layouts || []).flatMap((layout) => layout.module?.links ? layout.module.links() : []);
831
+ const allLinks = [...layoutLinksList, ...routeLinks];
832
+ if (allLinks.length > 0) {
833
+ jsonPayload.links = allLinks;
834
+ }
835
+ const matchesData = this.buildMatchesData(match, loaderData, layoutLoaderData);
836
+ jsonPayload.matches = matchesData;
837
+ const jsonResponse = new Response(JSON.stringify(jsonPayload), {
745
838
  headers: { "Content-Type": "application/json" }
746
839
  });
840
+ return this.applyRouteHeaders(jsonResponse, routeHeaders);
747
841
  }
748
- return this.renderPage(request, match, context, loaderData);
842
+ const htmlResponse = await this.renderPage(request, match, context, loaderData, layoutLoaderData);
843
+ return this.applyRouteHeaders(htmlResponse, routeHeaders);
749
844
  }
750
- async renderPage(request, match, context, loaderData) {
845
+ async renderPage(request, match, context, loaderData, layoutLoaderData = new Map) {
751
846
  const module = match.route.module;
752
847
  if (!module?.default) {
753
848
  return this.renderMinimalPage(match, loaderData);
754
849
  }
755
850
  const url = new URL(request.url);
756
851
  const metaDescriptors = this.buildMeta(module, loaderData, match.params, url);
852
+ const routeLinks = module.links ? module.links() : [];
853
+ const layoutLinks = (match.layouts || []).flatMap((layout) => layout.module?.links ? layout.module.links() : []);
854
+ const allLinks = [...layoutLinks, ...routeLinks];
757
855
  const shell = {
758
856
  ...this.options.shell,
759
857
  title: this.extractTitle(metaDescriptors) || this.options.shell?.title,
760
- meta: this.extractMetaTags(metaDescriptors)
858
+ meta: this.extractMetaTags(metaDescriptors),
859
+ links: allLinks.length > 0 ? allLinks : undefined
761
860
  };
762
861
  const PageComponent = module.default;
763
862
  let element = createElement(PageComponent, {
@@ -769,25 +868,27 @@ class BunServer {
769
868
  const layout = layouts[i];
770
869
  if (layout.module?.default) {
771
870
  const LayoutComponent = layout.module.default;
772
- element = createElement(LayoutComponent, {
773
- loaderData: null,
871
+ const childElement = element;
872
+ element = createElement(OutletProvider, { element: childElement }, createElement(LayoutComponent, {
873
+ loaderData: layoutLoaderData.get(layout.id) ?? null,
774
874
  params: match.params,
775
- children: element
776
- });
875
+ children: childElement
876
+ }));
777
877
  }
778
878
  }
879
+ const allLoaderData = layoutLoaderData.size > 0 ? { __routeData: loaderData, __layoutData: Object.fromEntries(layoutLoaderData) } : loaderData;
779
880
  const hasRootLayout = layouts.length > 0 && layouts[0].module?.default;
780
881
  if (hasRootLayout) {
781
882
  if (this.options.renderMode === "streaming") {
782
- return this.renderStreamingPageDirect(element, loaderData);
883
+ return this.renderStreamingPageDirect(element, allLoaderData);
783
884
  } else {
784
- return this.renderStringPageDirect(element, loaderData);
885
+ return this.renderStringPageDirect(element, allLoaderData);
785
886
  }
786
887
  }
787
888
  if (this.options.renderMode === "streaming") {
788
- return this.renderStreamingPage(element, shell, loaderData);
889
+ return this.renderStreamingPage(element, shell, allLoaderData);
789
890
  } else {
790
- return this.renderStringPage(element, shell, loaderData);
891
+ return this.renderStringPage(element, shell, allLoaderData);
791
892
  }
792
893
  }
793
894
  async renderStreamingPage(element, shell, loaderData) {
@@ -796,38 +897,64 @@ class BunServer {
796
897
  if (!renderToReadableStream) {
797
898
  return this.renderStringPage(element, shell, loaderData);
798
899
  }
900
+ const hasDeferred = hasDeferredData2(loaderData);
799
901
  const scripts = [this.options.clientEntry];
800
- const { head, tail } = createShell({ shell, scripts, loaderData });
902
+ const { head, tail } = createShell({
903
+ shell,
904
+ scripts,
905
+ loaderData: hasDeferred ? null : loaderData
906
+ });
801
907
  const encoder = new TextEncoder;
802
908
  const headBytes = encoder.encode(head);
803
- const tailBytes = encoder.encode(tail);
909
+ const tailBytes = hasDeferred ? null : encoder.encode(tail);
804
910
  const reactStream = await renderToReadableStream(element, {
805
911
  onError(error) {
806
912
  console.error("Streaming render error:", error);
807
913
  }
808
914
  });
809
- await reactStream.allReady;
915
+ const clientEntry = this.options.clientEntry;
810
916
  const reader = reactStream.getReader();
811
- const chunks = [headBytes];
812
- while (true) {
813
- const { done, value } = await reader.read();
814
- if (done)
815
- break;
816
- chunks.push(value);
817
- }
818
- chunks.push(tailBytes);
819
- const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
820
- const fullHtml = new Uint8Array(totalLength);
821
- let offset = 0;
822
- for (const chunk of chunks) {
823
- fullHtml.set(chunk, offset);
824
- offset += chunk.length;
825
- }
826
- return new Response(fullHtml, {
917
+ let phase = "head";
918
+ const stream = new ReadableStream({
919
+ async pull(controller) {
920
+ switch (phase) {
921
+ case "head":
922
+ controller.enqueue(headBytes);
923
+ phase = "body";
924
+ break;
925
+ case "body": {
926
+ const { done, value } = await reader.read();
927
+ if (done) {
928
+ if (hasDeferred) {
929
+ const resolved = await resolveAllDeferred2(loaderData);
930
+ const loaderScript = `<script>window.__EREO_DATA__=${serializeLoaderData2(resolved)}</script>`;
931
+ const scriptTag = `<script type="module" src="${clientEntry}"></script>`;
932
+ const resolvedTail = `</div>
933
+ ${loaderScript}
934
+ ${scriptTag}
935
+ </body>
936
+ </html>`;
937
+ controller.enqueue(encoder.encode(resolvedTail));
938
+ } else {
939
+ controller.enqueue(tailBytes);
940
+ }
941
+ controller.close();
942
+ phase = "done";
943
+ } else {
944
+ controller.enqueue(value);
945
+ }
946
+ break;
947
+ }
948
+ }
949
+ },
950
+ cancel() {
951
+ reader.cancel();
952
+ }
953
+ });
954
+ return new Response(stream, {
827
955
  status: 200,
828
956
  headers: {
829
- "Content-Type": "text/html; charset=utf-8",
830
- "Content-Length": totalLength.toString()
957
+ "Content-Type": "text/html; charset=utf-8"
831
958
  }
832
959
  });
833
960
  } catch (error) {
@@ -838,8 +965,9 @@ class BunServer {
838
965
  async renderStringPage(element, shell, loaderData) {
839
966
  try {
840
967
  const { renderToString: reactRenderToString } = await import("react-dom/server");
968
+ const resolvedData = hasDeferredData2(loaderData) ? await resolveAllDeferred2(loaderData) : loaderData;
841
969
  const scripts = [this.options.clientEntry];
842
- const { head, tail } = createShell({ shell, scripts, loaderData });
970
+ const { head, tail } = createShell({ shell, scripts, loaderData: resolvedData });
843
971
  const content = reactRenderToString(element);
844
972
  const html = head + content + tail;
845
973
  const encoder = new TextEncoder;
@@ -867,32 +995,40 @@ class BunServer {
867
995
  console.error("Streaming render error:", error);
868
996
  }
869
997
  });
870
- await reactStream.allReady;
871
- const reader = reactStream.getReader();
872
- const chunks = [];
873
- while (true) {
874
- const { done, value } = await reader.read();
875
- if (done)
876
- break;
877
- chunks.push(value);
878
- }
879
998
  const encoder = new TextEncoder;
880
- const loaderScript = loaderData ? `<script>window.__EREO_DATA__=${serializeLoaderData2(loaderData)}</script>` : "";
881
- const clientScript = `<script type="module" src="${this.options.clientEntry}"></script>`;
882
- const injectedScripts = encoder.encode(loaderScript + clientScript);
883
- const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0) + injectedScripts.length;
884
- const fullHtml = new Uint8Array(totalLength);
885
- let offset = 0;
886
- for (const chunk of chunks) {
887
- fullHtml.set(chunk, offset);
888
- offset += chunk.length;
889
- }
890
- fullHtml.set(injectedScripts, offset);
891
- return new Response(fullHtml, {
999
+ const hasDeferred = hasDeferredData2(loaderData);
1000
+ const clientEntry = this.options.clientEntry;
1001
+ const injectedScripts = hasDeferred ? null : encoder.encode((loaderData ? `<script>window.__EREO_DATA__=${serializeLoaderData2(loaderData)}</script>` : "") + `<script type="module" src="${clientEntry}"></script>`);
1002
+ const reader = reactStream.getReader();
1003
+ let done = false;
1004
+ const stream = new ReadableStream({
1005
+ async pull(controller) {
1006
+ if (done)
1007
+ return;
1008
+ const result = await reader.read();
1009
+ if (result.done) {
1010
+ if (hasDeferred) {
1011
+ const resolved = await resolveAllDeferred2(loaderData);
1012
+ const loaderScript = resolved ? `<script>window.__EREO_DATA__=${serializeLoaderData2(resolved)}</script>` : "";
1013
+ const clientScript = `<script type="module" src="${clientEntry}"></script>`;
1014
+ controller.enqueue(encoder.encode(loaderScript + clientScript));
1015
+ } else {
1016
+ controller.enqueue(injectedScripts);
1017
+ }
1018
+ controller.close();
1019
+ done = true;
1020
+ } else {
1021
+ controller.enqueue(result.value);
1022
+ }
1023
+ },
1024
+ cancel() {
1025
+ reader.cancel();
1026
+ }
1027
+ });
1028
+ return new Response(stream, {
892
1029
  status: 200,
893
1030
  headers: {
894
- "Content-Type": "text/html; charset=utf-8",
895
- "Content-Length": totalLength.toString()
1031
+ "Content-Type": "text/html; charset=utf-8"
896
1032
  }
897
1033
  });
898
1034
  } catch (error) {
@@ -903,8 +1039,9 @@ class BunServer {
903
1039
  async renderStringPageDirect(element, loaderData) {
904
1040
  try {
905
1041
  const { renderToString: reactRenderToString } = await import("react-dom/server");
1042
+ const resolvedData = hasDeferredData2(loaderData) ? await resolveAllDeferred2(loaderData) : loaderData;
906
1043
  let html = reactRenderToString(element);
907
- const loaderScript = loaderData ? `<script>window.__EREO_DATA__=${serializeLoaderData2(loaderData)}</script>` : "";
1044
+ const loaderScript = resolvedData ? `<script>window.__EREO_DATA__=${serializeLoaderData2(resolvedData)}</script>` : "";
908
1045
  const clientScript = `<script type="module" src="${this.options.clientEntry}"></script>`;
909
1046
  html = html.replace("</body>", `${loaderScript}${clientScript}</body>`);
910
1047
  const encoder = new TextEncoder;
@@ -921,9 +1058,10 @@ class BunServer {
921
1058
  return this.renderErrorPage(error);
922
1059
  }
923
1060
  }
924
- renderMinimalPage(match, loaderData) {
1061
+ async renderMinimalPage(match, loaderData) {
1062
+ const resolvedData = hasDeferredData2(loaderData) ? await resolveAllDeferred2(loaderData) : loaderData;
925
1063
  const serializedData = serializeLoaderData2({
926
- loaderData,
1064
+ loaderData: resolvedData,
927
1065
  params: match.params
928
1066
  });
929
1067
  const html = `<!DOCTYPE html>
@@ -1015,6 +1153,79 @@ class BunServer {
1015
1153
  }
1016
1154
  return tags;
1017
1155
  }
1156
+ buildMatchesData(match, loaderData, layoutLoaderData) {
1157
+ const matches = [];
1158
+ for (const layout of match.layouts || []) {
1159
+ matches.push({
1160
+ id: layout.id,
1161
+ pathname: match.pathname,
1162
+ params: match.params,
1163
+ data: layoutLoaderData.get(layout.id) ?? null,
1164
+ handle: layout.module?.handle ?? undefined
1165
+ });
1166
+ }
1167
+ matches.push({
1168
+ id: match.route.id,
1169
+ pathname: match.pathname,
1170
+ params: match.params,
1171
+ data: loaderData,
1172
+ handle: match.route.module?.handle ?? undefined
1173
+ });
1174
+ return matches;
1175
+ }
1176
+ buildRouteHeaders(match, actionHeaders = new Headers) {
1177
+ const layouts = match.layouts || [];
1178
+ const module = match.route.module;
1179
+ let parentHeaders = new Headers;
1180
+ for (const layout of layouts) {
1181
+ const headersFn = layout.module?.headers;
1182
+ if (headersFn) {
1183
+ try {
1184
+ const result = headersFn({
1185
+ loaderHeaders: new Headers,
1186
+ actionHeaders,
1187
+ parentHeaders
1188
+ });
1189
+ parentHeaders = result instanceof Headers ? result : new Headers(result);
1190
+ } catch (error) {
1191
+ console.error(`Error in layout headers function (${layout.id}):`, error);
1192
+ }
1193
+ }
1194
+ }
1195
+ if (module?.headers) {
1196
+ try {
1197
+ const result = module.headers({
1198
+ loaderHeaders: new Headers,
1199
+ actionHeaders,
1200
+ parentHeaders
1201
+ });
1202
+ return result instanceof Headers ? result : new Headers(result);
1203
+ } catch (error) {
1204
+ console.error("Error in route headers function:", error);
1205
+ }
1206
+ }
1207
+ return parentHeaders;
1208
+ }
1209
+ applyRouteHeaders(response, routeHeaders) {
1210
+ let hasHeaders = false;
1211
+ routeHeaders.forEach(() => {
1212
+ hasHeaders = true;
1213
+ });
1214
+ if (!hasHeaders)
1215
+ return response;
1216
+ const newHeaders = new Headers(response.headers);
1217
+ routeHeaders.forEach((value, key) => {
1218
+ const lower = key.toLowerCase();
1219
+ if (lower === "content-type" || lower === "content-length")
1220
+ return;
1221
+ newHeaders.set(key, value);
1222
+ });
1223
+ return new Response(response.body, {
1224
+ status: response.status,
1225
+ statusText: response.statusText,
1226
+ headers: newHeaders
1227
+ });
1228
+ }
1018
1229
  escapeHtml(str) {
1019
1230
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
1020
1231
  }
@@ -1022,6 +1233,16 @@ class BunServer {
1022
1233
  if (error instanceof Response) {
1023
1234
  return error;
1024
1235
  }
1236
+ if (error instanceof NotFoundError) {
1237
+ return new Response(JSON.stringify({
1238
+ error: "Not Found",
1239
+ status: 404,
1240
+ data: error.data
1241
+ }), {
1242
+ status: 404,
1243
+ headers: { "Content-Type": "application/json" }
1244
+ });
1245
+ }
1025
1246
  const message = error instanceof Error ? error.message : "Internal Server Error";
1026
1247
  const stack = error instanceof Error ? error.stack : undefined;
1027
1248
  console.error("Server error:", error);
@@ -4,7 +4,7 @@
4
4
  * Server-side rendering with streaming support for React 18+.
5
5
  */
6
6
  import type { ReactElement } from 'react';
7
- import type { RouteMatch, AppContext } from '@ereo/core';
7
+ import type { RouteMatch, AppContext, LinkDescriptor } from '@ereo/core';
8
8
  /**
9
9
  * Render options.
10
10
  */
@@ -34,6 +34,8 @@ export interface ShellTemplate {
34
34
  property?: string;
35
35
  content: string;
36
36
  }>;
37
+ /** Link descriptors for stylesheets, preloads, etc. */
38
+ links?: LinkDescriptor[];
37
39
  /** Head content */
38
40
  head?: string;
39
41
  /** Body attributes */
@@ -1 +1 @@
1
- {"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAS,UAAU,EAAE,UAAU,EAAkB,MAAM,YAAY,CAAC;AAGhF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,KAAK,EAAE,UAAU,CAAC;IAClB,sBAAsB;IACtB,OAAO,EAAE,UAAU,CAAC;IACpB,qBAAqB;IACrB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,uBAAuB;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kBAAkB;IAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpE,mBAAmB;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC1C,uBAAuB;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE;IACnC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAmDjC;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAmEvB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CA2BvB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,QAAQ,CAK7D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI;IACtC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACnC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAmBA"}
1
+ {"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAS,UAAU,EAAE,UAAU,EAAkB,cAAc,EAAE,MAAM,YAAY,CAAC;AAGhG;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,KAAK,EAAE,UAAU,CAAC;IAClB,sBAAsB;IACtB,OAAO,EAAE,UAAU,CAAC;IACpB,qBAAqB;IACrB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,uBAAuB;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kBAAkB;IAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpE,uDAAuD;IACvD,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,mBAAmB;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC1C,uBAAuB;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE;IACnC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CA8DjC;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAwEvB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAgCvB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,QAAQ,CAK7D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI;IACtC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACnC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAmBA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ereo/server",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "license": "MIT",
5
5
  "author": "Ereo Team",
6
6
  "homepage": "https://ereo.dev",
@@ -25,16 +25,17 @@
25
25
  "dist"
26
26
  ],
27
27
  "scripts": {
28
- "build": "bun build ./src/index.ts --outdir ./dist --target bun --external @ereo/core --external @ereo/router --external @ereo/data --external react --external react-dom && bun run build:types",
28
+ "build": "bun build ./src/index.ts --outdir ./dist --target bun --external @ereo/core --external @ereo/client --external @ereo/router --external @ereo/data --external react --external react-dom && bun run build:types",
29
29
  "build:types": "tsc --emitDeclarationOnly --outDir dist",
30
30
  "dev": "bun build ./src/index.ts --outdir ./dist --target bun --watch",
31
31
  "test": "bun test",
32
32
  "typecheck": "tsc --noEmit"
33
33
  },
34
34
  "dependencies": {
35
- "@ereo/core": "^0.1.23",
36
- "@ereo/router": "^0.1.23",
37
- "@ereo/data": "^0.1.23"
35
+ "@ereo/core": "^0.1.25",
36
+ "@ereo/client": "^0.1.25",
37
+ "@ereo/router": "^0.1.25",
38
+ "@ereo/data": "^0.1.25"
38
39
  },
39
40
  "devDependencies": {
40
41
  "@types/bun": "^1.1.0",