update: working on routing style feature 48 pass 1 fail
This commit is contained in:
parent
a8226d7b87
commit
50a12e4535
2 changed files with 158 additions and 33 deletions
|
@ -7,7 +7,7 @@ import '../routing_style.dart';
|
||||||
/// existing Express-like routing pattern. It provides the familiar app.get(),
|
/// existing Express-like routing pattern. It provides the familiar app.get(),
|
||||||
/// app.post(), etc. methods while utilizing the underlying routing system.
|
/// app.post(), etc. methods while utilizing the underlying routing system.
|
||||||
class ExpressStyle<T> implements RoutingStyle<T> {
|
class ExpressStyle<T> implements RoutingStyle<T> {
|
||||||
final Router<T> _router;
|
Router<T> _router;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Router<T> get router => _router;
|
Router<T> get router => _router;
|
||||||
|
@ -36,7 +36,8 @@ class ExpressStyle<T> implements RoutingStyle<T> {
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
Route<T> get(String path, T handler, {List<T> middleware = const []}) {
|
Route<T> get(String path, T handler, {List<T> middleware = const []}) {
|
||||||
return _router.get(path, handler, middleware: middleware);
|
return _router.get(path, _wrapHandler(handler),
|
||||||
|
middleware: middleware.map(_wrapMiddleware).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a route that handles POST requests.
|
/// Register a route that handles POST requests.
|
||||||
|
@ -47,7 +48,8 @@ class ExpressStyle<T> implements RoutingStyle<T> {
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
Route<T> post(String path, T handler, {List<T> middleware = const []}) {
|
Route<T> post(String path, T handler, {List<T> middleware = const []}) {
|
||||||
return _router.post(path, handler, middleware: middleware);
|
return _router.post(path, _wrapHandler(handler),
|
||||||
|
middleware: middleware.map(_wrapMiddleware).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a route that handles PUT requests.
|
/// Register a route that handles PUT requests.
|
||||||
|
@ -58,7 +60,8 @@ class ExpressStyle<T> implements RoutingStyle<T> {
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
Route<T> put(String path, T handler, {List<T> middleware = const []}) {
|
Route<T> put(String path, T handler, {List<T> middleware = const []}) {
|
||||||
return _router.put(path, handler, middleware: middleware) as Route<T>;
|
return _router.addRoute('PUT', path, _wrapHandler(handler),
|
||||||
|
middleware: middleware.map(_wrapMiddleware).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a route that handles DELETE requests.
|
/// Register a route that handles DELETE requests.
|
||||||
|
@ -69,7 +72,8 @@ class ExpressStyle<T> implements RoutingStyle<T> {
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
Route<T> delete(String path, T handler, {List<T> middleware = const []}) {
|
Route<T> delete(String path, T handler, {List<T> middleware = const []}) {
|
||||||
return _router.delete(path, handler, middleware: middleware);
|
return _router.delete(path, _wrapHandler(handler),
|
||||||
|
middleware: middleware.map(_wrapMiddleware).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a route that handles PATCH requests.
|
/// Register a route that handles PATCH requests.
|
||||||
|
@ -80,7 +84,8 @@ class ExpressStyle<T> implements RoutingStyle<T> {
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
Route<T> patch(String path, T handler, {List<T> middleware = const []}) {
|
Route<T> patch(String path, T handler, {List<T> middleware = const []}) {
|
||||||
return _router.patch(path, handler, middleware: middleware);
|
return _router.patch(path, _wrapHandler(handler),
|
||||||
|
middleware: middleware.map(_wrapMiddleware).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a route that handles HEAD requests.
|
/// Register a route that handles HEAD requests.
|
||||||
|
@ -91,7 +96,8 @@ class ExpressStyle<T> implements RoutingStyle<T> {
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
Route<T> head(String path, T handler, {List<T> middleware = const []}) {
|
Route<T> head(String path, T handler, {List<T> middleware = const []}) {
|
||||||
return _router.head(path, handler, middleware: middleware);
|
return _router.head(path, _wrapHandler(handler),
|
||||||
|
middleware: middleware.map(_wrapMiddleware).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a route that handles OPTIONS requests.
|
/// Register a route that handles OPTIONS requests.
|
||||||
|
@ -102,7 +108,8 @@ class ExpressStyle<T> implements RoutingStyle<T> {
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
Route<T> options(String path, T handler, {List<T> middleware = const []}) {
|
Route<T> options(String path, T handler, {List<T> middleware = const []}) {
|
||||||
return _router.options(path, handler, middleware: middleware);
|
return _router.options(path, _wrapHandler(handler),
|
||||||
|
middleware: middleware.map(_wrapMiddleware).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a route that handles all HTTP methods.
|
/// Register a route that handles all HTTP methods.
|
||||||
|
@ -113,7 +120,8 @@ class ExpressStyle<T> implements RoutingStyle<T> {
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
Route<T> all(String path, T handler, {List<T> middleware = const []}) {
|
Route<T> all(String path, T handler, {List<T> middleware = const []}) {
|
||||||
return _router.all(path, handler, middleware: middleware);
|
return _router.all(path, _wrapHandler(handler),
|
||||||
|
middleware: middleware.map(_wrapMiddleware).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use middleware for all routes.
|
/// Use middleware for all routes.
|
||||||
|
@ -125,7 +133,16 @@ class ExpressStyle<T> implements RoutingStyle<T> {
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
void use(T middleware) {
|
void use(T middleware) {
|
||||||
_router.chain([middleware]);
|
// Chain middleware and update router
|
||||||
|
var chainedRouter = _router.chain([_wrapMiddleware(middleware)]);
|
||||||
|
_router = chainedRouter;
|
||||||
|
|
||||||
|
// Apply middleware to existing routes
|
||||||
|
for (var route in _router.routes) {
|
||||||
|
if (route is! SymlinkRoute<T>) {
|
||||||
|
route.handlers.insert(0, _wrapMiddleware(middleware));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a route group with optional prefix and middleware.
|
/// Create a route group with optional prefix and middleware.
|
||||||
|
@ -138,9 +155,54 @@ class ExpressStyle<T> implements RoutingStyle<T> {
|
||||||
/// ```
|
/// ```
|
||||||
void group(String prefix, void Function(ExpressStyle<T> router) callback,
|
void group(String prefix, void Function(ExpressStyle<T> router) callback,
|
||||||
{List<T> middleware = const []}) {
|
{List<T> middleware = const []}) {
|
||||||
_router.group(prefix, (router) {
|
// Create a new router for the group
|
||||||
callback(ExpressStyle<T>(router));
|
var groupRouter = Router<T>();
|
||||||
}, middleware: middleware);
|
|
||||||
|
// Create new style instance for group
|
||||||
|
var groupStyle = ExpressStyle<T>(groupRouter);
|
||||||
|
|
||||||
|
// Execute callback with group style
|
||||||
|
callback(groupStyle);
|
||||||
|
|
||||||
|
// Apply middleware to all routes in the group
|
||||||
|
if (middleware.isNotEmpty) {
|
||||||
|
for (var route in groupRouter.routes) {
|
||||||
|
if (route is! SymlinkRoute<T>) {
|
||||||
|
route.handlers.insertAll(0, middleware.map(_wrapMiddleware).toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mount group router with prefix
|
||||||
|
_router.mount(prefix, groupRouter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to wrap handler functions to match expected signature
|
||||||
|
T _wrapHandler(T handler) {
|
||||||
|
if (handler is Function) {
|
||||||
|
return ((req, res) {
|
||||||
|
if (handler is Function(dynamic, dynamic)) {
|
||||||
|
handler(req, res);
|
||||||
|
} else if (handler is Function(dynamic, dynamic, Function)) {
|
||||||
|
handler(req, res, () {});
|
||||||
|
}
|
||||||
|
}) as T;
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to wrap middleware functions to match expected signature
|
||||||
|
T _wrapMiddleware(T middleware) {
|
||||||
|
if (middleware is Function) {
|
||||||
|
return ((req, res) {
|
||||||
|
if (middleware is Function(dynamic, dynamic, Function)) {
|
||||||
|
middleware(req, res, () {});
|
||||||
|
} else if (middleware is Function(dynamic, dynamic)) {
|
||||||
|
middleware(req, res);
|
||||||
|
}
|
||||||
|
}) as T;
|
||||||
|
}
|
||||||
|
return middleware;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,10 @@ import '../routing_style.dart';
|
||||||
/// underlying routing system. It demonstrates how different routing styles
|
/// underlying routing system. It demonstrates how different routing styles
|
||||||
/// can be implemented on top of the core routing functionality.
|
/// can be implemented on top of the core routing functionality.
|
||||||
class LaravelStyle<T> implements RoutingStyle<T> {
|
class LaravelStyle<T> implements RoutingStyle<T> {
|
||||||
final Router<T> _router;
|
Router<T> _router;
|
||||||
|
String? _groupPrefix;
|
||||||
|
String? _groupName;
|
||||||
|
List<T> _currentMiddleware = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Router<T> get router => _router;
|
Router<T> get router => _router;
|
||||||
|
@ -35,9 +38,49 @@ class LaravelStyle<T> implements RoutingStyle<T> {
|
||||||
/// Route::post('/users', handler);
|
/// Route::post('/users', handler);
|
||||||
/// ```
|
/// ```
|
||||||
Route<T> route(String method, String path, T handler,
|
Route<T> route(String method, String path, T handler,
|
||||||
{List<T> middleware = const []}) {
|
{List<T> middleware = const [], String? name}) {
|
||||||
return _router.addRoute(method.toUpperCase(), path, handler,
|
var allMiddleware = [..._currentMiddleware, ...middleware];
|
||||||
middleware: middleware);
|
var route = _router.addRoute(method.toUpperCase(), path, handler,
|
||||||
|
middleware: allMiddleware);
|
||||||
|
|
||||||
|
// Auto-generate route name if not provided
|
||||||
|
if (name != null) {
|
||||||
|
route.name = name;
|
||||||
|
} else {
|
||||||
|
// Convert path to route name (e.g., /users/{id} -> users.show)
|
||||||
|
var segments = path.split('/').where((s) => s.isNotEmpty).toList();
|
||||||
|
if (segments.isNotEmpty) {
|
||||||
|
var lastSegment = segments.last;
|
||||||
|
var prefix = segments.length > 1 ? segments[segments.length - 2] : '';
|
||||||
|
var groupPrefix = _groupName ?? _groupPrefix?.replaceAll('/', '.');
|
||||||
|
var namePrefix = groupPrefix != null ? '$groupPrefix.' : '';
|
||||||
|
|
||||||
|
// Generate name based on method and path
|
||||||
|
switch (method.toUpperCase()) {
|
||||||
|
case 'GET':
|
||||||
|
route.name = lastSegment.contains(':') || lastSegment.contains('{')
|
||||||
|
? '$namePrefix${prefix.isEmpty ? lastSegment : prefix}.show'
|
||||||
|
: '$namePrefix${lastSegment}.index';
|
||||||
|
break;
|
||||||
|
case 'POST':
|
||||||
|
route.name =
|
||||||
|
'$namePrefix${prefix.isEmpty ? lastSegment : prefix}.store';
|
||||||
|
break;
|
||||||
|
case 'PUT':
|
||||||
|
case 'PATCH':
|
||||||
|
route.name =
|
||||||
|
'$namePrefix${prefix.isEmpty ? lastSegment : prefix}.update';
|
||||||
|
break;
|
||||||
|
case 'DELETE':
|
||||||
|
route.name =
|
||||||
|
'$namePrefix${prefix.isEmpty ? lastSegment : prefix}.destroy';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
route.name = '$namePrefix$lastSegment';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return route;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a GET route.
|
/// Register a GET route.
|
||||||
|
@ -99,27 +142,40 @@ class LaravelStyle<T> implements RoutingStyle<T> {
|
||||||
void group(Map<String, dynamic> attributes, void Function() callback) {
|
void group(Map<String, dynamic> attributes, void Function() callback) {
|
||||||
var prefix = attributes['prefix'] as String? ?? '';
|
var prefix = attributes['prefix'] as String? ?? '';
|
||||||
var middleware = attributes['middleware'] as List<T>? ?? const [];
|
var middleware = attributes['middleware'] as List<T>? ?? const [];
|
||||||
|
var groupName = attributes['name'] as String? ?? '';
|
||||||
|
|
||||||
_router.group(prefix, (groupRouter) {
|
// Create new router for group
|
||||||
// Store current router
|
var groupRouter = Router<T>();
|
||||||
var parentRouter = _router;
|
|
||||||
// Create new style instance for group
|
// Create new style instance for group
|
||||||
var groupStyle = LaravelStyle<T>(groupRouter);
|
var groupStyle = LaravelStyle<T>(groupRouter);
|
||||||
// Set current instance as the active one
|
|
||||||
_activeInstance = groupStyle;
|
// Set group prefix and name for route naming
|
||||||
// Execute callback
|
groupStyle._groupPrefix = prefix;
|
||||||
callback();
|
groupStyle._groupName = groupName;
|
||||||
// Restore parent instance
|
groupStyle._currentMiddleware = [..._currentMiddleware, ...middleware];
|
||||||
_activeInstance = this;
|
|
||||||
}, middleware: middleware);
|
// Store previous active instance
|
||||||
|
var previousInstance = _activeInstance;
|
||||||
|
// Set group style as active instance
|
||||||
|
_activeInstance = groupStyle;
|
||||||
|
|
||||||
|
// Execute callback with group context
|
||||||
|
callback();
|
||||||
|
|
||||||
|
// Mount group router with prefix
|
||||||
|
var route = _router.mount(prefix, groupRouter);
|
||||||
|
if (groupName.isNotEmpty) {
|
||||||
|
route.name = groupName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore previous active instance
|
||||||
|
_activeInstance = previousInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track active instance for group context
|
// Track active instance for group context
|
||||||
static LaravelStyle? _activeInstance;
|
static LaravelStyle? _activeInstance;
|
||||||
|
|
||||||
// Forward calls to active instance
|
|
||||||
LaravelStyle<T> get _current => _activeInstance as LaravelStyle<T>? ?? this;
|
|
||||||
|
|
||||||
/// Add a name to the last registered route.
|
/// Add a name to the last registered route.
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
|
@ -137,7 +193,14 @@ class LaravelStyle<T> implements RoutingStyle<T> {
|
||||||
/// Route::middleware(['auth', 'throttle']);
|
/// Route::middleware(['auth', 'throttle']);
|
||||||
/// ```
|
/// ```
|
||||||
void middleware(List<T> middleware) {
|
void middleware(List<T> middleware) {
|
||||||
_router.chain(middleware);
|
_currentMiddleware.addAll(middleware);
|
||||||
|
|
||||||
|
// Apply middleware to all existing routes
|
||||||
|
for (var route in _router.routes) {
|
||||||
|
if (route is! SymlinkRoute<T>) {
|
||||||
|
route.handlers.insertAll(0, middleware);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue