@uniweb/runtime 1.3.10 → 1.3.12

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": "1.3.10",
3
+ "version": "1.3.12",
4
4
  "description": "Minimal runtime for loading Uniweb foundations",
5
5
  "type": "module",
6
6
  "exports": {
@@ -44,7 +44,7 @@
44
44
  "esbuild": "^0.21.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.27.0 || ^0.28.0",
45
45
  "vite": "^7.3.1",
46
46
  "vitest": "^4.1.7",
47
- "@uniweb/build": "1.14.0"
47
+ "@uniweb/build": "1.14.1"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "react": "^19.0.0",
@@ -179,7 +179,7 @@ export const ISOLATE_API = Object.freeze({
179
179
  * the publish that creates the version, never in anticipation — the whole
180
180
  * reason `UNRELEASED` exists a few lines up.
181
181
  * 2. **A raise is a CROSS-LANE event.** Backend reads this from the channel index
182
- * and refuses to serve a site below it, so the number moves for them when the
182
+ * and publishes no site below it, so the number moves for them when the
183
183
  * CHANNEL republishes — not when this constant changes.
184
184
  *
185
185
  * ⭐ **Revisited at 1.0 [Diego, 2026-10-11].** This note read: *"Revisit at 1.0: once
@@ -190,7 +190,13 @@ export const ISOLATE_API = Object.freeze({
190
190
  * using 1.0.1+"*. The two mechanical rules above stand.
191
191
  */
192
192
  /*
193
- * ⭐ **1.0.1, raised 2026-10-13 [Diego]** — the first 1.x runtime, a BASELINE raise like the two
193
+ * ⭐ **1.2.3, raised 2026-11-02** — an incompatibility, and a host's request: its render now relies on
194
+ * `render(target, { fetchedData })` and `Website#makeCurrent`, which first shipped in 1.2.3 with core
195
+ * 1.4.7. A runtime below it ignores the option without a word, so a page would render against whatever
196
+ * the graph kept from the last request. Neither is an export, so the map below cannot say it. 1.2.3 is
197
+ * on npm and in the channel, and, like every raise, this reaches backend at the next runtime publish.
198
+ *
199
+ * ⛔ **Previously 1.0.1, raised 2026-10-13 [Diego]** — the first 1.x runtime, a BASELINE raise like the two
194
200
  * below: *"We would also set `minUsable` to tell backend to start using 1.0.1+"* (2026-10-11).
195
201
  * 1.0.1 is the release that took every package from 0.x to 1.x; the runtime's line since 0.29.7
196
202
  * carries `carryQuery`. Raised once npm served 1.0.1 and the channel's `latest` was 1.0.1, and,
@@ -229,7 +235,7 @@ export const ISOLATE_API = Object.freeze({
229
235
  * which the service refuses with a whole-request `400` since it took `narrow`. It also carries
230
236
  * declared-key delivery and `$route`. That break is still real and still below this number.
231
237
  */
232
- export const WIRE_FLOOR = '1.0.1'
238
+ export const WIRE_FLOOR = '1.2.3'
233
239
 
234
240
  /**
235
241
  * ⭐ **THE MINIMUM RUNTIME VERSION A SITE MAY BE PUBLISHED AT.** At or above it,
@@ -33,7 +33,7 @@
33
33
  * - **Anything build-only.** `injectBuildData` stays in the build lane; it is the
34
34
  * other half of the head seam and has its own parity guard.
35
35
  */
36
- import { renderPage, classifyRenderError, injectPageContent } from './ssr-renderer.js'
36
+ import { renderPage, classifyRenderError, failingSectionOf, injectPageContent } from './ssr-renderer.js'
37
37
  import { resolveRequestedPage } from './resolve-page.js'
38
38
  import { hydrateDataStore } from './wire-foundation.js'
39
39
  import { loadPageData } from './load-page-data.js'
@@ -50,7 +50,9 @@ import { whileReadingIcons } from './page-icons.js'
50
50
  * @param {Object} opts
51
51
  * @param {Object} opts.website - `uniweb.activeWebsite`, already initialized
52
52
  * @param {string} opts.shell - the HTML shell to inject into, taken as given
53
- * @returns {{ website: Object, render: Function }}
53
+ * @returns {{ website: Object, render: Function, failingSection: Function }} `failingSection` asks
54
+ * which section stopped a page `render` reported as `failed` (`failingSectionOf`). A render per
55
+ * block: for a build's report, not for a host answering a request.
54
56
  */
55
57
  export function createPageRenderer({ website, shell }) {
56
58
  if (!website) throw new Error('createPageRenderer: `website` is required')
@@ -187,7 +189,7 @@ export function createPageRenderer({ website, shell }) {
187
189
  return { outcome: missing ? 'notFound' : 'rendered', html, page, error: null }
188
190
  }
189
191
 
190
- return { website, render }
192
+ return { website, render, failingSection: (page, message) => failingSectionOf(page, message) }
191
193
  }
192
194
 
193
195
  /**
@@ -579,6 +579,36 @@ export function renderPage(page, website) {
579
579
  return { renderedContent, sectionOverrideCSS }
580
580
  }
581
581
 
582
+ /**
583
+ * Which section stopped a page from rendering, for a report to whoever can fix it: each block the
584
+ * page renders, alone, and the deepest that fails the same way. Null when none does, so the layout
585
+ * around them did. `renderPage` can say only what went wrong: `renderToString` names no component,
586
+ * and a built foundation's stack names minified ones.
587
+ *
588
+ * One render per block, so it's for a page that has already failed and a caller with time to spend.
589
+ * The same message, since a block alone misses what its layout gives it, and may fail for that.
590
+ *
591
+ * @param {Page} page - The page that failed
592
+ * @param {string} message - What `renderPage` reported
593
+ * @returns {string|null} the section's type
594
+ */
595
+ export function failingSectionOf(page, message) {
596
+ const fails = (block) => {
597
+ try {
598
+ renderToString(renderBlock(block))
599
+ return false
600
+ } catch (err) {
601
+ return err.message === message
602
+ }
603
+ }
604
+ const deepest = (block) => {
605
+ const child = (block.childBlocks || []).find(fails)
606
+ return child ? deepest(child) : block
607
+ }
608
+ const block = page.getAllBlocks().find(fails)
609
+ return block ? deepest(block).type : null
610
+ }
611
+
582
612
  // ============================================================================
583
613
  // HTML injection
584
614
  // ============================================================================