@webtypen/webframez-react 0.0.32 → 0.0.34

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/dist/index.cjs CHANGED
@@ -147,6 +147,7 @@ function sendRSC(res, model, options = {}) {
147
147
  } = options;
148
148
  res.statusCode = statusCode;
149
149
  res.setHeader("Content-Type", contentType);
150
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
150
151
  const stream = (0, import_server.renderToPipeableStream)(model, moduleMap, { onError });
151
152
  stream.pipe(res);
152
153
  return stream;
@@ -184,6 +185,7 @@ function createRSCHandler(options) {
184
185
  var import_node_fs = __toESM(require("node:fs"), 1);
185
186
  var import_node_module2 = __toESM(require("node:module"), 1);
186
187
  var import_node_path2 = __toESM(require("node:path"), 1);
188
+ var import_route_slot = require("@webtypen/webframez-react/route-slot");
187
189
 
188
190
  // src/head.ts
189
191
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
@@ -273,6 +275,16 @@ function isRouteChildrenType(type) {
273
275
  return false;
274
276
  }
275
277
  }
278
+ function isReactElementLike(node) {
279
+ if (!node || typeof node !== "object") {
280
+ return false;
281
+ }
282
+ try {
283
+ return "type" in node && "props" in node;
284
+ } catch {
285
+ return false;
286
+ }
287
+ }
276
288
  function injectRouteChildren(node, routeChildren) {
277
289
  if (node === null || node === void 0 || typeof node === "boolean") {
278
290
  return node;
@@ -288,13 +300,17 @@ function injectRouteChildren(node, routeChildren) {
288
300
  });
289
301
  return changed ? next : node;
290
302
  }
291
- if (!import_react.default.isValidElement(node)) {
303
+ if (isReactElementLike(node) && isRouteChildrenType(node.type)) {
304
+ return routeChildren;
305
+ }
306
+ const isValidElement = import_react.default.isValidElement(node);
307
+ if (!isValidElement && !isReactElementLike(node)) {
292
308
  return node;
293
309
  }
294
- if (isRouteChildrenType(node.type)) {
310
+ if (isValidElement && isRouteChildrenType(node.type)) {
295
311
  return routeChildren;
296
312
  }
297
- const props = node.props;
313
+ const props = node.props ?? {};
298
314
  if (!("children" in props)) {
299
315
  return node;
300
316
  }
@@ -302,10 +318,19 @@ function injectRouteChildren(node, routeChildren) {
302
318
  if (nextChildren === props.children) {
303
319
  return node;
304
320
  }
305
- if (Array.isArray(nextChildren)) {
306
- return import_react.default.cloneElement(node, void 0, ...nextChildren);
321
+ if (isValidElement) {
322
+ if (Array.isArray(nextChildren)) {
323
+ return import_react.default.cloneElement(node, void 0, ...nextChildren);
324
+ }
325
+ return import_react.default.cloneElement(node, void 0, nextChildren);
307
326
  }
308
- return import_react.default.cloneElement(node, void 0, nextChildren);
327
+ const elementLike = node;
328
+ const nextProps = {
329
+ ...elementLike.props ?? {},
330
+ children: nextChildren,
331
+ ...elementLike.key !== void 0 && elementLike.key !== null ? { key: elementLike.key } : {}
332
+ };
333
+ return import_react.default.createElement(elementLike.type, nextProps);
309
334
  }
310
335
 
311
336
  // src/file-router.tsx
@@ -646,9 +671,12 @@ function createFileRouter(options) {
646
671
  const errorHead = await resolveHead(errorModule, errorProps);
647
672
  const layoutNode = layoutModule ? await layoutModule.default(context) : null;
648
673
  const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
674
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_route_slot.RouteChildrenSlot, {})) : void 0;
649
675
  return {
650
676
  statusCode,
651
677
  model,
678
+ contextModel,
679
+ pageModel: errorNode,
652
680
  head: mergeHead(layoutHead, errorHead)
653
681
  };
654
682
  }
@@ -768,9 +796,12 @@ function createFileRouter(options) {
768
796
  const pageHead = await resolveHead(pageModule, pageContext);
769
797
  const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
770
798
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
799
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_route_slot.RouteChildrenSlot, {})) : void 0;
771
800
  return {
772
801
  statusCode: 200,
773
802
  model,
803
+ contextModel,
804
+ pageModel: pageNode,
774
805
  head: mergeHead(layoutHead, pageHead)
775
806
  };
