@furystack/shades 13.2.1 → 14.0.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/CHANGELOG.md +150 -0
- package/esm/components/define-nested-routes.d.ts +27 -0
- package/esm/components/define-nested-routes.d.ts.map +1 -0
- package/esm/components/define-nested-routes.js +26 -0
- package/esm/components/define-nested-routes.js.map +1 -0
- package/esm/components/define-nested-routes.spec.d.ts +2 -0
- package/esm/components/define-nested-routes.spec.d.ts.map +1 -0
- package/esm/components/define-nested-routes.spec.js +81 -0
- package/esm/components/define-nested-routes.spec.js.map +1 -0
- package/esm/components/index.d.ts +3 -3
- package/esm/components/index.d.ts.map +1 -1
- package/esm/components/index.js +3 -3
- package/esm/components/index.js.map +1 -1
- package/esm/components/nested-hooks.d.ts +62 -0
- package/esm/components/nested-hooks.d.ts.map +1 -0
- package/esm/components/nested-hooks.js +73 -0
- package/esm/components/nested-hooks.js.map +1 -0
- package/esm/components/nested-hooks.spec.d.ts +2 -0
- package/esm/components/nested-hooks.spec.d.ts.map +1 -0
- package/esm/components/nested-hooks.spec.js +211 -0
- package/esm/components/nested-hooks.spec.js.map +1 -0
- package/esm/components/nested-navigate.d.ts +52 -21
- package/esm/components/nested-navigate.d.ts.map +1 -1
- package/esm/components/nested-navigate.js +32 -17
- package/esm/components/nested-navigate.js.map +1 -1
- package/esm/components/nested-navigate.spec.js +102 -12
- package/esm/components/nested-navigate.spec.js.map +1 -1
- package/esm/components/nested-replace.d.ts +36 -0
- package/esm/components/nested-replace.d.ts.map +1 -0
- package/esm/components/nested-replace.js +38 -0
- package/esm/components/nested-replace.js.map +1 -0
- package/esm/components/nested-replace.spec.d.ts +2 -0
- package/esm/components/nested-replace.spec.d.ts.map +1 -0
- package/esm/components/nested-replace.spec.js +59 -0
- package/esm/components/nested-replace.spec.js.map +1 -0
- package/esm/components/nested-route-link.d.ts +36 -26
- package/esm/components/nested-route-link.d.ts.map +1 -1
- package/esm/components/nested-route-link.js +17 -19
- package/esm/components/nested-route-link.js.map +1 -1
- package/esm/components/nested-route-link.spec.js +61 -11
- package/esm/components/nested-route-link.spec.js.map +1 -1
- package/esm/components/nested-route-types.d.ts +79 -2
- package/esm/components/nested-route-types.d.ts.map +1 -1
- package/esm/components/nested-router.d.ts +77 -7
- package/esm/components/nested-router.d.ts.map +1 -1
- package/esm/components/nested-router.js +137 -11
- package/esm/components/nested-router.js.map +1 -1
- package/esm/components/nested-router.spec.js +265 -34
- package/esm/components/nested-router.spec.js.map +1 -1
- package/esm/services/location-service.spec.js +33 -0
- package/esm/services/location-service.spec.js.map +1 -1
- package/esm/services/route-match-service.spec.js +4 -0
- package/esm/services/route-match-service.spec.js.map +1 -1
- package/esm/services/route-meta-utils.d.ts +28 -6
- package/esm/services/route-meta-utils.d.ts.map +1 -1
- package/esm/services/route-meta-utils.js +18 -4
- package/esm/services/route-meta-utils.js.map +1 -1
- package/esm/services/route-meta-utils.spec.js +57 -2
- package/esm/services/route-meta-utils.spec.js.map +1 -1
- package/esm/vnode.d.ts +1 -1
- package/esm/vnode.js +1 -1
- package/package.json +9 -9
- package/src/components/define-nested-routes.spec.ts +91 -0
- package/src/components/define-nested-routes.ts +27 -0
- package/src/components/index.ts +3 -3
- package/src/components/nested-hooks.spec.ts +254 -0
- package/src/components/nested-hooks.ts +109 -0
- package/src/components/nested-navigate.spec.ts +128 -25
- package/src/components/nested-navigate.ts +75 -26
- package/src/components/nested-replace.spec.ts +88 -0
- package/src/components/nested-replace.ts +46 -0
- package/src/components/nested-route-link.spec.tsx +84 -16
- package/src/components/nested-route-link.tsx +53 -28
- package/src/components/nested-route-types.ts +82 -2
- package/src/components/nested-router.spec.tsx +316 -33
- package/src/components/nested-router.tsx +182 -22
- package/src/services/location-service.spec.ts +39 -0
- package/src/services/route-match-service.spec.ts +4 -0
- package/src/services/route-meta-utils.spec.ts +75 -7
- package/src/services/route-meta-utils.ts +44 -15
- package/src/vnode.ts +1 -1
- package/esm/components/link-to-route.d.ts +0 -10
- package/esm/components/link-to-route.d.ts.map +0 -1
- package/esm/components/link-to-route.js +0 -16
- package/esm/components/link-to-route.js.map +0 -1
- package/esm/components/link-to-route.spec.d.ts +0 -2
- package/esm/components/link-to-route.spec.d.ts.map +0 -1
- package/esm/components/link-to-route.spec.js +0 -30
- package/esm/components/link-to-route.spec.js.map +0 -1
- package/esm/components/route-link.d.ts +0 -10
- package/esm/components/route-link.d.ts.map +0 -1
- package/esm/components/route-link.js +0 -25
- package/esm/components/route-link.js.map +0 -1
- package/esm/components/route-link.spec.d.ts +0 -2
- package/esm/components/route-link.spec.d.ts.map +0 -1
- package/esm/components/route-link.spec.js +0 -34
- package/esm/components/route-link.spec.js.map +0 -1
- package/esm/components/router.d.ts +0 -44
- package/esm/components/router.d.ts.map +0 -1
- package/esm/components/router.js +0 -66
- package/esm/components/router.js.map +0 -1
- package/esm/components/router.spec.d.ts +0 -2
- package/esm/components/router.spec.d.ts.map +0 -1
- package/esm/components/router.spec.js +0 -161
- package/esm/components/router.spec.js.map +0 -1
- package/src/components/link-to-route.spec.tsx +0 -45
- package/src/components/link-to-route.tsx +0 -26
- package/src/components/route-link.spec.tsx +0 -44
- package/src/components/route-link.tsx +0 -29
- package/src/components/router.spec.tsx +0 -217
- package/src/components/router.tsx +0 -103
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,155 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [14.0.0] - 2026-04-22
|
|
4
|
+
|
|
5
|
+
### 💥 Breaking Changes
|
|
6
|
+
|
|
7
|
+
### Removed the legacy flat router, `RouteLink`, and `LinkToRoute`
|
|
8
|
+
|
|
9
|
+
The long-deprecated single-level `Router` component, its supporting `Route` / `RouterProps` / `RouterState` types, and the legacy `RouteLink` / `LinkToRoute` navigation components have been removed. They were superseded by the nested router stack (`NestedRouter`, `NestedRouteLink`, `createNestedRouteLink`, `nestedNavigate`, etc.) and marked `@deprecated` for several releases.
|
|
10
|
+
|
|
11
|
+
**Removed exports:**
|
|
12
|
+
|
|
13
|
+
- `Router`, `RouterProps`, `RouterState`, `Route`
|
|
14
|
+
- `RouteLink`, `RouteLinkProps`
|
|
15
|
+
- `LinkToRoute`, `LinkToRouteProps`
|
|
16
|
+
|
|
17
|
+
**Impact:** Any module still importing `Router`, `RouteLink`, or `LinkToRoute` from `@furystack/shades` will fail to resolve.
|
|
18
|
+
|
|
19
|
+
**Migration:** Replace flat routers with `NestedRouter` + `defineNestedRoutes`, and swap `RouteLink` / `LinkToRoute` for `NestedRouteLink` (or the route-tree-aware `createNestedRouteLink<typeof routes>()` factory). See the `NestedRouter` section in the package README for the migration recipe.
|
|
20
|
+
|
|
21
|
+
### `NestedRouteLink` and `nestedNavigate` now accept a `path` prop / object argument
|
|
22
|
+
|
|
23
|
+
`NestedRouteLink` now uses `path` instead of `href`, matching the route-definition vocabulary used by `Breadcrumb` and the new navigation helpers. `nestedNavigate` / `createNestedNavigate` switched from positional arguments to an options object so that the new `query` and `hash` fields can be passed alongside `path` / `params` without a growing parameter list.
|
|
24
|
+
|
|
25
|
+
**Before:**
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
<NestedRouteLink href="/users/:id" params={{ id: '1' }}>User</NestedRouteLink>
|
|
29
|
+
|
|
30
|
+
nestedNavigate(injector, '/users/:id', { id: '1' })
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**After:**
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
<NestedRouteLink path="/users/:id" params={{ id: '1' }}>User</NestedRouteLink>
|
|
37
|
+
|
|
38
|
+
nestedNavigate(injector, { path: '/users/:id', params: { id: '1' } })
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Impact:** Every call site of `NestedRouteLink`, `nestedNavigate`, `createNestedRouteLink` and `createNestedNavigate` must be updated. Wrappers that forward `NestedRouteLinkProps` (for example `AppBarLink` in `@furystack/shades-common-components`) also switched to `path`.
|
|
42
|
+
|
|
43
|
+
**Migration:** Rename `href` → `path` on every `NestedRouteLink` call site, and rewrite `nestedNavigate(injector, path, params?)` as `nestedNavigate(injector, { path, params })`.
|
|
44
|
+
|
|
45
|
+
### `NestedRoute` gained two optional generic parameters
|
|
46
|
+
|
|
47
|
+
`NestedRoute<TMatchResult>` is now `NestedRoute<TMatchResult, TQuery, THash>`. Existing single-generic usages keep working through the defaults, but the `component` opts are now always called with `query` and `hash` fields (populated with `null` / `undefined` when the route declares no schema). `MatchChainEntry` likewise carries `query: unknown` and `hash: string | undefined` fields.
|
|
48
|
+
|
|
49
|
+
**Impact:** Test fixtures that construct `MatchChainEntry` literals by hand must supply `query` and `hash`. Components that destructure `component` opts by name are unaffected.
|
|
50
|
+
|
|
51
|
+
**Migration:** Add `query: null, hash: undefined` to any hand-rolled `MatchChainEntry` literal (typically in tests).
|
|
52
|
+
|
|
53
|
+
### ✨ Features
|
|
54
|
+
|
|
55
|
+
### Route-level `hash` and `query` schemas
|
|
56
|
+
|
|
57
|
+
`NestedRoute` can now declare a readonly tuple of allowed hash literals and a query-string validator. Both flow through the new `createNestedRouteLink` / `createNestedNavigate` / `createNestedHooks` helpers to constrain call sites at compile time and surface typed values to the route's `component` opts at render time.
|
|
58
|
+
|
|
59
|
+
**Usage:**
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
const routes = defineNestedRoutes({
|
|
63
|
+
'/users/:id': {
|
|
64
|
+
hash: ['profile', 'settings'] as const,
|
|
65
|
+
query: (raw): { page: number } | null =>
|
|
66
|
+
typeof raw.page === 'number' ? { page: raw.page } : null,
|
|
67
|
+
component: ({ match, query, hash }) => <UserPage match={match} query={query} hash={hash} />,
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const AppLink = createNestedRouteLink<typeof routes>()
|
|
72
|
+
const appNavigate = createNestedNavigate<typeof routes>()
|
|
73
|
+
|
|
74
|
+
<AppLink path="/users/:id" params={{ id: '1' }} query={{ page: 2 }} hash="profile">User</AppLink>
|
|
75
|
+
appNavigate(injector, { path: '/users/:id', params: { id: '1' }, hash: 'settings' })
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- The router matches on path only — an invalid query / hash never prevents navigation. Components receive `query: null` or `hash: undefined` when the URL does not satisfy the declared schema.
|
|
79
|
+
- Query serialization uses the existing `@furystack/rest` encoder, so any JSON-serializable shape round-trips without a schema library dependency.
|
|
80
|
+
|
|
81
|
+
### `defineNestedRoutes` helper
|
|
82
|
+
|
|
83
|
+
`defineNestedRoutes(...)` is an identity helper that preserves the exact inferred literal type of a route tree while still applying a structural `Record<string, NestedRoute<...>>` constraint. Using a plain `satisfies` assertion with the historical bound `NestedRoute<any>` collapsed per-route generics to their defaults, which defeated the downstream extractors used by `createNestedRouteLink` / `createNestedNavigate` / `createNestedHooks`. Declaring route trees through `defineNestedRoutes` keeps the literal shape intact so each route's declared query validator return type and hash literal tuple remain recoverable.
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
export const appRoutes = defineNestedRoutes({
|
|
87
|
+
'/tabs': { hash: ['a', 'b'] as const, component: () => <div /> },
|
|
88
|
+
})
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### `createNestedHooks` factory
|
|
92
|
+
|
|
93
|
+
`createNestedHooks(routes)` returns `{ getTypedQuery, getTypedHash }`, synchronous read helpers that look up the route declared at a given path and narrow the current URL's query / hash against its schema. The route tree is captured at factory time, so call sites only pass `(injector, path)` and the type-level narrowing is inferred from the tree. Intended for non-component consumers (services, side effects) that need a typed snapshot without subscribing through the router.
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
const { getTypedQuery, getTypedHash } = createNestedHooks(routes)
|
|
97
|
+
const query = getTypedQuery(injector, '/users/:id') // typed | null
|
|
98
|
+
const hash = getTypedHash(injector, '/users/:id') // typed | undefined
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### `buildNestedNavigateUrl` utility
|
|
102
|
+
|
|
103
|
+
Exposed the URL-composition helper used internally by `nestedNavigate` and `NestedRouteLink` so callers can produce a compiled URL (path + query + hash) without triggering navigation.
|
|
104
|
+
|
|
105
|
+
### Strongly-typed `extractNavTree` / `NavTreeNode<TRoutes>`
|
|
106
|
+
|
|
107
|
+
`extractNavTree` is now generic over the route tree it is called with, and returns `NavTreeNode<TRoutes>[]` instead of the previous loosely-typed `NavTreeNode[]`. On each node `pattern` is narrowed to `keyof TRoutes & string` and `fullPath` is narrowed to `ExtractRoutePaths<TRoutes> & string`, so the result feeds directly into `createNestedRouteLink` / `createNestedNavigate` / `createNestedReplace` / `createAppBarLink` without an `as` cast at the call site. Consumers that still reference `NavTreeNode` without a type argument keep compiling via a widened default parameter, preserving backward compatibility.
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { extractNavTree, type NavTreeNode } from '@furystack/shades'
|
|
111
|
+
|
|
112
|
+
const tree = extractNavTree(appRoutes)
|
|
113
|
+
// tree[0].fullPath is 'ExtractRoutePaths<typeof appRoutes>', not `string`.
|
|
114
|
+
|
|
115
|
+
const AppLink = createNestedRouteLink<typeof appRoutes>()
|
|
116
|
+
tree.map((node) => <AppLink path={node.fullPath}>{node.meta?.title}</AppLink>)
|
|
117
|
+
|
|
118
|
+
// Widened default is unchanged
|
|
119
|
+
const loose: NavTreeNode = { pattern: '/anything', fullPath: '/anything' }
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### `nestedReplace` / `createNestedReplace`
|
|
123
|
+
|
|
124
|
+
Symmetric counterparts to `nestedNavigate` / `createNestedNavigate` that call `history.replaceState` (via `LocationService.replace`) instead of `pushState`. Use this for SPA redirects — auth guards, canonicalization — where the intermediate URL should not be recoverable with the browser's Back button. Accepts the exact same object-argument shape and inherits the full type-safe narrowing of `path` / `params` / `query` / `hash` against the route tree.
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
const appReplace = createNestedReplace<typeof appRoutes>()
|
|
128
|
+
|
|
129
|
+
// Unauthenticated visitor → send to /login without polluting history
|
|
130
|
+
appReplace(injector, { path: '/login' })
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### ♻️ Refactoring
|
|
134
|
+
|
|
135
|
+
- The nested router now subscribes to query-string and hash changes in addition to path changes, re-rendering the matched chain without firing `onLeave` / `onVisit` lifecycle hooks when only the URL's search or hash segment changes.
|
|
136
|
+
- Path / query / hash observable bursts from a single `navigate` are now coalesced onto one microtask, so one logical navigation triggers one `updateUrl` run (the `versionRef` guard is retained as a race-safety net).
|
|
137
|
+
- `findDivergenceIndex` keeps its path-only semantics; a separate `hasQueryOrHashChanged` helper drives re-render decisions when the matched chain stays stable but its query / hash differ. Query values are compared with a key-order-independent shallow equality helper instead of `JSON.stringify`.
|
|
138
|
+
- `enrichMatchChain` short-circuits when no chain entry declares `query` or `hash`, returning the input array reference to avoid a per-navigation allocation on the common path-only case.
|
|
139
|
+
- New low-level exports surfaced for advanced routing integrations: `enrichMatchChain`, `hasQueryOrHashChanged`, and the supporting types `QueryValidator`, `HashLiterals`, `ExtractRouteQuery`, `ExtractRouteHash`, `RouteAt`, `TypedParamsArg`, `TypedQueryArg`, `TypedHashArg`, and `TreeAwareNestedRouteLinkProps`.
|
|
140
|
+
|
|
141
|
+
### 🧪 Tests
|
|
142
|
+
|
|
143
|
+
- Added type-level and runtime coverage for the new `query` / `hash` paths on `createNestedNavigate`, `createNestedRouteLink`, and the router's match-chain enrichment.
|
|
144
|
+
- Added a `buildNestedNavigateUrl` suite covering params, query and hash composition.
|
|
145
|
+
- Added `expectTypeOf` assertions for the new generic `extractNavTree` output: `pattern` / `fullPath` narrow to the declared route keys and composed path union for flat and nested typed trees, and the widened `NavTreeNode` default keeps compiling for ad-hoc consumers.
|
|
146
|
+
|
|
147
|
+
## [13.2.2] - 2026-04-17
|
|
148
|
+
|
|
149
|
+
### ⬆️ Dependencies
|
|
150
|
+
|
|
151
|
+
- Raised `path-to-regexp` to ^8.4.2, `jsdom` to ^29.0.2, `@types/node` to ^25.6.0, and dev `typescript` to ^6.0.3 and `vitest` to ^4.1.4.
|
|
152
|
+
|
|
3
153
|
## [13.2.1] - 2026-03-27
|
|
4
154
|
|
|
5
155
|
### 🐛 Bug Fixes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { NestedRoute } from './nested-router.js';
|
|
2
|
+
/**
|
|
3
|
+
* Identity helper that preserves the exact inferred literal type of a nested
|
|
4
|
+
* route tree while still applying a structural `Record<string, NestedRoute<...>>`
|
|
5
|
+
* constraint for compile-time validation.
|
|
6
|
+
*
|
|
7
|
+
* Using a plain `satisfies Record<string, NestedRoute<any>>` assertion collapses
|
|
8
|
+
* the per-route `query` / `hash` generics to their defaults, which defeats the
|
|
9
|
+
* type-safe navigation helpers (`createNestedRouteLink`, `createNestedNavigate`,
|
|
10
|
+
* `createNestedHooks`). Declaring route trees through this helper keeps the
|
|
11
|
+
* literal shape intact so downstream extractors can recover each route's
|
|
12
|
+
* declared query validator return type and hash literal tuple.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const routes = defineNestedRoutes({
|
|
17
|
+
* '/users/:id': {
|
|
18
|
+
* component: ({ match, query, hash }) => ...,
|
|
19
|
+
* hash: ['profile', 'settings'] as const,
|
|
20
|
+
* query: (raw): { page: number } | null =>
|
|
21
|
+
* typeof raw.page === 'number' ? { page: raw.page } : null,
|
|
22
|
+
* },
|
|
23
|
+
* })
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare const defineNestedRoutes: <T extends Record<string, NestedRoute<any, any, any>>>(routes: T) => T;
|
|
27
|
+
//# sourceMappingURL=define-nested-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-nested-routes.d.ts","sourceRoot":"","sources":["../../src/components/define-nested-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAG,CAAW,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity helper that preserves the exact inferred literal type of a nested
|
|
3
|
+
* route tree while still applying a structural `Record<string, NestedRoute<...>>`
|
|
4
|
+
* constraint for compile-time validation.
|
|
5
|
+
*
|
|
6
|
+
* Using a plain `satisfies Record<string, NestedRoute<any>>` assertion collapses
|
|
7
|
+
* the per-route `query` / `hash` generics to their defaults, which defeats the
|
|
8
|
+
* type-safe navigation helpers (`createNestedRouteLink`, `createNestedNavigate`,
|
|
9
|
+
* `createNestedHooks`). Declaring route trees through this helper keeps the
|
|
10
|
+
* literal shape intact so downstream extractors can recover each route's
|
|
11
|
+
* declared query validator return type and hash literal tuple.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const routes = defineNestedRoutes({
|
|
16
|
+
* '/users/:id': {
|
|
17
|
+
* component: ({ match, query, hash }) => ...,
|
|
18
|
+
* hash: ['profile', 'settings'] as const,
|
|
19
|
+
* query: (raw): { page: number } | null =>
|
|
20
|
+
* typeof raw.page === 'number' ? { page: raw.page } : null,
|
|
21
|
+
* },
|
|
22
|
+
* })
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export const defineNestedRoutes = (routes) => routes;
|
|
26
|
+
//# sourceMappingURL=define-nested-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-nested-routes.js","sourceRoot":"","sources":["../../src/components/define-nested-routes.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAuD,MAAS,EAAK,EAAE,CAAC,MAAM,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-nested-routes.spec.d.ts","sourceRoot":"","sources":["../../src/components/define-nested-routes.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { describe, expect, expectTypeOf, it } from 'vitest';
|
|
2
|
+
import { defineNestedRoutes } from './define-nested-routes.js';
|
|
3
|
+
const makeComponent = () => null;
|
|
4
|
+
describe('defineNestedRoutes', () => {
|
|
5
|
+
it('Should return the same object reference at runtime', () => {
|
|
6
|
+
const input = {
|
|
7
|
+
'/tabs': {
|
|
8
|
+
component: () => makeComponent(),
|
|
9
|
+
hash: ['a', 'b'],
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
const result = defineNestedRoutes(input);
|
|
13
|
+
expect(result).toBe(input);
|
|
14
|
+
});
|
|
15
|
+
it('Should accept values that satisfy Record<string, NestedRoute<...>>', () => {
|
|
16
|
+
const routes = defineNestedRoutes({
|
|
17
|
+
'/bare': { component: () => makeComponent() },
|
|
18
|
+
'/tabs': {
|
|
19
|
+
component: () => makeComponent(),
|
|
20
|
+
hash: ['a', 'b'],
|
|
21
|
+
query: (raw) => (typeof raw.page === 'number' ? { page: raw.page } : null),
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
expect(Object.keys(routes)).toEqual(['/bare', '/tabs']);
|
|
25
|
+
});
|
|
26
|
+
describe('Type preservation', () => {
|
|
27
|
+
it('Should preserve `hash` as a readonly tuple of literal values', () => {
|
|
28
|
+
const routes = defineNestedRoutes({
|
|
29
|
+
'/tabs': {
|
|
30
|
+
component: () => makeComponent(),
|
|
31
|
+
hash: ['overview', 'details'],
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
expectTypeOf(routes['/tabs'].hash).toEqualTypeOf();
|
|
35
|
+
});
|
|
36
|
+
it('Should preserve the declared return type of a `query` validator', () => {
|
|
37
|
+
const routes = defineNestedRoutes({
|
|
38
|
+
'/list': {
|
|
39
|
+
component: () => makeComponent(),
|
|
40
|
+
query: (raw) => (typeof raw.page === 'number' ? { page: raw.page } : null),
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
expectTypeOf().toEqualTypeOf();
|
|
44
|
+
});
|
|
45
|
+
it('Should preserve nested children literals', () => {
|
|
46
|
+
const routes = defineNestedRoutes({
|
|
47
|
+
'/navigation': {
|
|
48
|
+
component: () => makeComponent(),
|
|
49
|
+
children: {
|
|
50
|
+
'/tabs': {
|
|
51
|
+
component: () => makeComponent(),
|
|
52
|
+
hash: ['a'],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
expectTypeOf().toEqualTypeOf();
|
|
58
|
+
});
|
|
59
|
+
it('Should reject values that do not satisfy the NestedRoute constraint', () => {
|
|
60
|
+
// @ts-expect-error -- `component` is required on every route entry
|
|
61
|
+
defineNestedRoutes({ '/invalid': { hash: ['a'] } });
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('Satisfies-collapse regression coverage', () => {
|
|
65
|
+
it('Should keep literal shape intact (unlike a bare `satisfies` assertion)', () => {
|
|
66
|
+
// A plain `satisfies` on `Record<string, NestedRoute<any>>` would widen
|
|
67
|
+
// the per-route `hash` to `readonly any[]` and drop the literal tuple.
|
|
68
|
+
// `defineNestedRoutes` must preserve the narrow tuple so downstream
|
|
69
|
+
// type extractors (`ExtractRouteHash`, `RouteAt`) can recover it.
|
|
70
|
+
const routes = defineNestedRoutes({
|
|
71
|
+
'/tabs': {
|
|
72
|
+
component: () => makeComponent(),
|
|
73
|
+
hash: ['overview'],
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
expectTypeOf().not.toEqualTypeOf();
|
|
77
|
+
expectTypeOf().toEqualTypeOf();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=define-nested-routes.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-nested-routes.spec.js","sourceRoot":"","sources":["../../src/components/define-nested-routes.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
export * from './define-nested-routes.js';
|
|
1
2
|
export * from './lazy-load.js';
|
|
2
|
-
export * from './
|
|
3
|
+
export * from './nested-hooks.js';
|
|
3
4
|
export * from './nested-navigate.js';
|
|
5
|
+
export * from './nested-replace.js';
|
|
4
6
|
export * from './nested-route-link.js';
|
|
5
7
|
export * from './nested-route-types.js';
|
|
6
8
|
export * from './nested-router.js';
|
|
7
|
-
export * from './route-link.js';
|
|
8
|
-
export * from './router.js';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAA;AACzC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA"}
|
package/esm/components/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
export * from './define-nested-routes.js';
|
|
1
2
|
export * from './lazy-load.js';
|
|
2
|
-
export * from './
|
|
3
|
+
export * from './nested-hooks.js';
|
|
3
4
|
export * from './nested-navigate.js';
|
|
5
|
+
export * from './nested-replace.js';
|
|
4
6
|
export * from './nested-route-link.js';
|
|
5
7
|
export * from './nested-route-types.js';
|
|
6
8
|
export * from './nested-router.js';
|
|
7
|
-
export * from './route-link.js';
|
|
8
|
-
export * from './router.js';
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAA;AACzC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Injector } from '@furystack/inject';
|
|
2
|
+
import type { ExtractRouteHash, ExtractRouteQuery, ExtractRoutePaths, RouteAt } from './nested-route-types.js';
|
|
3
|
+
import type { NestedRoute } from './nested-router.js';
|
|
4
|
+
/**
|
|
5
|
+
* A pair of synchronous read helpers bound to a specific route tree. Use the
|
|
6
|
+
* factory {@link createNestedHooks} to produce one.
|
|
7
|
+
*/
|
|
8
|
+
export type NestedHooks<TRoutes extends Record<string, NestedRoute<any, any, any>>> = {
|
|
9
|
+
/**
|
|
10
|
+
* Reads and validates the current URL query string against the declared
|
|
11
|
+
* validator of the route at `path`. Returns the typed query value, or
|
|
12
|
+
* `null` when the route has no validator or the current URL's query does
|
|
13
|
+
* not satisfy it.
|
|
14
|
+
*
|
|
15
|
+
* This is a synchronous snapshot — for reactive use, subscribe to
|
|
16
|
+
* `locationService.onDeserializedLocationSearchChanged` and call this read
|
|
17
|
+
* on each change.
|
|
18
|
+
*/
|
|
19
|
+
getTypedQuery: <TPath extends ExtractRoutePaths<TRoutes>>(injector: Injector, path: TPath) => ExtractRouteQuery<RouteAt<TRoutes, TPath>> | null;
|
|
20
|
+
/**
|
|
21
|
+
* Reads the current URL hash and narrows it against the declared literal
|
|
22
|
+
* tuple of the route at `path`. Returns the hash when it matches one of
|
|
23
|
+
* the route's declared literals, or `undefined` otherwise.
|
|
24
|
+
*
|
|
25
|
+
* This is a synchronous snapshot — for reactive use, subscribe to
|
|
26
|
+
* `locationService.onLocationHashChanged` and call this read on each change.
|
|
27
|
+
*/
|
|
28
|
+
getTypedHash: <TPath extends ExtractRoutePaths<TRoutes>>(injector: Injector, path: TPath) => ExtractRouteHash<RouteAt<TRoutes, TPath>> | undefined;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Walks a route tree and returns the route value declared at the given path,
|
|
32
|
+
* matching each URL pattern segment-by-segment. The root `/` pattern is
|
|
33
|
+
* transparent: its children are searched with the full path.
|
|
34
|
+
*
|
|
35
|
+
* Exported for unit testing only — consumers should go through
|
|
36
|
+
* {@link createNestedHooks}.
|
|
37
|
+
*
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
export declare const walkRoute: (routes: Record<string, NestedRoute<any, any, any>>, path: string) => NestedRoute<any, any, any> | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Creates a pair of type-safe synchronous read helpers (`getTypedQuery`,
|
|
43
|
+
* `getTypedHash`) bound to a specific route tree. The returned functions
|
|
44
|
+
* validate the current URL's query and hash against the route declared at
|
|
45
|
+
* the given path, returning typed values or `null`/`undefined` on mismatch.
|
|
46
|
+
*
|
|
47
|
+
* The concrete route tree is captured at factory time, so call sites only
|
|
48
|
+
* pass `(injector, path)`; the type-level narrowing is derived from the
|
|
49
|
+
* inferred tree generic.
|
|
50
|
+
*
|
|
51
|
+
* @typeParam TRoutes - The route tree type (inferred from the `routes` argument)
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const { getTypedQuery, getTypedHash } = createNestedHooks(appRoutes)
|
|
56
|
+
*
|
|
57
|
+
* const query = getTypedQuery(injector, '/users') // typed
|
|
58
|
+
* const hash = getTypedHash(injector, '/users') // typed
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare const createNestedHooks: <TRoutes extends Record<string, NestedRoute<any, any, any>>>(routes: TRoutes) => NestedHooks<TRoutes>;
|
|
62
|
+
//# sourceMappingURL=nested-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nested-hooks.d.ts","sourceRoot":"","sources":["../../src/components/nested-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAC9G,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD;;;GAGG;AACH,MAAM,MAAM,WAAW,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI;IACpF;;;;;;;;;OASG;IACH,aAAa,EAAE,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,EACtD,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,KAAK,KACR,iBAAiB,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;IACtD;;;;;;;OAOG;IACH,YAAY,EAAE,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,EACrD,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,KAAK,KACR,gBAAgB,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,GAAG,SAAS,CAAA;CAC3D,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,SAAS,GACpB,QAAQ,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,EAClD,MAAM,MAAM,KACX,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,SAe/B,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,EAC1F,QAAQ,OAAO,KACd,WAAW,CAAC,OAAO,CAkBrB,CAAA"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { LocationService } from '../services/location-service.js';
|
|
2
|
+
/**
|
|
3
|
+
* Walks a route tree and returns the route value declared at the given path,
|
|
4
|
+
* matching each URL pattern segment-by-segment. The root `/` pattern is
|
|
5
|
+
* transparent: its children are searched with the full path.
|
|
6
|
+
*
|
|
7
|
+
* Exported for unit testing only — consumers should go through
|
|
8
|
+
* {@link createNestedHooks}.
|
|
9
|
+
*
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
export const walkRoute = (routes, path) => {
|
|
13
|
+
for (const [pattern, route] of Object.entries(routes)) {
|
|
14
|
+
if (pattern === path)
|
|
15
|
+
return route;
|
|
16
|
+
if (pattern === '/' && route.children) {
|
|
17
|
+
const nested = walkRoute(route.children, path);
|
|
18
|
+
if (nested)
|
|
19
|
+
return nested;
|
|
20
|
+
}
|
|
21
|
+
else if (route.children && path.startsWith(pattern)) {
|
|
22
|
+
const rest = path.slice(pattern.length);
|
|
23
|
+
if (rest.startsWith('/') || rest === '') {
|
|
24
|
+
const nested = walkRoute(route.children, rest || '/');
|
|
25
|
+
if (nested)
|
|
26
|
+
return nested;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Creates a pair of type-safe synchronous read helpers (`getTypedQuery`,
|
|
34
|
+
* `getTypedHash`) bound to a specific route tree. The returned functions
|
|
35
|
+
* validate the current URL's query and hash against the route declared at
|
|
36
|
+
* the given path, returning typed values or `null`/`undefined` on mismatch.
|
|
37
|
+
*
|
|
38
|
+
* The concrete route tree is captured at factory time, so call sites only
|
|
39
|
+
* pass `(injector, path)`; the type-level narrowing is derived from the
|
|
40
|
+
* inferred tree generic.
|
|
41
|
+
*
|
|
42
|
+
* @typeParam TRoutes - The route tree type (inferred from the `routes` argument)
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const { getTypedQuery, getTypedHash } = createNestedHooks(appRoutes)
|
|
47
|
+
*
|
|
48
|
+
* const query = getTypedQuery(injector, '/users') // typed
|
|
49
|
+
* const hash = getTypedHash(injector, '/users') // typed
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export const createNestedHooks = (routes) => {
|
|
53
|
+
return {
|
|
54
|
+
getTypedQuery: (injector, path) => {
|
|
55
|
+
const route = walkRoute(routes, path);
|
|
56
|
+
if (!route?.query)
|
|
57
|
+
return null;
|
|
58
|
+
const locationService = injector.getInstance(LocationService);
|
|
59
|
+
const deserialized = locationService.onDeserializedLocationSearchChanged.getValue();
|
|
60
|
+
return route.query(deserialized);
|
|
61
|
+
},
|
|
62
|
+
getTypedHash: (injector, path) => {
|
|
63
|
+
const route = walkRoute(routes, path);
|
|
64
|
+
const declaredHash = route?.hash;
|
|
65
|
+
if (!declaredHash)
|
|
66
|
+
return undefined;
|
|
67
|
+
const locationService = injector.getInstance(LocationService);
|
|
68
|
+
const currentHash = locationService.onLocationHashChanged.getValue();
|
|
69
|
+
return declaredHash.includes(currentHash) ? currentHash : undefined;
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=nested-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nested-hooks.js","sourceRoot":"","sources":["../../src/components/nested-hooks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AAqCjE;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,MAAkD,EAClD,IAAY,EAC4B,EAAE;IAC1C,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACtD,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,KAAK,CAAA;QAClC,IAAI,OAAO,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;YAC9C,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAA;QAC3B,CAAC;aAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACtD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;YACvC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;gBACxC,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,IAAI,GAAG,CAAC,CAAA;gBACrD,IAAI,MAAM;oBAAE,OAAO,MAAM,CAAA;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,MAAe,EACO,EAAE;IACxB,OAAO;QACL,aAAa,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE;YAChC,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;YACrC,IAAI,CAAC,KAAK,EAAE,KAAK;gBAAE,OAAO,IAAI,CAAA;YAC9B,MAAM,eAAe,GAAG,QAAQ,CAAC,WAAW,CAAC,eAAe,CAAC,CAAA;YAC7D,MAAM,YAAY,GAAG,eAAe,CAAC,mCAAmC,CAAC,QAAQ,EAAE,CAAA;YACnF,OAAO,KAAK,CAAC,KAAK,CAAC,YAAY,CAAU,CAAA;QAC3C,CAAC;QACD,YAAY,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE;YAC/B,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;YACrC,MAAM,YAAY,GAAG,KAAK,EAAE,IAAqC,CAAA;YACjE,IAAI,CAAC,YAAY;gBAAE,OAAO,SAAS,CAAA;YACnC,MAAM,eAAe,GAAG,QAAQ,CAAC,WAAW,CAAC,eAAe,CAAC,CAAA;YAC7D,MAAM,WAAW,GAAG,eAAe,CAAC,qBAAqB,CAAC,QAAQ,EAAE,CAAA;YACpE,OAAO,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAE,WAAqB,CAAC,CAAC,CAAC,SAAS,CAAA;QAChF,CAAC;KACF,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nested-hooks.spec.d.ts","sourceRoot":"","sources":["../../src/components/nested-hooks.spec.ts"],"names":[],"mappings":""}
|