mikser-io 9.40.2 → 9.40.3
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/docs/diagnostics.md +12 -0
- package/package.json +1 -1
- package/src/manifest.js +41 -0
package/docs/diagnostics.md
CHANGED
|
@@ -563,6 +563,18 @@ cannot model is how the entity's own frontmatter would change — that is
|
|
|
563
563
|
parsed during import, so an edit that moves `meta.layout` moves the
|
|
564
564
|
destination too, and this does not see it.
|
|
565
565
|
|
|
566
|
+
**Layout sidecars are the one entity answered by a different route.** A
|
|
567
|
+
sidecar never renders, nothing points at it by ref, and no query matches
|
|
568
|
+
it, so all three candidate walks come back empty — yet editing one
|
|
569
|
+
re-renders the whole site. Its dependency is the layout's *input digest*,
|
|
570
|
+
not an edge: `mikser-io-layouts` folds every sidecar script under the
|
|
571
|
+
folder into a single `sharedDigest` carried by every layout's checksum, so
|
|
572
|
+
one sidecar edit moves every layout. `affectedBy` therefore reports every
|
|
573
|
+
destination that rendered through any layout, each attributed to the
|
|
574
|
+
layout it went through. Entities with no layout — a copied asset, a
|
|
575
|
+
`files()` passthrough — stay out, or the answer would be "everything,
|
|
576
|
+
always", which is the same non-answer as "nothing" with the sign flipped.
|
|
577
|
+
|
|
566
578
|
### `runtime.provenance`
|
|
567
579
|
|
|
568
580
|
Where a value was **written** — source file, field path, line and column.
|
package/package.json
CHANGED
package/src/manifest.js
CHANGED
|
@@ -484,6 +484,25 @@ export function createManifest(db) {
|
|
|
484
484
|
WHERE refClosure LIKE '%"kind":"query"%'
|
|
485
485
|
`)
|
|
486
486
|
|
|
487
|
+
// Everything that rendered through a layout — the blast radius of a change
|
|
488
|
+
// to a layout SIDECAR.
|
|
489
|
+
//
|
|
490
|
+
// A sidecar is reachable by none of the three routes affectedBy otherwise
|
|
491
|
+
// walks: it never renders, so it has no snapshots; nothing points at it by
|
|
492
|
+
// ref; and no query matches it. Its dependency is the layout's input
|
|
493
|
+
// digest, which is not an edge. So the preview answered "nothing would be
|
|
494
|
+
// affected" for a change that re-renders the entire site — the one
|
|
495
|
+
// direction of wrong that matters, since it says a site-wide edit is safe.
|
|
496
|
+
//
|
|
497
|
+
// The blast radius really is everything: the layouts plugin folds every
|
|
498
|
+
// OTHER sidecar under the folder into each layout's `shared` digest, so any
|
|
499
|
+
// sidecar edit moves every layout's checksum, and every page renders
|
|
500
|
+
// through some layout.
|
|
501
|
+
const stmtSnapshotsWithLayout = db.prepare(`
|
|
502
|
+
SELECT id, destination, refClosure FROM mikser_snapshots
|
|
503
|
+
WHERE refClosure LIKE '%"kind":"layout"%'
|
|
504
|
+
`)
|
|
505
|
+
|
|
487
506
|
// Snapshots holding a non-query edge that names any of the given keys,
|
|
488
507
|
// by the name asked for OR by the entity it bound to. Both, for the same
|
|
489
508
|
// reason skipDecision reads both — a name survives a rename only through
|
|
@@ -572,6 +591,28 @@ export function createManifest(db) {
|
|
|
572
591
|
}
|
|
573
592
|
|
|
574
593
|
const affected = []
|
|
594
|
+
|
|
595
|
+
// Sidecars take the route above rather than the candidate walk:
|
|
596
|
+
// skipDecision compares against the edges a snapshot recorded, and
|
|
597
|
+
// no snapshot records an edge to a sidecar — it would answer "skip"
|
|
598
|
+
// for every page and hide the whole radius.
|
|
599
|
+
if (entity.type === 'sidecar') {
|
|
600
|
+
for (const row of stmtSnapshotsWithLayout.iterate()) {
|
|
601
|
+
let layoutEdge = null
|
|
602
|
+
try {
|
|
603
|
+
layoutEdge = JSON.parse(row.refClosure ?? '[]').find(e => e.kind === 'layout') ?? null
|
|
604
|
+
} catch { /* unreadable closure — still affected, just unattributed */ }
|
|
605
|
+
affected.push({
|
|
606
|
+
id: row.id,
|
|
607
|
+
destination: row.destination,
|
|
608
|
+
reason: 'ref-changed',
|
|
609
|
+
...(layoutEdge?.target ? { dependency: layoutEdge.target } : {}),
|
|
610
|
+
why: 'a layout sidecar feeds every layout through its shared digest',
|
|
611
|
+
})
|
|
612
|
+
}
|
|
613
|
+
return affected
|
|
614
|
+
}
|
|
615
|
+
|
|
575
616
|
for (const { id, destination } of candidates.values()) {
|
|
576
617
|
// Its own renders: the premise of the question is that this
|
|
577
618
|
// entity changed, so asking skipDecision — which compares the
|