Repository navigation
feat(observe): declare the route the document arrived on - #623
Conversation
🦋 Changeset detectedLatest commit: f1f0772 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
b5a1cc8 to
94713bc
Compare
The same withOrigin call the router makes for every navigation, around
the work that builds its context, with `initial: true` on the ref — on
both sides. Client: the first "navigation" record names the pageload's
route. Server: the request's "render" record carries RenderEvent.route.
`describeNavigation` and the new `describeInitial` share the match
description (`routeName`/`routeParams`).
Also the rc.10 moves the observe test and this file need: NavigationRef
is exported from `solid-js`, and `attribution.history("navigation")`
replaces `attribution.navigations()`.
Requires the solid release shipping NavigationRef.initial and
RenderEvent.route (solidjs/solid#3683).
Co-Authored-By: Claude via Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…l record, not a navigation The base normalization write (a hash history with no hash, a memory history seeded with "") went through the setter's withOrigin and opened a nested navigation frame that took the write, so the initial record kept the pre-normalization location — `to: ""`, matched to nothing — and a phantom navigation "" -> base followed it. A write from no location is not a navigation: the setter no longer declares it, the write stamps the enclosing initial frame (writes: 1, settles at drain end), and every field of the initial ref is a getter read at settle, so `to`/`name`/`params` are the normalized location on both sides. Co-Authored-By: Claude via Cursor <cursoragent@cursor.com> Co-authored-by: Cursor <cursoragent@cursor.com>
NavigationRef.initial and RenderEvent.route shipped in rc.12; rc.13 is current. The peer floor moves to rc.12, the first release with the fields this declaration uses (and without the sharedConfig types the migration replaces). Co-authored-by: Cursor <cursoragent@cursor.com>
94713bc to
1d21adf
Compare
|
Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # package.json
Co-authored-by: Cursor <cursoragent@cursor.com>
…d's observe tier The Solid adapter declared every navigation's match publish to the observe tier, but the first page has no publish to wrap, so the route the page loaded as was never declared, and on the server the request's "render" record had a URL and no route. solid-js / @solidjs/web 2.0.0-rc.12 added NavigationRef.initial and RenderEvent.route for exactly this; Solid Router adopted them in solidjs/solid-router#623. RouterContextProvider now wraps the work that establishes its initial match (the ready memo, which on the server starts the load) in the same call, with initial: true on the ref: - Client: the engine opens the frame at the time origin and settles it as the provider returns: the first "navigation" record, initial: true, writes: 0, at: 0, no from; kept out of feedback().navigations. - Server: there is no engine; the server entry's withOrigin files the ref on the render, and the "render" record carries RenderEvent.route ({ name, to, params }), read at settle, after a provider-run load. describeInitial shares describeRoute with describeNavigation; its fields are getters over router.latestLocation. The Transitioner's post-mount commit of the canonical arrival location (search defaults, trailing slash) is the arrival's, not a navigation, the TanStack form of TanStack#623's "an empty arrival normalized onto the base". With the router loaded before mount, resolvedLocation was already set and that commit was declared as a navigation from the arrival to itself; without it, the arrival's history change left requestedAt set and the next real navigation was dated from the mount. The commit is now marked, and every non-pending publish answers the pending request, declared or not. Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Stacked on #641 (base branch
migrate-public-hydration-api); GitHub retargets tonextwhen that merges.solid-js/@solidjs/web2.0.0-rc.13shipNavigationRef.initialandRenderEvent.route(solidjs/solid#3683, in rc.12), so this branch bumps to^2.0.0-rc.13and moves the peer floor to^2.0.0-rc.12. Verified on the published packages:pnpm testclient 40 files / 445 tests, server 7 / 44, type tests,pnpm build, attw all green.What
The router already declares every navigation to the observe tier around its location write (
OBSERVE.attribution.withOrigin), so consumers get the route pattern for every navigation — except the first. A fresh document has no location write, so the route the page loaded as was never declared, and on the server the request had a URL and no route.Now
RouterComponentwraps the work that builds its context in the same call, withinitial: trueon the ref:"navigation"record,initial: true,writes: 0,at: 0, nofrom. Kept out offeedback().navigationsby the engine."render"record carriesRenderEvent.route({ name, to, params }), read at settle so a lazy subtree that resolved during the render names the exact route (pinned).describeNavigationanddescribeInitialshare the match description (routeName,routeParams);name/paramsremain getters read at settle.OBSERVE, as the navigation declaration is.Also in this PR (rc.10 moves the touched files need)
NavigationRefis imported fromsolid-js(the frame refs moved besidewithOriginin rc.10).test/observe-navigation.spec.tsxusesattribution.history("navigation")in place of the removedattribution.navigations().Public API
No router option or export changes; one new call site. Peer dependency floor:
solid-js/@solidjs/webpeers move from^2.0.0-rc.10to^2.0.0-rc.12, the first release with the fields this declaration uses (and without thesharedConfigtypes #641 replaces).Tests
test/observe-navigation.spec.tsx+3: mounting declares the initial route (fields,at: 0,writes: 0,committed); an empty arrival normalized ontobaseis that one record (writes: 1), not a navigation; the declaration is not afeedback().navigationsrow.test/server/observe-render-route.spec.tsx(new, 6): url prop, root/, request-event URL precedence, lazy subtree refined at settle (stream path), empty arrival +basenames the render by the base, no router → noroute.Why it matters
Sentry's Performance product (and every peer framework SDK) names transactions by route pattern;
@sentry/solid-2will rename thepageloadroot from the initial record and sethttp.routefromrender.route. Any other Solid router adopts the same contract with the same one call.— Claude via Cursor
Made with Cursor