tp_router 0.0.2
tp_router: ^0.0.2 copied to clipboard
A simplified Flutter router based on go_router with annotation support.
TpRouter #
| Package | Version |
|---|---|
| tp_router | |
| tp_router_annotation | |
| tp_router_generator |
A simplified, type-safe, and annotation-driven routing library for Flutter, built on top of go_router.
Stop writing boilerplate routing tables manually. Let tp_router handle it for you with strong typing and compile-time safety.
Features #
- 🚀 Annotation Driven: Define routes directly on your widgets using
@TpRoute. - 🛡️ Type-Safe Parsing: Automatically extracts
int,double,bool,String, and complex objects from path, query parameters, or extra data. - 🔄 Smart Redirection: Strong-typed redirection mechanism. Check parameters before navigating.
- 🐚 Shell Routes & Nested Navigation: Full support for
ShellRouteandStatefulShellRoute(IndexedStack). - ⚡ Simple Navigation API: Just call
MyRoute().tp(context).
Installation #
Add the following to your pubspec.yaml:
dependencies:
tp_router: ^0.0.1
tp_router_annotation: ^0.0.1
dev_dependencies:
build_runner: ^2.4.0
tp_router_generator: ^0.0.1
Getting Started #
1. Define Your Routes #
Annotate your widget with @TpRoute.
Constructor arguments are automatically mapped to route parameters!
// lib/pages/user_page.dart
import 'package:flutter/material.dart';
import 'package:tp_router/tp_router.dart';
@TpRoute(path: '/user/:id')
class UserPage extends StatelessWidget {
// Automatically mapped from path parameter ':id'
// Or query parameter 'id', or extra data 'id'.
final int id;
// Optional parameter with default value
final String section;
const UserPage({
required this.id,
this.section = 'profile',
super.key,
});
@override
Widget build(BuildContext context) {
return Text('User $id - Section $section');
}
}
2. Generate Code #
Run the build runner to generate the routing table:
dart run build_runner build
This will generate lib/tp_router.g.dart (default path).
3. Initialize Router #
In your main.dart, initialize TpRouter with the generated routes list.
import 'package:flutter/material.dart';
import 'package:tp_router/tp_router.dart';
import 'tp_router.g.dart'; // Import generated file
void main() {
final router = TpRouter(
routes: tpRoutes, // Generated list of routes
);
runApp(MaterialApp.router(
routerConfig: router.routerConfig,
));
}
Navigation #
Navigate using the generated route classes. This is 100% type-safe.
// Push a new route
UserPage(id: 42).tp(context);
// Replace the current route
LoginPage().tp(context, replacement: true);
// Clear history and go to new route
HomePage().tp(context, clearHistory: true);
// Wait for a result
final result = await SelectProfileRoute().tp<String>(context);
You can also pop:
context.tpRouter.pop('Some Result');
Capabilities #
Parameter Extraction Strategy #
TpRouter smartly resolves constructor parameters in this order:
- Explicit Annotation:
@Path('id')(Force path param) or@Query('q')(Force query param). - Extra Data: Checks if the object was passed via
extramap. - Path Parameters: Checks if the URL path contains the key.
- Query Parameters: Checks the URL query string.
Redirection / Guards #
TpRouter supports a powerful, type-safe redirection system. You can define a redirect function or class that receives the fully instantiated route object.
1. Define a Redirect Logic
// You can access 'route.id' directly!
FutureOr<TpRouteData?> checkUserAccess(BuildContext context, UserRoute route) {
if (route.id == 999) {
// Redirect to blocked page
return const BlockedRoute();
}
return null; // No redirect, proceed to page
}
2. Attach to Route
@TpRoute(path: '/user/:id', redirect: checkUserAccess)
class UserPage extends StatelessWidget { ... }
You can also use a class extending TpRedirect<T> for cleaner organization.
class AuthRedirect extends TpRedirect<ProtectedRoute> {
const AuthRedirect();
@override
FutureOr<TpRouteData?> handle(BuildContext context, ProtectedRoute route) {
if (!AuthService.isLoggedIn) {
return const LoginRoute();
}
return null;
}
}
@TpRoute(path: '/protected', redirect: AuthRedirect)
class ProtectedPage extends StatelessWidget { ... }
Shell Routes (Nested Navigation) #
Use @TpShellRoute or @TpStatefulShellRoute for nested navigation (e.g., Bottom Navigation Bars).
@TpStatefulShellRoute(
branches: [
[HomeRoute],
[SettingsRoute],
],
)
class MainShellPage extends StatelessWidget {
final TpStatefulNavigationShell navigationShell;
const MainShellPage({required this.navigationShell});
@override
Widget build(BuildContext context) {
return Scaffold(
body: navigationShell,
bottomNavigationBar: BottomNavigationBar(
currentIndex: navigationShell.currentIndex,
onTap: (index) => navigationShell.goBranch(index),
items: [ ... ],
),
);
}
}
Configuration #
Custom Output Path #
By default, code is generated in lib/tp_router.g.dart. You can customize this in build.yaml:
targets:
$default:
builders:
tp_router_generator:tp_router:
options:
output: lib/routes/app_routes.dart
Migration Guide #
Thinking about switching from go_router or auto_router? Check out our Migration Guide.