Repository navigation
Add typed ICU localisation and compiled Svelte integration - #3
Draft
elucidsoft wants to merge 14 commits into
Draft
elucidsoft wants to merge 14 commits into
elucidsoft wants to merge 14 commits into
Conversation
A legacy-alias redirect in StateConfig.redirects (e.g. /jobs -> /activity) dropped the original request's query string and hash, because runPipeline() built the recursive navigation's path from the bare redirect target alone. A shared filtered link (/jobs?status=error) lost its filter the moment the alias redirected. Navigator.mergeRedirectTarget() reparses the redirect target and recombines pathname+search+hash, letting a target-declared component win over the original request's so ordering stays valid regardless of which component the target itself carries. RouteMatcher.match()'s pathname-only contract is untouched. Regression: BUG-07-098 (cloudlayerio bug-tracker).
BUG-07-098's matrix covered single-hop redirects only. Each hop of runPipeline() reparses the CURRENT request's path, so a second config redirect chained onto the first needs its own pin proving the already-merged query from hop one survives hop two, rather than the carry only holding at the outermost call. Found during BUG-07-098 Plan TPR (codex).
The two-hop chain pin added at BUG-07-098 Plan TPR Round 0 only exercised the case where neither hop's target declares its own query. Missing cell: hop one's target owns a query (winning per §03.4's single-hop precedence), which then has to survive being reparsed as hop two's own request rather than losing to the true original request's query. Found during BUG-07-098 Plan TPR Round 1 (opencode).
Round 1's hop-one-target-owned-query pin has no hash counterpart. The merge treats search and hash symmetrically by construction, but the matrix had no test proving it — a fix that only special-cased query across hops would still pass every existing case. Found during BUG-07-098 Plan TPR Round 2 (codex).
Two precedent single-hop cases each pinned one owned component in isolation (query-only, hash-only). Neither proved a target owning BOTH components at once carries both — a fix that checked only one component before falling back to the original request could still pass both isolated cases while dropping the other here. Found during BUG-07-098 Plan TPR Round 3 (codex).
The JSDoc claimed StateConfig.redirects entries "are bare pathnames" as a general fact. The type is Record<string, string> — nothing forces bare pathnames structurally, and mergeRedirectTarget() itself handles a target that declares its own query/hash. Scoped the claim to what every current consumer declares. Found during BUG-07-098 Plan TPR Round 4 (codex).
The single-hop both-components-owned case and the two-hop single-component cases were each pinned separately, but nothing combined them: hop one's target owning both query and hash still had to survive being reparsed as hop two's own request. Found during BUG-07-098 Plan TPR Round 4 (codex).
Every prior two-hop case gave hop two a bare target, so the merge's precedence logic was only ever exercised fresh at hop one. This pins that hop two's own declared query/hash wins over whatever hop one produced, proving the merge re-evaluates precedence at each hop rather than treating the prior hop's output as immutable. Found during BUG-07-098 Plan TPR Round 5 (codex).
The Round 5 "hop-two owns both components" case passed even with mergeRedirectTarget() reverted: a target owning both components is indistinguishable from a no-merge implementation, since its own literal redirect string already equals the expected output regardless of merge logic. Redesigned to own only the hash (forcing the query to still be carried from a bare hop one), verified failing without the fix. Added the query-only mirror to complete the hop-two partial-ownership cell. Found during BUG-07-098 Plan TPR Round 6 (agy + codex).
The no-match-to-default branch already had a negative pin proving its query-dropping behavior is unchanged. The state-mismatch-to-default and beforeNavigate-hook redirect branches — the other two mechanisms BUG-07-098's root cause analysis explicitly scoped out — had none, leaving the scope boundary only two-thirds clamped. Found during BUG-07-098 Plan TPR Round 8 (codex).
…e duplication
A live rebuild of this package's dist/ while a consumer's Vite dev server
holds it open via a symlink can serve two distinct module instances of
context.ts to different import chains in one page load. With a local
Symbol('warpkit-v2'), the two instances produced two different context
keys, so setContext in one and getContext in the other never matched —
surfacing as "usePage must be called within WarpKitProvider" even though
the component tree was correctly nested. Symbol.for resolves to the same
global registry entry regardless of how many times the module is
evaluated, closing this class of dev-time duplication bug.
…as core Sibling instance of the WARPKIT_CONTEXT fix (f2509d0): a local Symbol() context key breaks setContext/getContext matching across duplicate module instances Vite's dev server can serve when this package's dist/ is rebuilt live under a consumer app's already-open dev server.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Applications need one localisation API that works across browser UI and request-scoped server/email rendering. This adds optional
@warpkit/i18n: consumer-owned locales and catalogues, typed ICU message parameters, strict catalogue validation, locale negotiation, and explicit timezone formatting.The optional Svelte context updates text and formatting without navigation or remounting. Browser and server exports contain compiled JavaScript; consumers do not compile framework runes. Tests import the public exports and verify dirty input, focus, operation identity, provider isolation, cleanup and declaration errors. There are no product-specific messages, languages or policies in the runtime.
Build/publish registration and the public guide are included. Browser verification also found a test-helper compatibility defect: awaiting the renderer preserves the added WarpKit handle when the renderer is thenable. Its regression test and stale missing-route fixtures are corrected.
Validation:
Catalogues are eager in this initial API. Translation quality, language selection, persistence, URL policy and lazy resource loading remain consumer responsibilities or future framework enhancements. No package has been published. The external review runtime was unavailable locally (
scripts/tooling-python.shis absent); these checks are not an independent-review result.