776
807
  } catch (error) {
@@ -954,7 +985,21 @@ async function renderHtmlFromFlightData(flightData, moduleMap) {
954
985
  ? payload.model
955
986
  : payload;
956
987
 
957
- return renderHtml(model);
988
+ const basename =
989
+ payload &&
990
+ typeof payload === "object" &&
991
+ payload.head &&
992
+ typeof payload.head.basename === "string"
993
+ ? payload.head.basename
994
+ : "";
995
+
996
+ const previousBasename = globalThis.__RSC_BASENAME;
997
+ globalThis.__RSC_BASENAME = basename;
998
+ try {
999
+ return await renderHtml(model);
1000
+ } finally {
1001
+ globalThis.__RSC_BASENAME = previousBasename;
1002
+ }
958
1003
  }
959
1004
 
960
1005
  process.on("message", async (message) => {
@@ -1291,16 +1336,16 @@ function createServerConsumerManifest(manifest) {
1291
1336
  }
1292
1337
  return requestKey;
1293
1338
  };
1294
- const addReference = (lookupKey, reference) => {
1339
+ const addReference = (lookupKey, exportName, reference) => {
1295
1340
  if (!lookupKey || lookupKey.trim() === "") {
1296
1341
  return;
1297
1342
  }
1298
- if (lookupKey in consumerManifest) {
1343
+ const normalizedExportName = exportName || "*";
1344
+ consumerManifest[lookupKey] ??= {};
1345
+ if (normalizedExportName in consumerManifest[lookupKey]) {
1299
1346
  return;
1300
1347
  }
1301
- consumerManifest[lookupKey] = {
1302
- "*": reference
1303
- };
1348
+ consumerManifest[lookupKey][normalizedExportName] = reference;
1304
1349
  };
1305
1350
  for (const [key, value] of Object.entries(manifest)) {
1306
1351
  if (!value || typeof value !== "object") {
@@ -1317,9 +1362,35 @@ function createServerConsumerManifest(manifest) {
1317
1362
  name: entry.name ?? "*",
1318
1363
  ...entry.async ? { async: entry.async } : {}
1319
1364
  };
1320
- addReference(key, reference);
1365
+ const hashIndex = key.lastIndexOf("#");
1366
+ const keyWithoutExport = hashIndex > -1 ? key.slice(0, hashIndex) : key;
1367
+ const keyExportName = hashIndex > -1 ? key.slice(hashIndex + 1) : "";
1368
+ const manifestExportName = typeof entry.name === "string" && entry.name !== "*" ? entry.name : "";
1369
+ const exportNames = new Set(
1370
+ [keyExportName, manifestExportName].filter((name) => name.trim() !== "")
1371
+ );
1372
+ addReference(
1373
+ key,
1374
+ "*",
1375
+ keyExportName ? { ...reference, name: keyExportName } : reference
1376
+ );
1377
+ addReference(keyWithoutExport, "*", reference);
1378
+ for (const exportName of exportNames) {
1379
+ const exportReference = {
1380
+ ...reference,
1381
+ name: exportName
1382
+ };
1383
+ addReference(keyWithoutExport, exportName, exportReference);
1384
+ addReference(key, "*", exportReference);
1385
+ }
1321
1386
  if (typeof entry.id === "number" && Number.isFinite(entry.id)) {
1322
- addReference(String(entry.id), reference);
1387
+ addReference(String(entry.id), "*", reference);
1388
+ for (const exportName of exportNames) {
1389
+ addReference(String(entry.id), exportName, {
1390
+ ...reference,
1391
+ name: exportName
1392
+ });
1393
+ }
1323
1394
  }
1324
1395
  }
1325
1396
  return consumerManifest;
@@ -1421,6 +1492,8 @@ function createNodeRequestHandler(options) {
1421
1492
  );
1422
1493
  const payload = {
1423
1494
  model: resolved2.model,
1495
+ contextModel: resolved2.contextModel,
1496
+ pageModel: resolved2.pageModel,
1424
1497
  head: resolved2.head
1425
1498
  };
1426
1499
  sendRSC(res, payload, {
@@ -1443,6 +1516,7 @@ function createNodeRequestHandler(options) {
1443
1516
  } else if (ext === ".json") {
1444
1517
  res.setHeader("Content-Type", "application/json; charset=utf-8");
1445
1518
  }
1519
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
1446
1520
  const stream = import_node_fs2.default.createReadStream(filePath);
1447
1521
  stream.on("error", () => {
1448
1522
  res.statusCode = 404;
@@ -1466,6 +1540,8 @@ function createNodeRequestHandler(options) {
1466
1540
  );
1467
1541
  const initialPayload = {
1468
1542
  model: resolved.model,
1543
+ contextModel: resolved.contextModel,
1544
+ pageModel: resolved.pageModel,
1469
1545
  head: resolved.head
1470
1546
  };
1471
1547
  const initialFlightData = await renderRSCToString(initialPayload, {
package/dist/index.js CHANGED
@@ -111,6 +111,7 @@ function sendRSC(res, model, options = {}) {
111
111
  } = options;
112
112
  res.statusCode = statusCode;
113
113
  res.setHeader("Content-Type", contentType);
114
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
114
115
  const stream = renderToPipeableStream(model, moduleMap, { onError });
115
116
  stream.pipe(res);
116
117
  return stream;
@@ -148,6 +149,7 @@ function createRSCHandler(options) {
148
149
  import fs from "node:fs";
149
150
  import Module from "node:module";
150
151
  import path2 from "node:path";
152
+ import { RouteChildrenSlot } from "@webtypen/webframez-react/route-slot";
151
153
 
152
154
  // src/head.ts
153
155
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
@@ -237,6 +239,16 @@ function isRouteChildrenType(type) {
237
239
  return false;
238
240
  }
239
241
  }
242
+ function isReactElementLike(node) {
243
+ if (!node || typeof node !== "object") {
244
+ return false;
245
+ }
246
+ try {
247
+ return "type" in node && "props" in node;
248
+ } catch {
249
+ return false;
250
+ }
251
+ }
240
252
  function injectRouteChildren(node, routeChildren) {
241
253
  if (node === null || node === void 0 || typeof node === "boolean") {
242
254
  return node;
@@ -252,13 +264,17 @@ function injectRouteChildren(node, routeChildren) {
252
264
  });
253
265
  return changed ? next : node;
254
266
  }
255
- if (!React.isValidElement(node)) {
267
+ if (isReactElementLike(node) && isRouteChildrenType(node.type)) {
268
+ return routeChildren;
269
+ }
270
+ const isValidElement = React.isValidElement(node);
271
+ if (!isValidElement && !isReactElementLike(node)) {
256
272
  return node;
257
273
  }
258
- if (isRouteChildrenType(node.type)) {
274
+ if (isValidElement && isRouteChildrenType(node.type)) {
259
275
  return routeChildren;
260
276
  }
261
- const props = node.props;
277
+ const props = node.props ?? {};
262
278
  if (!("children" in props)) {
263
279
  return node;
264
280
  }
@@ -266,10 +282,19 @@ function injectRouteChildren(node, routeChildren) {
266
282
  if (nextChildren === props.children) {
267
283
  return node;
268
284
  }
269
- if (Array.isArray(nextChildren)) {
270
- return React.cloneElement(node, void 0, ...nextChildren);
285
+ if (isValidElement) {
286
+ if (Array.isArray(nextChildren)) {
287
+ return React.cloneElement(node, void 0, ...nextChildren);
288
+ }
289
+ return React.cloneElement(node, void 0, nextChildren);
271
290
  }
272
- return React.cloneElement(node, void 0, nextChildren);
291
+ const elementLike = node;
292
+ const nextProps = {
293
+ ...elementLike.props ?? {},
294
+ children: nextChildren,
295
+ ...elementLike.key !== void 0 && elementLike.key !== null ? { key: elementLike.key } : {}
296
+ };
297
+ return React.createElement(elementLike.type, nextProps);
273
298
  }
274
299
 
275
300
  // src/file-router.tsx
@@ -610,9 +635,12 @@ function createFileRouter(options) {
610
635
  const errorHead = await resolveHead(errorModule, errorProps);
611
636
  const layoutNode = layoutModule ? await layoutModule.default(context) : null;
612
637
  const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
638
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ jsx(RouteChildrenSlot, {})) : void 0;
613
639
  return {
614
640
  statusCode,
615
641
  model,
642
+ contextModel,
643
+ pageModel: errorNode,
616
644
  head: mergeHead(layoutHead, errorHead)
617
645
  };
618
646
  }
@@ -732,9 +760,12 @@ function createFileRouter(options) {
732
760
  const pageHead = await resolveHead(pageModule, pageContext);
733
761
  const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
734
762
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
763
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ jsx(RouteChildrenSlot, {})) : void 0;
735
764
  return {
736
765
  statusCode: 200,
737
766
  model,
767
+ contextModel,
768
+ pageModel: pageNode,
738
769
  head: mergeHead(layoutHead, pageHead)
739
770
  };
740
771
  } catch (error) {
@@ -918,7 +949,21 @@ async function renderHtmlFromFlightData(flightData, moduleMap) {
918
949
  ? payload.model
919
950
  : payload;
920
951
 
921
- return renderHtml(model);
952
+ const basename =
953
+ payload &&
954
+ typeof payload === "object" &&
955
+ payload.head &&
956
+ typeof payload.head.basename === "string"
957
+ ? payload.head.basename
958
+ : "";
959
+
960
+ const previousBasename = globalThis.__RSC_BASENAME;
961
+ globalThis.__RSC_BASENAME = basename;
962
+ try {
963
+ return await renderHtml(model);
964
+ } finally {
965
+ globalThis.__RSC_BASENAME = previousBasename;
966
+ }
922
967
  }
923
968
 
924
969
  process.on("message", async (message) => {
@@ -1255,16 +1300,16 @@ function createServerConsumerManifest(manifest) {
1255
1300
  }
1256
1301
  return requestKey;
1257
1302
  };
1258
- const addReference = (lookupKey, reference) => {
1303
+ const addReference = (lookupKey, exportName, reference) => {
1259
1304
  if (!lookupKey || lookupKey.trim() === "") {
1260
1305
  return;
1261
1306
  }
1262
- if (lookupKey in consumerManifest) {
1307
+ const normalizedExportName = exportName || "*";
1308
+ consumerManifest[lookupKey] ??= {};
1309
+ if (normalizedExportName in consumerManifest[lookupKey]) {
1263
1310
  return;
1264
1311
  }
1265
- consumerManifest[lookupKey] = {
1266
- "*": reference
1267
- };
1312
+ consumerManifest[lookupKey][normalizedExportName] = reference;
1268
1313
  };
1269
1314
  for (const [key, value] of Object.entries(manifest)) {
1270
1315
  if (!value || typeof value !== "object") {
@@ -1281,9 +1326,35 @@ function createServerConsumerManifest(manifest) {
1281
1326
  name: entry.name ?? "*",
1282
1327
  ...entry.async ? { async: entry.async } : {}
1283
1328
  };
1284
- addReference(key, reference);
1329
+ const hashIndex = key.lastIndexOf("#");
1330
+ const keyWithoutExport = hashIndex > -1 ? key.slice(0, hashIndex) : key;
1331
+ const keyExportName = hashIndex > -1 ? key.slice(hashIndex + 1) : "";
1332
+ const manifestExportName = typeof entry.name === "string" && entry.name !== "*" ? entry.name : "";
1333
+ const exportNames = new Set(
1334
+ [keyExportName, manifestExportName].filter((name) => name.trim() !== "")
1335
+ );
1336
+ addReference(
1337
+ key,
1338
+ "*",
1339
+ keyExportName ? { ...reference, name: keyExportName } : reference
1340
+ );
1341
+ addReference(keyWithoutExport, "*", reference);
1342
+ for (const exportName of exportNames) {
1343
+ const exportReference = {
1344
+ ...reference,
1345
+ name: exportName
1346
+ };
1347
+ addReference(keyWithoutExport, exportName, exportReference);
1348
+ addReference(key, "*", exportReference);
1349
+ }
1285
1350
  if (typeof entry.id === "number" && Number.isFinite(entry.id)) {
1286
- addReference(String(entry.id), reference);
1351
+ addReference(String(entry.id), "*", reference);
1352
+ for (const exportName of exportNames) {
1353
+ addReference(String(entry.id), exportName, {
1354
+ ...reference,
1355
+ name: exportName
1356
+ });
1357
+ }
1287
1358
  }
1288
1359
  }
1289
1360
  return consumerManifest;
@@ -1385,6 +1456,8 @@ function createNodeRequestHandler(options) {
1385
1456
  );
1386
1457
  const payload = {
1387
1458
  model: resolved2.model,
1459
+ contextModel: resolved2.contextModel,
1460
+ pageModel: resolved2.pageModel,
1388
1461
  head: resolved2.head
1389
1462
  };
1390
1463
  sendRSC(res, payload, {
@@ -1407,6 +1480,7 @@ function createNodeRequestHandler(options) {
1407
1480
  } else if (ext === ".json") {
1408
1481
  res.setHeader("Content-Type", "application/json; charset=utf-8");
1409
1482
  }
1483
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
1410
1484
  const stream = fs2.createReadStream(filePath);
1411
1485
  stream.on("error", () => {
1412
1486
  res.statusCode = 404;
@@ -1430,6 +1504,8 @@ function createNodeRequestHandler(options) {
1430
1504
  );
1431
1505
  const initialPayload = {
1432
1506
  model: resolved.model,
1507
+ contextModel: resolved.contextModel,
1508
+ pageModel: resolved.pageModel,
1433
1509
  head: resolved.head
1434
1510
  };
1435
1511
  const initialFlightData = await renderRSCToString(initialPayload, {
@@ -0,0 +1,53 @@
1
+ "use client";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/route-slot.tsx
31
+ var route_slot_exports = {};
32
+ __export(route_slot_exports, {
33
+ RouteChildrenSlot: () => RouteChildrenSlot,
34
+ RouteChildrenSlotProvider: () => RouteChildrenSlotProvider
35
+ });
36
+ module.exports = __toCommonJS(route_slot_exports);
37
+ var import_react = __toESM(require("react"), 1);
38
+ var import_jsx_runtime = require("react/jsx-runtime");
39
+ var RouteChildrenSlotContext = import_react.default.createContext(null);
40
+ function RouteChildrenSlotProvider({
41
+ children,
42
+ page
43
+ }) {
44
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouteChildrenSlotContext.Provider, { value: page, children });
45
+ }
46
+ function RouteChildrenSlot() {
47
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: import_react.default.useContext(RouteChildrenSlotContext) });
48
+ }
49
+ // Annotate the CommonJS export names for ESM import in node:
50
+ 0 && (module.exports = {
51
+ RouteChildrenSlot,
52
+ RouteChildrenSlotProvider
53
+ });
@@ -0,0 +1,7 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ export function RouteChildrenSlotProvider(props: {
4
+ children: ReactNode;
5
+ page: ReactNode;
6
+ }): ReactNode;
7
+ export function RouteChildrenSlot(): ReactNode;
@@ -0,0 +1,19 @@
1
+ "use client";
2
+
3
+ // src/route-slot.tsx
4
+ import React from "react";
5
+ import { Fragment, jsx } from "react/jsx-runtime";
6
+ var RouteChildrenSlotContext = React.createContext(null);
7
+ function RouteChildrenSlotProvider({
8
+ children,
9
+ page
10
+ }) {
11
+ return /* @__PURE__ */ jsx(RouteChildrenSlotContext.Provider, { value: page, children });
12
+ }
13
+ function RouteChildrenSlot() {
14
+ return /* @__PURE__ */ jsx(Fragment, { children: React.useContext(RouteChildrenSlotContext) });
15
+ }
16
+ export {
17
+ RouteChildrenSlot,
18
+ RouteChildrenSlotProvider
19
+ };
package/dist/router.cjs CHANGED
@@ -40,6 +40,7 @@ module.exports = __toCommonJS(router_exports);
40
40
  var import_node_fs = __toESM(require("node:fs"), 1);
41
41
  var import_node_module = __toESM(require("node:module"), 1);
42
42
  var import_node_path = __toESM(require("node:path"), 1);
43
+ var import_route_slot = require("@webtypen/webframez-react/route-slot");
43
44
 
44
45
  // src/head.ts
45
46
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
@@ -129,6 +130,16 @@ function isRouteChildrenType(type) {
129
130
  return false;
130
131
  }
131
132
  }
133
+ function isReactElementLike(node) {
134
+ if (!node || typeof node !== "object") {
135
+ return false;
136
+ }
137
+ try {
138
+ return "type" in node && "props" in node;
139
+ } catch {
140
+ return false;
141
+ }
142
+ }
132
143
  function injectRouteChildren(node, routeChildren) {
133
144
  if (node === null || node === void 0 || typeof node === "boolean") {
134
145
  return node;
@@ -144,13 +155,17 @@ function injectRouteChildren(node, routeChildren) {
144
155
  });
145
156
  return changed ? next : node;
146
157
  }
147
- if (!import_react.default.isValidElement(node)) {
158
+ if (isReactElementLike(node) && isRouteChildrenType(node.type)) {
159
+ return routeChildren;
160
+ }
161
+ const isValidElement = import_react.default.isValidElement(node);
162
+ if (!isValidElement && !isReactElementLike(node)) {
148
163
  return node;
149
164
  }
150
- if (isRouteChildrenType(node.type)) {
165
+ if (isValidElement && isRouteChildrenType(node.type)) {
151
166
  return routeChildren;
152
167
  }
153
- const props = node.props;
168
+ const props = node.props ?? {};
154
169
  if (!("children" in props)) {
155
170
  return node;
156
171
  }
@@ -158,10 +173,19 @@ function injectRouteChildren(node, routeChildren) {
158
173
  if (nextChildren === props.children) {
159
174
  return node;
160
175
  }
161
- if (Array.isArray(nextChildren)) {
162
- return import_react.default.cloneElement(node, void 0, ...nextChildren);
176
+ if (isValidElement) {
177
+ if (Array.isArray(nextChildren)) {
178
+ return import_react.default.cloneElement(node, void 0, ...nextChildren);
179
+ }
180
+ return import_react.default.cloneElement(node, void 0, nextChildren);
163
181
  }
164
- return import_react.default.cloneElement(node, void 0, nextChildren);
182
+ const elementLike = node;
183
+ const nextProps = {
184
+ ...elementLike.props ?? {},
185
+ children: nextChildren,
186
+ ...elementLike.key !== void 0 && elementLike.key !== null ? { key: elementLike.key } : {}
187
+ };
188
+ return import_react.default.createElement(elementLike.type, nextProps);
165
189
  }
166
190
 
167
191
  // src/file-router.tsx
@@ -502,9 +526,12 @@ function createFileRouter(options) {
502
526
  const errorHead = await resolveHead(errorModule, errorProps);
503
527
  const layoutNode = layoutModule ? await layoutModule.default(context) : null;
504
528
  const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
529
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_route_slot.RouteChildrenSlot, {})) : void 0;
505
530
  return {
506
531
  statusCode,
507
532
  model,
533
+ contextModel,
534
+ pageModel: errorNode,
508
535
  head: mergeHead(layoutHead, errorHead)
509
536
  };
510
537
  }
@@ -624,9 +651,12 @@ function createFileRouter(options) {
624
651
  const pageHead = await resolveHead(pageModule, pageContext);
625
652
  const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
626
653
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
654
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_route_slot.RouteChildrenSlot, {})) : void 0;
627
655
  return {
628
656
  statusCode: 200,
629
657
  model,
658
+ contextModel,
659
+ pageModel: pageNode,
630
660
  head: mergeHead(layoutHead, pageHead)
631
661
  };
632
662
  } catch (error) {
package/dist/router.d.ts CHANGED
@@ -5,6 +5,8 @@ export type ResolvedRoute = {
5
5
  statusCode: number;
6
6
  model: ReactNode;
7
7
  head: HeadConfig;
8
+ contextModel?: ReactNode;
9
+ pageModel?: ReactNode;
8
10
  };
9
11
 
10
12
  export function createFileRouter(options: { pagesDir: string }): {