@ereo/server 0.1.22 → 0.1.24

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":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAClC,OAAO,KAAK,EAAmE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACrH,OAAO,EAAiC,OAAO,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,UAAU,EAAwD,MAAM,cAAc,CAAC;AAChG,OAAO,EAIL,IAAI,EACJ,eAAe,EAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAA+C,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAuD9F;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,qBAAqB;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kBAAkB;IAClB,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,6BAA6B;IAC7B,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7D,wBAAwB;IACxB,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACzD,kBAAkB;IAClB,GAAG,CAAC,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,wFAAwF;IACxF,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,GAAG,CAAwB;IACnC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,aAAa,CAAiE;IACtF,OAAO,CAAC,OAAO,CAAgB;gBAEnB,OAAO,GAAE,aAAkB;IAoBvC;;OAEG;IACH,OAAO,CAAC,eAAe;IAmBvB;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAI1B;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAOnC;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IACrC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI;IASnD;;OAEG;YACW,aAAa;IA0F3B;;OAEG;YACW,sBAAsB;IA2BpC;;OAEG;YACW,WAAW;IAuDzB;;OAEG;YACW,UAAU;IAmExB;;;OAGG;YACW,mBAAmB;IAiEjC;;OAEG;YACW,gBAAgB;IA8B9B;;;OAGG;YACW,yBAAyB;IA+DvC;;OAEG;YACW,sBAAsB;IAgCpC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAgCzB;;OAEG;IACH,OAAO,CAAC,eAAe;IA+BvB;;OAEG;IACH,OAAO,CAAC,SAAS;IA0BjB;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB;;OAEG;IACH,OAAO,CAAC,eAAe;IAcvB;;OAEG;IACH,OAAO,CAAC,UAAU;IASlB;;OAEG;IACH,OAAO,CAAC,WAAW;IA2BnB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IA0BvC;;OAEG;IACH,IAAI,IAAI,IAAI;IAOZ;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ7B;;OAEG;IACH,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI;IAInC;;OAEG;IACH,OAAO,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE;CAOpE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAE/D;AAED;;GAEG;AACH,wBAAsB,KAAK,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAIvE"}
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
@@ -206,7 +206,7 @@ function rateLimit(options = {}) {
206
206
 
207
207
  // src/static.ts
208
208
  import { stat } from "fs/promises";
209
- import { join, extname } from "path";
209
+ import { join, extname, resolve, normalize } from "path";
210
210
  var MIME_TYPES = {
211
211
  ".html": "text/html; charset=utf-8",
212
212
  ".css": "text/css; charset=utf-8",
@@ -295,7 +295,11 @@ function serveStatic(options) {
295
295
  if (pathname.includes("..")) {
296
296
  return new Response("Forbidden", { status: 403 });
297
297
  }
298
- let filepath = join(root, pathname);
298
+ const resolvedRoot = resolve(root);
299
+ let filepath = resolve(root, normalize(pathname.replace(/^\//, "")));
300
+ if (!filepath.startsWith(resolvedRoot)) {
301
+ return new Response("Forbidden", { status: 403 });
302
+ }
299
303
  try {
300
304
  let stats = await stat(filepath);
301
305
  if (negotiateImageFormat && stats.isFile()) {
@@ -418,18 +422,24 @@ function staticMiddleware(options) {
418
422
  }
419
423
 
420
424
  // src/streaming.ts
421
- import { serializeLoaderData } from "@ereo/data";
425
+ import { serializeLoaderData, hasDeferredData, resolveAllDeferred } from "@ereo/data";
422
426
  function createShell(options) {
423
427
  const { shell = {}, scripts = [], styles = [], loaderData } = options;
424
428
  const htmlAttrs = Object.entries(shell.htmlAttrs || {}).map(([k, v]) => `${k}="${v}"`).join(" ");
425
429
  const bodyAttrs = Object.entries(shell.bodyAttrs || {}).map(([k, v]) => `${k}="${v}"`).join(" ");
430
+ const escapeAttr = (s) => s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
426
431
  const metaTags = (shell.meta || []).map((m) => {
427
- const key = m.name ? `name="${m.name}"` : `property="${m.property}"`;
428
- return `<meta ${key} content="${m.content}">`;
432
+ const key = m.name ? `name="${escapeAttr(m.name)}"` : `property="${escapeAttr(m.property || "")}"`;
433
+ return `<meta ${key} content="${escapeAttr(m.content || "")}">`;
429
434
  }).join(`
430
435
  `);
431
436
  const styleLinks = styles.map((href) => `<link rel="stylesheet" href="${href}">`).join(`
432
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
+ `);
433
443
  const scriptTags = scripts.map((src) => `<script type="module" src="${src}"></script>`).join(`
434
444
  `);
435
445
  const loaderScript = loaderData ? `<script>window.__EREO_DATA__=${serializeLoaderData(loaderData)}</script>` : "";
@@ -440,6 +450,7 @@ function createShell(options) {
440
450
  <meta name="viewport" content="width=device-width, initial-scale=1">
441
451
  ${shell.title ? `<title>${shell.title}</title>` : ""}
442
452
  ${metaTags}
453
+ ${linkTags}
443
454
  ${styleLinks}
444
455
  ${shell.head || ""}
445
456
  </head>
@@ -463,8 +474,11 @@ async function renderToStream(element, options) {
463
474
  context: options.context
464
475
  });
465
476
  }
477
+ if (hasDeferredData(loaderData)) {
478
+ loaderData = await resolveAllDeferred(loaderData);
479
+ }
466
480
  const { head, tail } = createShell({ shell, scripts, styles, loaderData });
467
- return new Promise((resolve, reject) => {
481
+ return new Promise((resolve2, reject) => {
468
482
  const { PassThrough } = __require("stream");
469
483
  const { pipe, abort } = renderToPipeableStream(element, {
470
484
  bootstrapScripts: scripts,
@@ -478,7 +492,7 @@ async function renderToStream(element, options) {
478
492
  passThrough.on("end", () => {
479
493
  chunks.push(Buffer.from(tail));
480
494
  const fullHtml = Buffer.concat(chunks).toString("utf-8");
481
- resolve({
495
+ resolve2({
482
496
  body: fullHtml,
483
497
  headers: new Headers({
484
498
  "Content-Type": "text/html; charset=utf-8",
@@ -517,6 +531,9 @@ async function renderToString(element, options) {
517
531
  context: options.context
518
532
  });
519
533
  }
534
+ if (hasDeferredData(loaderData)) {
535
+ loaderData = await resolveAllDeferred(loaderData);
536
+ }
520
537
  const { head, tail } = createShell({ shell, scripts, styles, loaderData });
521
538
  const content = reactRenderToString(element);
522
539
  const html = head + content + tail;
@@ -555,8 +572,9 @@ function createSuspenseStream() {
555
572
  }
556
573
 
557
574
  // src/bun-server.ts
558
- import { serializeLoaderData as serializeLoaderData2 } from "@ereo/data";
575
+ import { serializeLoaderData as serializeLoaderData2, hasDeferredData as hasDeferredData2, resolveAllDeferred as resolveAllDeferred2 } from "@ereo/data";
559
576
  import { createElement } from "react";
577
+ import { OutletProvider } from "@ereo/client";
560
578
  async function getStreamingRenderer() {
561
579
  try {
562
580
  const browserServer = await import("react-dom/server.browser");
@@ -674,7 +692,7 @@ class BunServer {
674
692
  if (typeof this.router.loadModule === "function") {
675
693
  await this.router.loadModule(match.route);
676
694
  }
677
- return this.handleRoute(request, { ...match, layouts: [] }, context);
695
+ return this.handleRoute(request, { ...match, layouts: match.layouts || [] }, context);
678
696
  }
679
697
  }
680
698
  if (this.app) {
@@ -708,6 +726,50 @@ class BunServer {
708
726
  if (!module) {
709
727
  return new Response("Route module not loaded", { status: 500 });
710
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
+ }
711
773
  if (request.method !== "GET" && request.method !== "HEAD") {
712
774
  if (module.action) {
713
775
  const result = await module.action({
@@ -716,43 +778,85 @@ class BunServer {
716
778
  context
717
779
  });
718
780
  if (result instanceof Response) {
719
- return result;
781
+ const actionHeaders = new Headers(result.headers);
782
+ const routeHeaders3 = this.buildRouteHeaders(match, actionHeaders);
783
+ return this.applyRouteHeaders(result, routeHeaders3);
720
784
  }
721
- return new Response(JSON.stringify(result), {
785
+ const actionResponse = new Response(JSON.stringify(result), {
722
786
  headers: { "Content-Type": "application/json" }
723
787
  });
788
+ const routeHeaders2 = this.buildRouteHeaders(match);
789
+ return this.applyRouteHeaders(actionResponse, routeHeaders2);
724
790
  }
725
791
  return new Response("Method Not Allowed", { status: 405 });
726
792
  }
727
- let loaderData = null;
728
- if (module.loader) {
729
- loaderData = await module.loader({
730
- request,
731
- params: match.params,
732
- context
733
- });
734
- if (loaderData instanceof Response) {
735
- 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);
736
812
  }
737
813
  }
814
+ const routeHeaders = this.buildRouteHeaders(match);
738
815
  if (request.headers.get("Accept")?.includes("application/json")) {
739
- 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), {
740
838
  headers: { "Content-Type": "application/json" }
741
839
  });
840
+ return this.applyRouteHeaders(jsonResponse, routeHeaders);
742
841
  }
743
- return this.renderPage(request, match, context, loaderData);
842
+ const htmlResponse = await this.renderPage(request, match, context, loaderData, layoutLoaderData);
843
+ return this.applyRouteHeaders(htmlResponse, routeHeaders);
744
844
  }
745
- async renderPage(request, match, context, loaderData) {
845
+ async renderPage(request, match, context, loaderData, layoutLoaderData = new Map) {
746
846
  const module = match.route.module;
747
847
  if (!module?.default) {
748
848
  return this.renderMinimalPage(match, loaderData);
749
849
  }
750
850
  const url = new URL(request.url);
751
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];
752
855
  const shell = {
753
856
  ...this.options.shell,
754
857
  title: this.extractTitle(metaDescriptors) || this.options.shell?.title,
755
- meta: this.extractMetaTags(metaDescriptors)
858
+ meta: this.extractMetaTags(metaDescriptors),
859
+ links: allLinks.length > 0 ? allLinks : undefined
756
860
  };
757
861
  const PageComponent = module.default;
758
862
  let element = createElement(PageComponent, {
@@ -764,25 +868,27 @@ class BunServer {
764
868
  const layout = layouts[i];
765
869
  if (layout.module?.default) {
766
870
  const LayoutComponent = layout.module.default;
767
- element = createElement(LayoutComponent, {
768
- loaderData: null,
871
+ const childElement = element;
872
+ element = createElement(OutletProvider, { element: childElement }, createElement(LayoutComponent, {
873
+ loaderData: layoutLoaderData.get(layout.id) ?? null,
769
874
  params: match.params,
770
- children: element
771
- });
875
+ children: childElement
876
+ }));
772
877
  }
773
878
  }
879
+ const allLoaderData = layoutLoaderData.size > 0 ? { __routeData: loaderData, __layoutData: Object.fromEntries(layoutLoaderData) } : loaderData;
774
880
  const hasRootLayout = layouts.length > 0 && layouts[0].module?.default;
775
881
  if (hasRootLayout) {
776
882
  if (this.options.renderMode === "streaming") {
777
- return this.renderStreamingPageDirect(element, loaderData);
883
+ return this.renderStreamingPageDirect(element, allLoaderData);
778
884
  } else {
779
- return this.renderStringPageDirect(element, loaderData);
885
+ return this.renderStringPageDirect(element, allLoaderData);
780
886
  }
781
887
  }
782
888
  if (this.options.renderMode === "streaming") {
783
- return this.renderStreamingPage(element, shell, loaderData);
889
+ return this.renderStreamingPage(element, shell, allLoaderData);
784
890
  } else {
785
- return this.renderStringPage(element, shell, loaderData);
891
+ return this.renderStringPage(element, shell, allLoaderData);
786
892
  }
787
893
  }
788
894
  async renderStreamingPage(element, shell, loaderData) {
@@ -791,38 +897,64 @@ class BunServer {
791
897
  if (!renderToReadableStream) {
792
898
  return this.renderStringPage(element, shell, loaderData);
793
899
  }
900
+ const hasDeferred = hasDeferredData2(loaderData);
794
901
  const scripts = [this.options.clientEntry];
795
- const { head, tail } = createShell({ shell, scripts, loaderData });
902
+ const { head, tail } = createShell({
903
+ shell,
904
+ scripts,
905
+ loaderData: hasDeferred ? null : loaderData
906
+ });
796
907
  const encoder = new TextEncoder;
797
908
  const headBytes = encoder.encode(head);
798
- const tailBytes = encoder.encode(tail);
909
+ const tailBytes = hasDeferred ? null : encoder.encode(tail);
799
910
  const reactStream = await renderToReadableStream(element, {
800
911
  onError(error) {
801
912
  console.error("Streaming render error:", error);
802
913
  }
803
914
  });
804
- await reactStream.allReady;
915
+ const clientEntry = this.options.clientEntry;
805
916
  const reader = reactStream.getReader();
806
- const chunks = [headBytes];
807
- while (true) {
808
- const { done, value } = await reader.read();
809
- if (done)
810
- break;
811
- chunks.push(value);
812
- }
813
- chunks.push(tailBytes);
814
- const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
815
- const fullHtml = new Uint8Array(totalLength);
816
- let offset = 0;
817
- for (const chunk of chunks) {
818
- fullHtml.set(chunk, offset);
819
- offset += chunk.length;
820
- }
821
- 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, {
822
955
  status: 200,
823
956
  headers: {
824
- "Content-Type": "text/html; charset=utf-8",
825
- "Content-Length": totalLength.toString()
957
+ "Content-Type": "text/html; charset=utf-8"
826
958
  }
827
959
  });
828
960
  } catch (error) {
@@ -833,8 +965,9 @@ class BunServer {
833
965
  async renderStringPage(element, shell, loaderData) {
834
966
  try {
835
967
  const { renderToString: reactRenderToString } = await import("react-dom/server");
968
+ const resolvedData = hasDeferredData2(loaderData) ? await resolveAllDeferred2(loaderData) : loaderData;
836
969
  const scripts = [this.options.clientEntry];
837
- const { head, tail } = createShell({ shell, scripts, loaderData });
970
+ const { head, tail } = createShell({ shell, scripts, loaderData: resolvedData });
838
971
  const content = reactRenderToString(element);
839
972
  const html = head + content + tail;
840
973
  const encoder = new TextEncoder;
@@ -862,32 +995,40 @@ class BunServer {
862
995
  console.error("Streaming render error:", error);
863
996
  }
864
997
  });
865
- await reactStream.allReady;
866
- const reader = reactStream.getReader();
867
- const chunks = [];
868
- while (true) {
869
- const { done, value } = await reader.read();
870
- if (done)
871
- break;
872
- chunks.push(value);
873
- }
874
998
  const encoder = new TextEncoder;
875
- const loaderScript = loaderData ? `<script>window.__EREO_DATA__=${serializeLoaderData2(loaderData)}</script>` : "";
876
- const clientScript = `<script type="module" src="${this.options.clientEntry}"></script>`;
877
- const injectedScripts = encoder.encode(loaderScript + clientScript);
878
- const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0) + injectedScripts.length;
879
- const fullHtml = new Uint8Array(totalLength);
880
- let offset = 0;
881
- for (const chunk of chunks) {
882
- fullHtml.set(chunk, offset);
883
- offset += chunk.length;
884
- }
885
- fullHtml.set(injectedScripts, offset);
886
- 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, {
887
1029
  status: 200,
888
1030
  headers: {
889
- "Content-Type": "text/html; charset=utf-8",
890
- "Content-Length": totalLength.toString()
1031
+ "Content-Type": "text/html; charset=utf-8"
891
1032
  }
892
1033
  });
893
1034
  } catch (error) {
@@ -898,8 +1039,9 @@ class BunServer {
898
1039
  async renderStringPageDirect(element, loaderData) {
899
1040
  try {
900
1041
  const { renderToString: reactRenderToString } = await import("react-dom/server");
1042
+ const resolvedData = hasDeferredData2(loaderData) ? await resolveAllDeferred2(loaderData) : loaderData;
901
1043
  let html = reactRenderToString(element);
902
- const loaderScript = loaderData ? `<script>window.__EREO_DATA__=${serializeLoaderData2(loaderData)}</script>` : "";
1044
+ const loaderScript = resolvedData ? `<script>window.__EREO_DATA__=${serializeLoaderData2(resolvedData)}</script>` : "";
903
1045
  const clientScript = `<script type="module" src="${this.options.clientEntry}"></script>`;
904
1046
  html = html.replace("</body>", `${loaderScript}${clientScript}</body>`);
905
1047
  const encoder = new TextEncoder;
@@ -916,9 +1058,10 @@ class BunServer {
916
1058
  return this.renderErrorPage(error);
917
1059
  }
918
1060
  }
919
- renderMinimalPage(match, loaderData) {
1061
+ async renderMinimalPage(match, loaderData) {
1062
+ const resolvedData = hasDeferredData2(loaderData) ? await resolveAllDeferred2(loaderData) : loaderData;
920
1063
  const serializedData = serializeLoaderData2({
921
- loaderData,
1064
+ loaderData: resolvedData,
922
1065
  params: match.params
923
1066
  });
924
1067
  const html = `<!DOCTYPE html>
@@ -1010,6 +1153,79 @@ class BunServer {
1010
1153
  }
1011
1154
  return tags;
1012
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
+ }
1013
1229
  escapeHtml(str) {
1014
1230
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
1015
1231
  }
@@ -1017,6 +1233,16 @@ class BunServer {
1017
1233
  if (error instanceof Response) {
1018
1234
  return error;
1019
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
+ }
1020
1246
  const message = error instanceof Error ? error.message : "Internal Server Error";
1021
1247
  const stack = error instanceof Error ? error.stack : undefined;
1022
1248
  console.error("Server error:", error);
@@ -1037,7 +1263,16 @@ class BunServer {
1037
1263
  const serverOptions = {
1038
1264
  port,
1039
1265
  hostname,
1040
- fetch: (request) => this.handleRequest(request),
1266
+ fetch: (request, server) => {
1267
+ if (websocket) {
1268
+ const url = new URL(request.url);
1269
+ if (url.pathname === "/__hmr") {
1270
+ if (server.upgrade(request, { data: {} }))
1271
+ return;
1272
+ }
1273
+ }
1274
+ return this.handleRequest(request);
1275
+ },
1041
1276
  error: (error) => this.handleError(error, {})
1042
1277
  };
1043
1278
  if (tls) {
@@ -1 +1 @@
1
- {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../src/static.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAuCH;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAwDD;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA6IlG;AA6CD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,IAGvC,SAAS,OAAO,EAAE,SAAS,GAAG,EAAE,MAAM,MAAM,OAAO,CAAC,QAAQ,CAAC,uBAK5E"}
1
+ {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../src/static.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAuCH;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAwDD;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAkJlG;AA6CD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,IAGvC,SAAS,OAAO,EAAE,SAAS,GAAG,EAAE,MAAM,MAAM,OAAO,CAAC,QAAQ,CAAC,uBAK5E"}
@@ -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,CAkDjC;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.22",
3
+ "version": "0.1.24",
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.22",
36
- "@ereo/router": "^0.1.22",
37
- "@ereo/data": "^0.1.22"
35
+ "@ereo/core": "^0.1.24",
36
+ "@ereo/client": "^0.1.24",
37
+ "@ereo/router": "^0.1.24",
38
+ "@ereo/data": "^0.1.24"
38
39
  },
39
40
  "devDependencies": {
40
41
  "@types/bun": "^1.1.0",