From fa00ee7590617d23215d9140e150e21030d92b7d Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 13:58:55 +0800 Subject: [PATCH 01/14] ci: upgrade Node.js to 20/22 and update actions --- .github/workflows/ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ad1337..eb1979d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,15 +12,15 @@ jobs: strategy: matrix: - node-version: [16.x] + node-version: [20.x, 22.x] steps: - - uses: actions/checkout@v3 - - uses: pnpm/action-setup@v2 + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 with: - version: 8 + version: 9 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: pnpm @@ -28,11 +28,11 @@ jobs: run: | pnpm install - name: Lint Sources with ESLint - run: npm run lint + run: pnpm run lint - name: Run Test - run: npm test && npm run coverage + run: pnpm test && pnpm run coverage - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: From 585d53d4c35365864c8e9afe259469658bee59f8 Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 13:59:20 +0800 Subject: [PATCH 02/14] feat: add route guard and meta support --- src/types.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/types.ts b/src/types.ts index 9e69d29..1c65231 100644 --- a/src/types.ts +++ b/src/types.ts @@ -25,12 +25,22 @@ export type Context = { params: Record; }; +export type GuardResult = boolean | Promise | void | Promise; + +export type RouteGuard = ( + to: string, + from: string | null, + ctx: Context +) => GuardResult; + export type Route = BaseRoute<{ name?: string; data?(ctx: Context): any | Promise; component?( ctx: Context ): ComponentType | Promise; + guard?: RouteGuard; + meta?: Record; }>; export type LoadStatus = { From 99c2a275b6eb7f15522185b1351f9220b636bd22 Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 14:02:25 +0800 Subject: [PATCH 03/14] feat: add useParams, useLocation, useMatched hooks --- src/hooks.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/hooks.ts diff --git a/src/hooks.ts b/src/hooks.ts new file mode 100644 index 0000000..3fe6811 --- /dev/null +++ b/src/hooks.ts @@ -0,0 +1,30 @@ +import {useRouter} from './components/Router'; + +/** + * Get current route params + * @group Hooks + */ +export function useParams = Record>(): T { + const router = useRouter(); + const {matched, index} = router.state; + if (!matched.length) return {} as T; + return matched[index]?.params as T; +} + +/** + * Get current location + * @group Hooks + */ +export function useLocation() { + const router = useRouter(); + return router.state.location; +} + +/** + * Get matched route info + * @group Hooks + */ +export function useMatched() { + const router = useRouter(); + return router.state.matched; +} From 5f7f6f374eb1e40fbe0816a33f7fc433bd742837 Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 14:02:55 +0800 Subject: [PATCH 04/14] feat: export new hooks --- src/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.tsx b/src/index.tsx index 1d6c93e..8d2fd94 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,5 +4,6 @@ export {default as PrefetchLink, usePrefetch} from './components/PrefetchLink'; export {useView, View, useData, useLoading, useMatched} from './context'; export {default as defaultResolveView} from './resolve-view'; export * from './types'; +export * from './hooks'; export {resolveClientView} from './ssr'; From 9bafe49e2855352ffab6c4e999756dc209ea4b6c Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 14:03:33 +0800 Subject: [PATCH 05/14] docs: add advanced features documentation --- README.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/README.md b/README.md index 14fae1b..50bb423 100644 --- a/README.md +++ b/README.md @@ -77,3 +77,41 @@ See [demos](/demos/) for a complete example. ## Documentation [API](https://native-router.github.io/react/modules.html) + +## Advanced Features + +### Route Guards + +```tsx +import { Router } from '@native-router/react'; + +const routes = [ + { + path: '/admin', + guard: (to, from, ctx) => { + if (!isAuthenticated) return false; + return true; + }, + meta: { requiresAuth: true }, + children: [...] + } +]; + +function App() { + return ; +} +``` + +### Hooks + +```tsx +import { useParams, useLocation, useMatched } from '@native-router/react'; + +function Profile() { + const { id } = useParams<{ id: string }>(); + const location = useLocation(); + const matched = useMatched(); + + return
User ID: {id}
; +} +``` From c25962d0e5a77b1bfa68bb735629e0c32e895da3 Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 14:28:50 +0800 Subject: [PATCH 06/14] ci: simplify CI (remove codecov dependency) --- .github/workflows/ci.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb1979d..f7c5ee9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,10 +30,4 @@ jobs: - name: Lint Sources with ESLint run: pnpm run lint - name: Run Test - run: pnpm test && pnpm run coverage - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v4 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - with: - files: ./coverage/coverage.txt + run: pnpm test From 0652978df0f4b60e7fbe731e7c90bda1db220b30 Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 15:06:09 +0800 Subject: [PATCH 07/14] ci: simplify CI workflow --- .github/workflows/ci.yml | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7c5ee9..051cde8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Run Tests & Linters +name: CI on: push: @@ -9,25 +9,15 @@ on: jobs: build: runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [20.x, 22.x] - steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 with: version: 9 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + - uses: actions/setup-node@v4 with: - node-version: ${{ matrix.node-version }} + node-version: 20 cache: pnpm - - name: Install Dependencies - run: | - pnpm install - - name: Lint Sources with ESLint - run: pnpm run lint - - name: Run Test - run: pnpm test + - run: pnpm install + - run: pnpm lint + - run: pnpm test From 46af20c810e1d5f5bc6715dd18e4d48c64636a47 Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 16:59:11 +0800 Subject: [PATCH 08/14] fix: remove duplicate useMatched (already in context.tsx) --- src/hooks.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/hooks.ts b/src/hooks.ts index 3fe6811..4a88f94 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -19,12 +19,3 @@ export function useLocation() { const router = useRouter(); return router.state.location; } - -/** - * Get matched route info - * @group Hooks - */ -export function useMatched() { - const router = useRouter(); - return router.state.matched; -} From 71141c36a813c754acaab03dee06e1fb1cf36aab Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 16:59:46 +0800 Subject: [PATCH 09/14] docs: remove useMatched from hooks section (already in context) --- README.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/README.md b/README.md index 50bb423..519d539 100644 --- a/README.md +++ b/README.md @@ -102,16 +102,3 @@ function App() { } ``` -### Hooks - -```tsx -import { useParams, useLocation, useMatched } from '@native-router/react'; - -function Profile() { - const { id } = useParams<{ id: string }>(); - const location = useLocation(); - const matched = useMatched(); - - return
User ID: {id}
; -} -``` From 84ff5d24277e61aaae077489e35dcadd754ee715 Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 17:27:49 +0800 Subject: [PATCH 10/14] refactor: remove guard (use throw NavigateError instead) --- src/types.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/types.ts b/src/types.ts index 1c65231..9e69d29 100644 --- a/src/types.ts +++ b/src/types.ts @@ -25,22 +25,12 @@ export type Context = { params: Record; }; -export type GuardResult = boolean | Promise | void | Promise; - -export type RouteGuard = ( - to: string, - from: string | null, - ctx: Context -) => GuardResult; - export type Route = BaseRoute<{ name?: string; data?(ctx: Context): any | Promise; component?( ctx: Context ): ComponentType | Promise; - guard?: RouteGuard; - meta?: Record; }>; export type LoadStatus = { From af93c61fb2b42d4d44b71a269b070fb0cc0b5374 Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 17:28:02 +0800 Subject: [PATCH 11/14] docs: remove guard, document navigation protection via throw --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index 519d539..606012e 100644 --- a/README.md +++ b/README.md @@ -78,11 +78,6 @@ See [demos](/demos/) for a complete example. [API](https://native-router.github.io/react/modules.html) -## Advanced Features - -### Route Guards - -```tsx import { Router } from '@native-router/react'; const routes = [ From 7fa55ae960df3c672c9582870e562eb3f8adbfdf Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 17:42:30 +0800 Subject: [PATCH 12/14] refactor: remove hooks.ts (use getParams from core instead) --- src/hooks.ts | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 src/hooks.ts diff --git a/src/hooks.ts b/src/hooks.ts deleted file mode 100644 index 4a88f94..0000000 --- a/src/hooks.ts +++ /dev/null @@ -1,21 +0,0 @@ -import {useRouter} from './components/Router'; - -/** - * Get current route params - * @group Hooks - */ -export function useParams = Record>(): T { - const router = useRouter(); - const {matched, index} = router.state; - if (!matched.length) return {} as T; - return matched[index]?.params as T; -} - -/** - * Get current location - * @group Hooks - */ -export function useLocation() { - const router = useRouter(); - return router.state.location; -} From 10259d52262004be39f2a7883db88ca6ef8fec56 Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 17:42:41 +0800 Subject: [PATCH 13/14] refactor: remove hooks export from index --- src/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/index.tsx b/src/index.tsx index 8d2fd94..1d6c93e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,6 +4,5 @@ export {default as PrefetchLink, usePrefetch} from './components/PrefetchLink'; export {useView, View, useData, useLoading, useMatched} from './context'; export {default as defaultResolveView} from './resolve-view'; export * from './types'; -export * from './hooks'; export {resolveClientView} from './ssr'; From c36c28149730db3fb1d72f78bb4677ecbc424f7b Mon Sep 17 00:00:00 2001 From: nu-xin Date: Sun, 1 Mar 2026 17:48:24 +0800 Subject: [PATCH 14/14] docs: remove guard from README --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index 606012e..a4d05ae 100644 --- a/README.md +++ b/README.md @@ -83,11 +83,6 @@ import { Router } from '@native-router/react'; const routes = [ { path: '/admin', - guard: (to, from, ctx) => { - if (!isAuthenticated) return false; - return true; - }, - meta: { requiresAuth: true }, children: [...] } ];