@uniweb/runtime 0.23.0 → 0.25.0
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/ssr.js +85 -64
- package/dist/ssr.js.map +1 -1
- package/package.json +3 -3
- package/src/collect-records.js +26 -23
- package/src/default-fetcher.js +138 -90
- package/src/prefetch.js +25 -16
- package/src/prepare-props.js +53 -21
- package/src/ssr-renderer.js +2 -2
package/src/prepare-props.js
CHANGED
|
@@ -313,27 +313,54 @@ export function applyDefaults(params, defaults) {
|
|
|
313
313
|
}
|
|
314
314
|
|
|
315
315
|
/**
|
|
316
|
-
*
|
|
316
|
+
* ⭐ `content.data` HOLDS THE KEYS THE COMPONENT DECLARES, AND NOTHING ELSE — ruled 2026-09-14
|
|
317
|
+
* [Diego]. Every key in its `meta.js` `data:` and its foundation's `main.js` `data:`
|
|
318
|
+
* (`website.declaredKeys`), each filled, in order, from:
|
|
317
319
|
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
* entity
|
|
321
|
-
*
|
|
322
|
-
*
|
|
320
|
+
* 1. what the section holds under that key (`block.heldData`) — a tagged data block, or
|
|
321
|
+
* its own fetch's answer a static build prerendered into it;
|
|
322
|
+
* 2. what the entity store delivered for it — the fetch that fills it (`fillDeclaredKeys`);
|
|
323
|
+
* 3. `null` — nothing fills it, or its fetch is still out (`block.dataLoading`) or failed
|
|
324
|
+
* (`block.dataError[key]`). ⭐ Never `[]`, which is an answer with no records.
|
|
325
|
+
*
|
|
326
|
+
* A tagged data block under a key the component does not declare is left out, and said so
|
|
327
|
+
* in dev (`warnUndeclaredBlocks`); it stays in `content.sequence`. The data object is
|
|
328
|
+
* rebuilt on each render from those sources, never from the last render's.
|
|
329
|
+
*
|
|
330
|
+
* ⛔ Until 2026-09-14 this merged every delivered key into what the section held, so a
|
|
331
|
+
* section received every fetch that reached it and every tagged block it had.
|
|
323
332
|
*/
|
|
324
|
-
function
|
|
325
|
-
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
if (
|
|
331
|
-
|
|
332
|
-
changed = true
|
|
333
|
-
}
|
|
333
|
+
function assembleData(block, meta, entityData) {
|
|
334
|
+
const declared = block.website?.declaredKeys ? block.website.declaredKeys(meta) : []
|
|
335
|
+
const held = block.heldData || {}
|
|
336
|
+
const data = {}
|
|
337
|
+
for (const [key] of declared) {
|
|
338
|
+
if (held[key] !== undefined) data[key] = held[key]
|
|
339
|
+
else if (entityData && entityData[key] !== undefined) data[key] = entityData[key]
|
|
340
|
+
else data[key] = null
|
|
334
341
|
}
|
|
335
|
-
|
|
336
|
-
|
|
342
|
+
warnUndeclaredBlocks(block, declared)
|
|
343
|
+
block.parsedContent.data = data
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Say once, in dev, that a tagged data block did not reach its section's component — its
|
|
348
|
+
* key is not declared. The block is still in `content.sequence`, where a component that
|
|
349
|
+
* renders the sequence finds it.
|
|
350
|
+
*/
|
|
351
|
+
const warnedBlocks = new Set()
|
|
352
|
+
function warnUndeclaredBlocks(block, declared) {
|
|
353
|
+
if (!block.website?.entityStore?.dev) return
|
|
354
|
+
const keys = new Set(declared.map(([key]) => key))
|
|
355
|
+
for (const item of block.parsedContent?.sequence || []) {
|
|
356
|
+
if (item?.type !== 'dataBlock' || typeof item.tag !== 'string' || keys.has(item.tag)) continue
|
|
357
|
+
const memo = `${block.type}::${item.tag}`
|
|
358
|
+
if (warnedBlocks.has(memo)) continue
|
|
359
|
+
warnedBlocks.add(memo)
|
|
360
|
+
console.warn(
|
|
361
|
+
`[uniweb] ${block.type}: the \`${item.tag}\` data block is not in content.data — ${block.type} does not ` +
|
|
362
|
+
`declare \`${item.tag}\` in its meta.js \`data:\`. It stays in content.sequence.`
|
|
363
|
+
)
|
|
337
364
|
}
|
|
338
365
|
}
|
|
339
366
|
|
|
@@ -434,8 +461,9 @@ function runPropsHandler(content, params, block) {
|
|
|
434
461
|
* renderers (`BlockRenderer.jsx` CSR and `ssr-renderer.js` SSG) share
|
|
435
462
|
* the same code path:
|
|
436
463
|
*
|
|
437
|
-
* 1.
|
|
438
|
-
*
|
|
464
|
+
* 1. Assemble `block.parsedContent.data` from the keys the component
|
|
465
|
+
* declares: what the section holds, else what EntityStore delivered,
|
|
466
|
+
* else `null` (`assembleData`).
|
|
439
467
|
* 2. Run the foundation data handler (if registered) to filter or
|
|
440
468
|
* reshape the assembled data.
|
|
441
469
|
* 3. Run the foundation content handler (if registered) on the
|
|
@@ -456,7 +484,11 @@ function runPropsHandler(content, params, block) {
|
|
|
456
484
|
* @returns {Object} Prepared props: { content, params }
|
|
457
485
|
*/
|
|
458
486
|
export function prepareProps(block, meta, entityData = null) {
|
|
459
|
-
|
|
487
|
+
assembleData(block, meta, entityData)
|
|
488
|
+
// ⭐ A list the section held before the store answered — its own fetch, prerendered
|
|
489
|
+
// into its content by a static build — gets its records' `$route` by the store's rule,
|
|
490
|
+
// which the store did not deliver it by (2026-09-14).
|
|
491
|
+
block.website?.entityStore?.linkOwnRecords?.(block)
|
|
460
492
|
runDataHandler(block)
|
|
461
493
|
runContentHandler(block)
|
|
462
494
|
|
package/src/ssr-renderer.js
CHANGED
|
@@ -231,8 +231,8 @@ export function renderBlock(block, { as = 'section' } = {}) {
|
|
|
231
231
|
}, `Component not found: ${block.type}`)
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
// Resolve
|
|
235
|
-
//
|
|
234
|
+
// Resolve entity data synchronously (SSG has no async): EntityStore fills the keys
|
|
235
|
+
// the component declares (`meta.data`) from the fetches that reach the block.
|
|
236
236
|
const meta = getComponentMeta(block.type)
|
|
237
237
|
const entityStore = block.website?.entityStore
|
|
238
238
|
let entityData = null
|