@webtypen/webframez-react 0.0.48 → 0.0.50
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/README.md +61 -0
- package/defaults/webpack.client.cjs +6 -2
- package/dist/client.cjs +1 -1
- package/dist/client.js +1 -1
- package/dist/http.cjs +134 -46
- package/dist/http.d.ts +5 -0
- package/dist/http.js +131 -45
- package/dist/index.cjs +207 -53
- package/dist/index.d.ts +2 -0
- package/dist/index.js +227 -53
- package/dist/navigation.cjs +80 -15
- package/dist/navigation.d.ts +1 -1
- package/dist/navigation.js +92 -15
- package/dist/paths.cjs +102 -0
- package/dist/paths.d.ts +4 -0
- package/dist/paths.js +92 -0
- package/dist/router.cjs +58 -8
- package/dist/router.d.ts +8 -2
- package/dist/router.js +58 -8
- package/dist/types.d.ts +24 -0
- package/dist/webframez-core.cjs +186 -53
- package/dist/webframez-core.d.ts +2 -8
- package/dist/webframez-core.js +206 -53
- package/package.json +18 -4
package/dist/http.js
CHANGED
|
@@ -7,6 +7,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
// src/http.ts
|
|
10
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
10
11
|
import fs2 from "node:fs";
|
|
11
12
|
import path3 from "node:path";
|
|
12
13
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
@@ -35,6 +36,8 @@ function createHTMLShell(options = {}) {
|
|
|
35
36
|
buildId = "",
|
|
36
37
|
headTags = "",
|
|
37
38
|
bodyClassName = "",
|
|
39
|
+
bodyStartHtml = "",
|
|
40
|
+
bodyEndHtml = "",
|
|
38
41
|
rootHtml = "",
|
|
39
42
|
initialFlightData = "",
|
|
40
43
|
basename = "",
|
|
@@ -84,7 +87,9 @@ function createHTMLShell(options = {}) {
|
|
|
84
87
|
${headTags}
|
|
85
88
|
</head>
|
|
86
89
|
<body${bodyClassName ? ` class="${bodyClassName.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">")}"` : ""}>
|
|
90
|
+
${bodyStartHtml}
|
|
87
91
|
<div id="root">${rootHtml}</div>
|
|
92
|
+
${bodyEndHtml}
|
|
88
93
|
<script>window.__RSC_ENDPOINT = "${rscEndpoint}";</script>
|
|
89
94
|
<script>window.__RSC_BASENAME = "${basename}";</script>
|
|
90
95
|
<script>window.__RSC_ROUTE_BASE_PATH = "${routeBasePath}";</script>
|
|
@@ -199,6 +204,12 @@ function normalizeHeadConfig(head, inheritedBasename) {
|
|
|
199
204
|
href: resolveHeadAssetUrl(link.href, effectiveBasename)
|
|
200
205
|
}));
|
|
201
206
|
}
|
|
207
|
+
if (normalizedHead.scripts) {
|
|
208
|
+
normalizedHead.scripts = normalizedHead.scripts.map((script) => ({
|
|
209
|
+
...script,
|
|
210
|
+
...script.src ? { src: resolveHeadAssetUrl(script.src, effectiveBasename) } : {}
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
202
213
|
return normalizedHead;
|
|
203
214
|
}
|
|
204
215
|
|
|
@@ -311,8 +322,7 @@ var FORCED_PACKAGE_REQUESTS = [
|
|
|
311
322
|
"react-server-dom-webpack",
|
|
312
323
|
"react-server-dom-webpack/server",
|
|
313
324
|
"react-server-dom-webpack/client",
|
|
314
|
-
"react-server-dom-webpack/client.node"
|
|
315
|
-
"scheduler"
|
|
325
|
+
"react-server-dom-webpack/client.node"
|
|
316
326
|
];
|
|
317
327
|
var forcedPackageResolutionInstalled = false;
|
|
318
328
|
function normalizePathname(pathname) {
|
|
@@ -451,7 +461,9 @@ function matchRoute(entry, pathname) {
|
|
|
451
461
|
function mergeHead(...configs) {
|
|
452
462
|
const merged = {
|
|
453
463
|
meta: [],
|
|
454
|
-
links: []
|
|
464
|
+
links: [],
|
|
465
|
+
scripts: [],
|
|
466
|
+
html: []
|
|
455
467
|
};
|
|
456
468
|
for (const candidate of configs) {
|
|
457
469
|
const config = normalizeHeadConfig(candidate, merged.basename);
|
|
@@ -486,9 +498,28 @@ function mergeHead(...configs) {
|
|
|
486
498
|
if (config.links) {
|
|
487
499
|
merged.links?.push(...config.links);
|
|
488
500
|
}
|
|
501
|
+
if (config.scripts) {
|
|
502
|
+
merged.scripts?.push(...config.scripts);
|
|
503
|
+
}
|
|
504
|
+
if (config.html) {
|
|
505
|
+
merged.html?.push(...Array.isArray(config.html) ? config.html : [config.html]);
|
|
506
|
+
}
|
|
507
|
+
if (config.bodyStartHtml) {
|
|
508
|
+
merged.bodyStartHtml = [merged.bodyStartHtml, config.bodyStartHtml].filter(Boolean).join("\n");
|
|
509
|
+
}
|
|
510
|
+
if (config.bodyEndHtml) {
|
|
511
|
+
merged.bodyEndHtml = [merged.bodyEndHtml, config.bodyEndHtml].filter(Boolean).join("\n");
|
|
512
|
+
}
|
|
489
513
|
}
|
|
490
514
|
return merged;
|
|
491
515
|
}
|
|
516
|
+
function renderGenericAttributes(entry, excluded = []) {
|
|
517
|
+
return Object.entries(entry).filter(
|
|
518
|
+
([key, value]) => !excluded.includes(key) && value !== void 0 && value !== null && value !== false
|
|
519
|
+
).map(
|
|
520
|
+
([key, value]) => value === true ? key : `${key}="${escapeHtml(String(value))}"`
|
|
521
|
+
).join(" ");
|
|
522
|
+
}
|
|
492
523
|
function renderHeadToString(head) {
|
|
493
524
|
const normalizedHead = normalizeHeadConfig(head) ?? head;
|
|
494
525
|
const tags = [];
|
|
@@ -510,6 +541,23 @@ function renderHeadToString(head) {
|
|
|
510
541
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
511
542
|
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
512
543
|
}
|
|
544
|
+
for (const script of normalizedHead.scripts ?? []) {
|
|
545
|
+
if (script.html) {
|
|
546
|
+
tags.push(script.html);
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
const attrs = renderGenericAttributes(script, [
|
|
550
|
+
"content",
|
|
551
|
+
"html"
|
|
552
|
+
]);
|
|
553
|
+
const content = script.content ? String(script.content) : "";
|
|
554
|
+
tags.push(`<script ${createManagedAttributes()} ${attrs}>${content}</script>`);
|
|
555
|
+
}
|
|
556
|
+
for (const html of normalizedHead.html ?? []) {
|
|
557
|
+
if (typeof html === "string" && html.trim() !== "") {
|
|
558
|
+
tags.push(html);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
513
561
|
return tags.join("\n");
|
|
514
562
|
}
|
|
515
563
|
function clearModuleCache(modulePath, rootDir, visited = /* @__PURE__ */ new Set()) {
|
|
@@ -595,6 +643,7 @@ function isRouteAbort(value) {
|
|
|
595
643
|
function createFileRouter(options) {
|
|
596
644
|
installForcedPackageResolution();
|
|
597
645
|
const pagesDir = options.pagesDir;
|
|
646
|
+
const onData = options.onData;
|
|
598
647
|
const layoutPath = path2.join(pagesDir, "layout.js");
|
|
599
648
|
const errorPath = path2.join(pagesDir, "errors.js");
|
|
600
649
|
const middlewaresPath = path2.join(pagesDir, "middlewares.js");
|
|
@@ -759,10 +808,16 @@ function createFileRouter(options) {
|
|
|
759
808
|
data: mergeRouteData(middlewareContext.data, pageData)
|
|
760
809
|
};
|
|
761
810
|
activeContext = pageContext;
|
|
762
|
-
const
|
|
763
|
-
const
|
|
764
|
-
|
|
765
|
-
|
|
811
|
+
const onDataResult = typeof onData === "function" ? await onData(pageContext) : void 0;
|
|
812
|
+
const eventContext = {
|
|
813
|
+
...pageContext,
|
|
814
|
+
data: mergeRouteData(pageContext.data, onDataResult)
|
|
815
|
+
};
|
|
816
|
+
activeContext = eventContext;
|
|
817
|
+
const pageNode = await pageModule.default(eventContext);
|
|
818
|
+
const layoutHead = layoutModule ? await resolveHead(layoutModule, eventContext) : void 0;
|
|
819
|
+
const pageHead = await resolveHead(pageModule, eventContext);
|
|
820
|
+
const layoutNode = layoutModule ? await layoutModule.default(eventContext) : null;
|
|
766
821
|
const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
|
|
767
822
|
const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ jsx(RouteChildren, {})) : void 0;
|
|
768
823
|
return {
|
|
@@ -771,7 +826,7 @@ function createFileRouter(options) {
|
|
|
771
826
|
contextModel,
|
|
772
827
|
pageModel: pageNode,
|
|
773
828
|
head: mergeHead(layoutHead, pageHead),
|
|
774
|
-
context:
|
|
829
|
+
context: eventContext
|
|
775
830
|
};
|
|
776
831
|
} catch (error) {
|
|
777
832
|
if (isRouteAbort(error)) {
|
|
@@ -918,6 +973,7 @@ const rootParent = {
|
|
|
918
973
|
path: process.cwd(),
|
|
919
974
|
paths: Module._nodeModulePaths(process.cwd()),
|
|
920
975
|
};
|
|
976
|
+
// Transitive dependencies (e.g. scheduler) must resolve from their importer.
|
|
921
977
|
const forcedPackageRequests = [
|
|
922
978
|
"@webtypen/webframez-core",
|
|
923
979
|
"@webtypen/webframez-react",
|
|
@@ -932,7 +988,6 @@ const forcedPackageRequests = [
|
|
|
932
988
|
"react-server-dom-webpack/server",
|
|
933
989
|
"react-server-dom-webpack/client",
|
|
934
990
|
"react-server-dom-webpack/client.node",
|
|
935
|
-
"scheduler"
|
|
936
991
|
];
|
|
937
992
|
|
|
938
993
|
function shouldForcePackageResolution(request) {
|
|
@@ -1124,13 +1179,17 @@ async function renderHtmlFromFlightData(flightData, moduleMap) {
|
|
|
1124
1179
|
? payload.head.basename
|
|
1125
1180
|
: "";
|
|
1126
1181
|
|
|
1127
|
-
const
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1182
|
+
const routingContext = globalThis.__WEBFRAMEZ_ROUTING_CONTEXT__ ??=
|
|
1183
|
+
new (require("node:async_hooks").AsyncLocalStorage)();
|
|
1184
|
+
return routingContext.run(basename, async () => {
|
|
1185
|
+
const previousBasename = globalThis.__RSC_BASENAME;
|
|
1186
|
+
globalThis.__RSC_BASENAME = basename;
|
|
1187
|
+
try {
|
|
1188
|
+
return await renderHtml(model);
|
|
1189
|
+
} finally {
|
|
1190
|
+
globalThis.__RSC_BASENAME = previousBasename;
|
|
1191
|
+
}
|
|
1192
|
+
});
|
|
1134
1193
|
}
|
|
1135
1194
|
|
|
1136
1195
|
process.on("message", async (message) => {
|
|
@@ -1366,24 +1425,10 @@ ${stderrBuffer.trim()}` : "";
|
|
|
1366
1425
|
}
|
|
1367
1426
|
};
|
|
1368
1427
|
}
|
|
1428
|
+
var routingRuntime = globalThis;
|
|
1429
|
+
var basenameContext = routingRuntime.__WEBFRAMEZ_ROUTING_CONTEXT__ ??= new AsyncLocalStorage();
|
|
1369
1430
|
function withRequestBasename(basename, fn) {
|
|
1370
|
-
|
|
1371
|
-
const previous = target.__RSC_BASENAME;
|
|
1372
|
-
target.__RSC_BASENAME = basename;
|
|
1373
|
-
const finish = () => {
|
|
1374
|
-
target.__RSC_BASENAME = previous;
|
|
1375
|
-
};
|
|
1376
|
-
try {
|
|
1377
|
-
const result = fn();
|
|
1378
|
-
if (result && typeof result.then === "function") {
|
|
1379
|
-
return result.finally(finish);
|
|
1380
|
-
}
|
|
1381
|
-
finish();
|
|
1382
|
-
return result;
|
|
1383
|
-
} catch (error) {
|
|
1384
|
-
finish();
|
|
1385
|
-
throw error;
|
|
1386
|
-
}
|
|
1431
|
+
return basenameContext.run(basename, fn);
|
|
1387
1432
|
}
|
|
1388
1433
|
function parseCookies(rawCookieHeader) {
|
|
1389
1434
|
const raw = Array.isArray(rawCookieHeader) ? rawCookieHeader.join("; ") : rawCookieHeader ?? "";
|
|
@@ -1418,12 +1463,27 @@ function normalizeClientManifest(manifest, options) {
|
|
|
1418
1463
|
}
|
|
1419
1464
|
};
|
|
1420
1465
|
for (const [key, value] of Object.entries(manifest)) {
|
|
1466
|
+
const hashIndex = key.indexOf("#");
|
|
1467
|
+
const moduleKey = hashIndex < 0 ? key : key.slice(0, hashIndex);
|
|
1468
|
+
const exportSuffix = hashIndex < 0 ? "" : key.slice(hashIndex);
|
|
1469
|
+
if (!path3.isAbsolute(moduleKey) && !moduleKey.includes(":") && !moduleKey.startsWith("file://")) {
|
|
1470
|
+
const runtimePath = path3.resolve(options.cwd, moduleKey);
|
|
1471
|
+
const allowedRoots = [options.distRootDir, ...candidateNodeModulesDirs];
|
|
1472
|
+
const insideArtifact = allowedRoots.some((root) => {
|
|
1473
|
+
const relative = path3.relative(path3.resolve(root), runtimePath);
|
|
1474
|
+
return relative !== "" && relative !== ".." && !relative.startsWith(`..${path3.sep}`) && !path3.isAbsolute(relative);
|
|
1475
|
+
});
|
|
1476
|
+
if (insideArtifact) {
|
|
1477
|
+
addAlias(`${runtimePath}${exportSuffix}`, value);
|
|
1478
|
+
addAlias(`${pathToFileURL(runtimePath).href}${exportSuffix}`, value);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1421
1481
|
if (!key.startsWith("file://")) {
|
|
1422
1482
|
continue;
|
|
1423
1483
|
}
|
|
1424
1484
|
let absolutePath = "";
|
|
1425
1485
|
try {
|
|
1426
|
-
absolutePath = fileURLToPath(
|
|
1486
|
+
absolutePath = fileURLToPath(moduleKey);
|
|
1427
1487
|
} catch {
|
|
1428
1488
|
continue;
|
|
1429
1489
|
}
|
|
@@ -1434,13 +1494,13 @@ function normalizeClientManifest(manifest, options) {
|
|
|
1434
1494
|
}
|
|
1435
1495
|
const relativeModulePath = absolutePath.slice(markerIndex + marker.length);
|
|
1436
1496
|
const relativeModulePathPosix = relativeModulePath.split(path3.sep).join("/");
|
|
1437
|
-
addAlias(`./node_modules/${relativeModulePathPosix}`, value);
|
|
1438
|
-
addAlias(`node_modules/${relativeModulePathPosix}`, value);
|
|
1439
|
-
addAlias(absolutePath
|
|
1497
|
+
addAlias(`./node_modules/${relativeModulePathPosix}${exportSuffix}`, value);
|
|
1498
|
+
addAlias(`node_modules/${relativeModulePathPosix}${exportSuffix}`, value);
|
|
1499
|
+
addAlias(`${absolutePath}${exportSuffix}`, value);
|
|
1440
1500
|
for (const nodeModulesDir of candidateNodeModulesDirs) {
|
|
1441
1501
|
const aliasPath = path3.join(nodeModulesDir, relativeModulePath);
|
|
1442
|
-
addAlias(aliasPath
|
|
1443
|
-
addAlias(pathToFileURL(aliasPath).href
|
|
1502
|
+
addAlias(`${aliasPath}${exportSuffix}`, value);
|
|
1503
|
+
addAlias(`${pathToFileURL(aliasPath).href}${exportSuffix}`, value);
|
|
1444
1504
|
}
|
|
1445
1505
|
}
|
|
1446
1506
|
return normalized;
|
|
@@ -1585,16 +1645,16 @@ function createNodeRequestHandler(options) {
|
|
|
1585
1645
|
const manifestPath = path3.resolve(
|
|
1586
1646
|
options.manifestPath ?? path3.join(distRootDir, "react-client-manifest.json")
|
|
1587
1647
|
);
|
|
1588
|
-
const assetsPrefix = options.assetsPrefix ?? "/assets/";
|
|
1589
|
-
const rscPath = options.rscPath ?? "/rsc";
|
|
1590
|
-
const clientScriptUrl = options.clientScriptUrl ?? "/assets/client.js";
|
|
1591
1648
|
const basePath = normalizeBasePath(options.basePath);
|
|
1649
|
+
const assetsPrefix = options.assetsPrefix ?? `${basePath}/assets/`;
|
|
1650
|
+
const rscPath = options.rscPath ?? `${basePath}/rsc`;
|
|
1651
|
+
const clientScriptUrl = options.clientScriptUrl ?? `${basePath}/assets/client.js`;
|
|
1592
1652
|
const nodeEnv = process.env.NODE_ENV || "";
|
|
1593
1653
|
const runningInWatchMode = Array.isArray(process.execArgv) && process.execArgv.includes("--watch");
|
|
1594
1654
|
const liveReloadEnabled = options.liveReloadPath !== false && (nodeEnv === "development" || runningInWatchMode);
|
|
1595
1655
|
const liveReloadPath = !liveReloadEnabled ? "" : options.liveReloadPath ?? `${basePath || ""}/__webframez_live_reload`;
|
|
1596
1656
|
const liveReloadClients = /* @__PURE__ */ new Set();
|
|
1597
|
-
const router = createFileRouter({ pagesDir });
|
|
1657
|
+
const router = createFileRouter({ pagesDir, onData: options.onData });
|
|
1598
1658
|
const getManifestState = createManifestLoader({
|
|
1599
1659
|
distRootDir,
|
|
1600
1660
|
manifestPath,
|
|
@@ -1607,7 +1667,7 @@ function createNodeRequestHandler(options) {
|
|
|
1607
1667
|
process.once("exit", disposeInitialHtmlWorker);
|
|
1608
1668
|
process.once("SIGINT", disposeInitialHtmlWorker);
|
|
1609
1669
|
process.once("SIGTERM", disposeInitialHtmlWorker);
|
|
1610
|
-
|
|
1670
|
+
const handleRequest = async (req, res) => {
|
|
1611
1671
|
if (!req.url) {
|
|
1612
1672
|
res.statusCode = 400;
|
|
1613
1673
|
res.end("Bad request");
|
|
@@ -1671,6 +1731,7 @@ function createNodeRequestHandler(options) {
|
|
|
1671
1731
|
request: requestContext
|
|
1672
1732
|
})
|
|
1673
1733
|
);
|
|
1734
|
+
resolved2.head = { ...resolved2.head, basename: resolved2.head.basename ?? basePath };
|
|
1674
1735
|
attachResolvedContextToCoreRequest(req, resolved2.context);
|
|
1675
1736
|
const payload = {
|
|
1676
1737
|
model: resolved2.model,
|
|
@@ -1746,6 +1807,7 @@ function createNodeRequestHandler(options) {
|
|
|
1746
1807
|
)
|
|
1747
1808
|
})
|
|
1748
1809
|
);
|
|
1810
|
+
resolved.head = { ...resolved.head, basename: resolved.head.basename ?? basePath };
|
|
1749
1811
|
attachResolvedContextToCoreRequest(req, resolved.context);
|
|
1750
1812
|
const initialPayload = {
|
|
1751
1813
|
model: resolved.model,
|
|
@@ -1818,6 +1880,8 @@ function createNodeRequestHandler(options) {
|
|
|
1818
1880
|
initialFlightData,
|
|
1819
1881
|
basename: shellBasename,
|
|
1820
1882
|
routeBasePath: shellRouteBasePath,
|
|
1883
|
+
bodyStartHtml: resolved.head.bodyStartHtml || "",
|
|
1884
|
+
bodyEndHtml: resolved.head.bodyEndHtml || "",
|
|
1821
1885
|
liveReloadPath: liveReloadPath || void 0,
|
|
1822
1886
|
liveReloadServerId: liveReloadPath ? devServerId : void 0
|
|
1823
1887
|
}),
|
|
@@ -1829,7 +1893,29 @@ function createNodeRequestHandler(options) {
|
|
|
1829
1893
|
}
|
|
1830
1894
|
);
|
|
1831
1895
|
};
|
|
1896
|
+
return (req, res) => withRequestBasename(basePath, () => handleRequest(req, res));
|
|
1897
|
+
}
|
|
1898
|
+
var standaloneHtmlWorker;
|
|
1899
|
+
async function renderReactToHtml(element) {
|
|
1900
|
+
if (!standaloneHtmlWorker) {
|
|
1901
|
+
standaloneHtmlWorker = createInitialHtmlWorker(process.cwd());
|
|
1902
|
+
process.once("exit", disposeReactHtmlRenderer);
|
|
1903
|
+
}
|
|
1904
|
+
const flightData = await renderRSCToString({ model: element }, {
|
|
1905
|
+
moduleMap: {},
|
|
1906
|
+
onError: (error) => {
|
|
1907
|
+
console.error("[webframez-react] HTML render failed", error);
|
|
1908
|
+
}
|
|
1909
|
+
});
|
|
1910
|
+
return standaloneHtmlWorker.renderFromFlightData({ flightData, moduleMap: {} });
|
|
1911
|
+
}
|
|
1912
|
+
function disposeReactHtmlRenderer() {
|
|
1913
|
+
process.removeListener("exit", disposeReactHtmlRenderer);
|
|
1914
|
+
standaloneHtmlWorker?.dispose();
|
|
1915
|
+
standaloneHtmlWorker = void 0;
|
|
1832
1916
|
}
|
|
1833
1917
|
export {
|
|
1834
|
-
createNodeRequestHandler
|
|
1918
|
+
createNodeRequestHandler,
|
|
1919
|
+
disposeReactHtmlRenderer,
|
|
1920
|
+
renderReactToHtml
|
|
1835
1921
|
};
|