@uniweb/runtime 0.9.4 → 0.9.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniweb/runtime",
3
- "version": "0.9.4",
3
+ "version": "0.9.6",
4
4
  "description": "Minimal runtime for loading Uniweb foundations",
5
5
  "type": "module",
6
6
  "exports": {
@@ -13,7 +13,8 @@
13
13
  },
14
14
  "files": [
15
15
  "src",
16
- "dist"
16
+ "dist",
17
+ "!dist/app/**/*.map"
17
18
  ],
18
19
  "keywords": [
19
20
  "uniweb",
@@ -43,7 +44,7 @@
43
44
  "esbuild": "^0.21.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.27.0",
44
45
  "vite": "^7.3.1",
45
46
  "vitest": "^4.1.7",
46
- "@uniweb/build": "0.16.9"
47
+ "@uniweb/build": "0.16.12"
47
48
  },
48
49
  "peerDependencies": {
49
50
  "react": "^19.0.0",
@@ -553,6 +553,30 @@ export async function prefetchIcons(siteContent, uniweb, onProgress = () => {})
553
553
  * @param {Error} err
554
554
  * @returns {{ type: 'hooks'|'null-component'|'unknown', message: string }}
555
555
  */
556
+ /**
557
+ * Resolve a route to the Page that should render it.
558
+ *
559
+ * Exists because this module exported `renderPage(page, …)` and no supported way
560
+ * to *get* a page — so every host rendering server-side wrote its own lookup,
561
+ * and the obvious one (`website.pages.find(p => p.route === route)`) cannot
562
+ * match a dynamic route, because the payload holds `/blog/:id` and the request
563
+ * carries `/blog/1`. One host wrote that lookup three times in three files
564
+ * before the gap was noticed. A renderer that takes a Page owes callers a Page.
565
+ *
566
+ * This is `Website#getPage` — the same seven-step resolution the browser runs,
567
+ * literally the same function, so a server-rendered page and the one hydrating
568
+ * over it cannot disagree. Pure `@uniweb/core`: no React, no DOM, no DataStore
569
+ * required, safe in a Worker isolate.
570
+ *
571
+ * @param {Website} website
572
+ * @param {string} route - The requested path, e.g. `/blog/1`
573
+ * @returns {Page|undefined} The page, or undefined when nothing matches — which
574
+ * is a genuine 404 and the caller's to turn into one.
575
+ */
576
+ export function resolvePage(website, route) {
577
+ return website.getPage(route)
578
+ }
579
+
556
580
  export function classifyRenderError(err) {
557
581
  const msg = err.message || ''
558
582
 
@@ -589,6 +613,27 @@ export function classifyRenderError(err) {
589
613
  export function renderPage(page, website) {
590
614
  website.setActivePage(page.route)
591
615
 
616
+ // A page that claims content but yields no blocks has not been loaded — it is
617
+ // not an empty page. `Page#bodyBlocks` returns [] when its sections are absent
618
+ // from the payload (split content), on the understanding that a caller loads
619
+ // them first: the SPA does, in PageRenderer and at boot. THIS path never has.
620
+ //
621
+ // Left alone, that renders a structurally valid, completely empty document and
622
+ // reports success — which is the worst shape a failure can take, and it cost a
623
+ // host most of a day chasing a renderer that was doing what it was told.
624
+ // Distinguishing it here is cheap: a content-less container reports
625
+ // hasContent() === false and is correctly empty, so the two never collide.
626
+ if (page.hasContent?.() && page.getBodyBlocks().length === 0) {
627
+ return {
628
+ error: {
629
+ type: 'content-not-loaded',
630
+ message:
631
+ `page "${page.route}" declares content but has no loaded sections — ` +
632
+ 'its sections are not in the payload and this renderer does not fetch them',
633
+ },
634
+ }
635
+ }
636
+
592
637
  const element = renderLayout(page, website)
593
638
 
594
639
  let renderedContent
package/src/ssr.js CHANGED
@@ -39,7 +39,12 @@ export {
39
39
  hydrateDataStore,
40
40
  prefetchIcons,
41
41
 
42
- // Layer 3: Per-page rendering
42
+ // Layer 3: Per-page rendering.
43
+ // `resolvePage` belongs beside `renderPage` and its absence was a real bug:
44
+ // this list handed callers a renderer that takes a Page and no supported way
45
+ // to get one, so a host wrote its own lookup three times — and the obvious
46
+ // one, an exact match over `website.pages`, cannot match a dynamic route.
47
+ resolvePage,
43
48
  renderPage,
44
49
  classifyRenderError,
45
50
 
@@ -1 +0,0 @@
1
- {"version":3,"file":"@uniweb-core.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}