@ereo/server 0.2.25 → 0.2.28

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.
@@ -60,6 +60,20 @@ export interface ServerOptions {
60
60
  middleware: MiddlewareHandler;
61
61
  viewerHandler?: (req: Request) => Response;
62
62
  tracesAPIHandler?: (req: Request) => Response;
63
+ /** WebSocket handler for live trace streaming */
64
+ traceWebSocket?: {
65
+ websocket: {
66
+ open: (ws: any) => void;
67
+ close: (ws: any) => void;
68
+ message: (ws: any, message: string | Buffer) => void;
69
+ };
70
+ };
71
+ /** Auto-instrumentation functions from @ereo/trace */
72
+ instrumentors?: {
73
+ getActiveSpan: (ctx: any) => any;
74
+ traceRouteMatch: <T>(span: any, fn: () => T) => T;
75
+ traceLoader: <T>(span: any, key: string, fn: () => T | Promise<T>) => T | Promise<T>;
76
+ };
63
77
  };
64
78
  }
65
79
  /**
@@ -91,6 +105,10 @@ export declare class BunServer {
91
105
  */
92
106
  use(handler: MiddlewareHandler): void;
93
107
  use(path: string, handler: MiddlewareHandler): void;
108
+ /** Get auto-instrumentation helpers if tracing is enabled */
109
+ private get traceInstrumentors();
110
+ /** Generate a <script> tag to inject the trace ID into the page for client tracing */
111
+ private getTraceIdScript;
94
112
  /**
95
113
  * Register a WebSocket upgrade handler for a specific path.
96
114
  * Plugins can use this to add WebSocket support alongside HMR.
@@ -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
@@ -746,6 +746,21 @@ class BunServer {
746
746
  this.middleware.use(pathOrHandler, maybeHandler);
747
747
  }
748
748
  }
749
+ get traceInstrumentors() {
750
+ if (this.options.trace && typeof this.options.trace === "object" && this.options.trace.instrumentors) {
751
+ return this.options.trace.instrumentors;
752
+ }
753
+ return null;
754
+ }
755
+ getTraceIdScript(context) {
756
+ const inst = this.traceInstrumentors;
757
+ if (!inst)
758
+ return "";
759
+ const span = inst.getActiveSpan(context);
760
+ if (!span?.traceId)
761
+ return "";
762
+ return `<script>window.__EREO_TRACE_ID__="${span.traceId}"</script>`;
763
+ }
749
764
  addWebSocketUpgrade(path, upgrader, wsConfig) {
750
765
  this.wsUpgradeHandlers.push({ path, upgrader, wsConfig });
751
766
  }
@@ -788,7 +803,9 @@ class BunServer {
788
803
  const pathname = new URL(request.url).pathname;
789
804
  if (typeof this.router.getRoutes === "function") {
790
805
  const routes = this.router.getRoutes();
791
- const matchResult = matchWithLayouts(pathname, routes);
806
+ const inst = this.traceInstrumentors;
807
+ const activeSpan = inst?.getActiveSpan(context);
808
+ const matchResult = activeSpan ? inst.traceRouteMatch(activeSpan, () => matchWithLayouts(pathname, routes)) : matchWithLayouts(pathname, routes);
792
809
  if (!matchResult) {
793
810
  return new Response("Not Found", { status: 404 });
794
811
  }
@@ -942,10 +959,22 @@ class BunServer {
942
959
  return new Response("Method Not Allowed", { status: 405 });
943
960
  }
944
961
  const loaderArgs = { request, params: match.params, context };
962
+ const inst = this.traceInstrumentors;
963
+ const activeSpan = inst?.getActiveSpan(context);
945
964
  const loaderPromises = [];
946
- loaderPromises.push(module.loader ? Promise.resolve(module.loader(loaderArgs)) : Promise.resolve(null));
965
+ if (module.loader) {
966
+ const loaderFn = () => module.loader(loaderArgs);
967
+ loaderPromises.push(activeSpan ? Promise.resolve(inst.traceLoader(activeSpan, match.route.id || "route", loaderFn)) : Promise.resolve(loaderFn()));
968
+ } else {
969
+ loaderPromises.push(Promise.resolve(null));
970
+ }
947
971
  for (const layout of layouts) {
948
- loaderPromises.push(layout.module?.loader ? Promise.resolve(layout.module.loader(loaderArgs)) : Promise.resolve(null));
972
+ if (layout.module?.loader) {
973
+ const layoutLoaderFn = () => layout.module.loader(loaderArgs);
974
+ loaderPromises.push(activeSpan ? Promise.resolve(inst.traceLoader(activeSpan, `layout:${layout.id}`, layoutLoaderFn)) : Promise.resolve(layoutLoaderFn()));
975
+ } else {
976
+ loaderPromises.push(Promise.resolve(null));
977
+ }
949
978
  }
950
979
  let loaderResults;
951
980
  try {
@@ -1005,13 +1034,27 @@ class BunServer {
1005
1034
  });
1006
1035
  return this.applyRouteHeaders(jsonResponse, routeHeaders);
1007
1036
  }
1008
- const htmlResponse = await this.renderPage(request, match, context, loaderData, layoutLoaderData);
1037
+ let htmlResponse;
1038
+ if (activeSpan) {
1039
+ const renderSpan = activeSpan.child("render", "custom");
1040
+ try {
1041
+ htmlResponse = await this.renderPage(request, match, context, loaderData, layoutLoaderData);
1042
+ renderSpan.end();
1043
+ } catch (err) {
1044
+ renderSpan.error(err);
1045
+ renderSpan.end();
1046
+ throw err;
1047
+ }
1048
+ } else {
1049
+ htmlResponse = await this.renderPage(request, match, context, loaderData, layoutLoaderData);
1050
+ }
1009
1051
  return this.applyRouteHeaders(htmlResponse, routeHeaders);
1010
1052
  }
1011
1053
  async renderPage(request, match, context, loaderData, layoutLoaderData = new Map, actionData) {
1054
+ const traceScript = this.getTraceIdScript(context);
1012
1055
  const module = match.route.module;
1013
1056
  if (!module?.default) {
1014
- return this.renderMinimalPage(match, loaderData);
1057
+ return this.renderMinimalPage(match, loaderData, traceScript);
1015
1058
  }
1016
1059
  const url = new URL(request.url);
1017
1060
  const metaDescriptors = this.buildMeta(module, loaderData, match.params, url);
@@ -1054,23 +1097,23 @@ class BunServer {
1054
1097
  const hasRootLayout = layouts.length > 0 && layouts[0].module?.default;
1055
1098
  if (hasRootLayout) {
1056
1099
  if (this.options.renderMode === "streaming") {
1057
- return this.renderStreamingPageDirect(element, allLoaderData, metaDescriptors);
1100
+ return this.renderStreamingPageDirect(element, allLoaderData, metaDescriptors, traceScript);
1058
1101
  } else {
1059
- return this.renderStringPageDirect(element, allLoaderData, metaDescriptors);
1102
+ return this.renderStringPageDirect(element, allLoaderData, metaDescriptors, traceScript);
1060
1103
  }
1061
1104
  }
1062
1105
  if (this.options.renderMode === "streaming") {
1063
- return this.renderStreamingPage(element, shell, allLoaderData);
1106
+ return this.renderStreamingPage(element, shell, allLoaderData, traceScript);
1064
1107
  } else {
1065
- return this.renderStringPage(element, shell, allLoaderData);
1108
+ return this.renderStringPage(element, shell, allLoaderData, traceScript);
1066
1109
  }
1067
1110
  }
1068
- async renderStreamingPage(element, shell, loaderData) {
1111
+ async renderStreamingPage(element, shell, loaderData, traceScript = "") {
1069
1112
  let timeoutId;
1070
1113
  try {
1071
1114
  const { renderToReadableStream } = await getStreamingRenderer();
1072
1115
  if (!renderToReadableStream) {
1073
- return this.renderStringPage(element, shell, loaderData);
1116
+ return this.renderStringPage(element, shell, loaderData, traceScript);
1074
1117
  }
1075
1118
  const hasDeferred = hasDeferredData2(loaderData);
1076
1119
  const clientEntry = this.options.clientEntry;
@@ -1114,7 +1157,7 @@ class BunServer {
1114
1157
  console.error("Deferred data resolution failed:", error);
1115
1158
  resolvedData = null;
1116
1159
  }
1117
- const loaderScript = `<script>window.__EREO_DATA__=${serializeLoaderData2(resolvedData)}</script>`;
1160
+ const loaderScript = `${traceScript}<script>window.__EREO_DATA__=${serializeLoaderData2(resolvedData)}</script>`;
1118
1161
  const resolvedTail = `</div>
1119
1162
  ${loaderScript}
1120
1163
  </body>
@@ -1147,17 +1190,17 @@ class BunServer {
1147
1190
  } catch (error) {
1148
1191
  clearTimeout(timeoutId);
1149
1192
  console.error("Streaming render failed:", error);
1150
- return this.renderStringPage(element, shell, loaderData);
1193
+ return this.renderStringPage(element, shell, loaderData, traceScript);
1151
1194
  }
1152
1195
  }
1153
- async renderStringPage(element, shell, loaderData) {
1196
+ async renderStringPage(element, shell, loaderData, traceScript = "") {
1154
1197
  try {
1155
1198
  const { renderToString: reactRenderToString } = await import("react-dom/server");
1156
1199
  const resolvedData = hasDeferredData2(loaderData) ? await resolveAllDeferred2(loaderData) : loaderData;
1157
1200
  const scripts = [this.options.clientEntry];
1158
1201
  const { head, tail } = createShell({ shell, scripts, loaderData: resolvedData });
1159
1202
  const content = reactRenderToString(element);
1160
- const html = head + content + tail;
1203
+ const html = head + content + (traceScript ? tail.replace("</body>", `${traceScript}</body>`) : tail);
1161
1204
  const encoder = new TextEncoder;
1162
1205
  const htmlBytes = encoder.encode(html);
1163
1206
  return new Response(htmlBytes, {
@@ -1172,12 +1215,12 @@ class BunServer {
1172
1215
  return this.renderErrorPage(error);
1173
1216
  }
1174
1217
  }
1175
- async renderStreamingPageDirect(element, loaderData, metaDescriptors = []) {
1218
+ async renderStreamingPageDirect(element, loaderData, metaDescriptors = [], traceScript = "") {
1176
1219
  let timeoutId;
1177
1220
  try {
1178
1221
  const { renderToReadableStream } = await getStreamingRenderer();
1179
1222
  if (!renderToReadableStream) {
1180
- return this.renderStringPageDirect(element, loaderData, metaDescriptors);
1223
+ return this.renderStringPageDirect(element, loaderData, metaDescriptors, traceScript);
1181
1224
  }
1182
1225
  const hasDeferred = hasDeferredData2(loaderData);
1183
1226
  const clientEntry = this.options.clientEntry;
@@ -1191,7 +1234,7 @@ class BunServer {
1191
1234
  console.error("Streaming render error:", error);
1192
1235
  }
1193
1236
  });
1194
- const loaderScript = !hasDeferred && loaderData ? encoder.encode(`<script>window.__EREO_DATA__=${serializeLoaderData2(loaderData)}</script>`) : null;
1237
+ const loaderScript = !hasDeferred && loaderData ? encoder.encode(`${traceScript}<script>window.__EREO_DATA__=${serializeLoaderData2(loaderData)}</script>`) : traceScript ? encoder.encode(traceScript) : null;
1195
1238
  const metaHtml = metaDescriptors.length > 0 ? this.buildMetaHtml(metaDescriptors) : "";
1196
1239
  let metaInjected = metaHtml.length === 0;
1197
1240
  const decoder = new TextDecoder;
@@ -1215,7 +1258,7 @@ class BunServer {
1215
1258
  console.error("Deferred data resolution failed:", error);
1216
1259
  resolvedData = null;
1217
1260
  }
1218
- controller.enqueue(encoder.encode(`<script>window.__EREO_DATA__=${serializeLoaderData2(resolvedData)}</script>`));
1261
+ controller.enqueue(encoder.encode(`${traceScript}<script>window.__EREO_DATA__=${serializeLoaderData2(resolvedData)}</script>`));
1219
1262
  } else if (loaderScript) {
1220
1263
  controller.enqueue(loaderScript);
1221
1264
  }
@@ -1249,10 +1292,10 @@ class BunServer {
1249
1292
  } catch (error) {
1250
1293
  clearTimeout(timeoutId);
1251
1294
  console.error("Streaming render failed:", error);
1252
- return this.renderStringPageDirect(element, loaderData, metaDescriptors);
1295
+ return this.renderStringPageDirect(element, loaderData, metaDescriptors, traceScript);
1253
1296
  }
1254
1297
  }
1255
- async renderStringPageDirect(element, loaderData, metaDescriptors = []) {
1298
+ async renderStringPageDirect(element, loaderData, metaDescriptors = [], traceScript = "") {
1256
1299
  try {
1257
1300
  const { renderToString: reactRenderToString } = await import("react-dom/server");
1258
1301
  const resolvedData = hasDeferredData2(loaderData) ? await resolveAllDeferred2(loaderData) : loaderData;
@@ -1260,7 +1303,7 @@ class BunServer {
1260
1303
  if (metaDescriptors.length > 0) {
1261
1304
  html = this.injectMetaIntoHtml(html, metaDescriptors);
1262
1305
  }
1263
- const loaderScript = resolvedData ? `<script>window.__EREO_DATA__=${serializeLoaderData2(resolvedData)}</script>` : "";
1306
+ const loaderScript = resolvedData ? `${traceScript}<script>window.__EREO_DATA__=${serializeLoaderData2(resolvedData)}</script>` : traceScript;
1264
1307
  const clientScript = `<script type="module" src="${this.options.clientEntry}"></script>`;
1265
1308
  if (html.includes("</body>")) {
1266
1309
  html = html.replace("</body>", `${loaderScript}${clientScript}</body>`);
@@ -1281,7 +1324,7 @@ class BunServer {
1281
1324
  return this.renderErrorPage(error);
1282
1325
  }
1283
1326
  }
1284
- async renderMinimalPage(match, loaderData) {
1327
+ async renderMinimalPage(match, loaderData, traceScript = "") {
1285
1328
  const resolvedData = hasDeferredData2(loaderData) ? await resolveAllDeferred2(loaderData) : loaderData;
1286
1329
  const serializedData = serializeLoaderData2({
1287
1330
  loaderData: resolvedData,
@@ -1296,7 +1339,7 @@ class BunServer {
1296
1339
  </head>
1297
1340
  <body>
1298
1341
  <div id="root"></div>
1299
- <script>window.__EREO_DATA__=${serializedData}</script>
1342
+ ${traceScript}<script>window.__EREO_DATA__=${serializedData}</script>
1300
1343
  <script type="module" src="${this.options.clientEntry}"></script>
1301
1344
  </body>
1302
1345
  </html>`;
@@ -1626,6 +1669,18 @@ class BunServer {
1626
1669
  if (server.upgrade(request, { data: { _wsType: "hmr" } }))
1627
1670
  return;
1628
1671
  }
1672
+ if (url.pathname === "/__ereo/trace-ws" && typeof this.options.trace === "object" && this.options.trace.traceWebSocket) {
1673
+ const traceWsType = "__ereo_trace_ws";
1674
+ if (!upgradeHandlers.some((h) => h.path === traceWsType)) {
1675
+ upgradeHandlers.push({
1676
+ path: traceWsType,
1677
+ upgrader: () => true,
1678
+ wsConfig: this.options.trace.traceWebSocket.websocket
1679
+ });
1680
+ }
1681
+ if (server.upgrade(request, { data: { _wsType: traceWsType } }))
1682
+ return;
1683
+ }
1629
1684
  const upgradeHeader = request.headers.get("Upgrade");
1630
1685
  if (upgradeHeader?.toLowerCase() === "websocket") {
1631
1686
  for (const handler of upgradeHandlers) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ereo/server",
3
- "version": "0.2.25",
3
+ "version": "0.2.28",
4
4
  "license": "MIT",
5
5
  "author": "Ereo Team",
6
6
  "homepage": "https://ereojs.github.io/ereoJS",
@@ -32,10 +32,10 @@
32
32
  "typecheck": "tsc --noEmit"
33
33
  },
34
34
  "dependencies": {
35
- "@ereo/core": "^0.2.25",
36
- "@ereo/client": "^0.2.25",
37
- "@ereo/router": "^0.2.25",
38
- "@ereo/data": "^0.2.25"
35
+ "@ereo/core": "^0.2.28",
36
+ "@ereo/client": "^0.2.28",
37
+ "@ereo/router": "^0.2.28",
38
+ "@ereo/data": "^0.2.28"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/bun": "^1.1.0",