2.0.0
This commit is contained in:
parent
57b2bdff87
commit
4357a102da
11 changed files with 56 additions and 83 deletions
|
@ -1,6 +1,5 @@
|
|||
library angel_route;
|
||||
|
||||
export 'src/extensible.dart';
|
||||
export 'src/middleware_pipeline.dart';
|
||||
export 'src/router.dart';
|
||||
export 'src/routing_exception.dart';
|
|
@ -108,7 +108,7 @@ class _HashRouter extends _BrowserRouterImpl {
|
|||
|
||||
void handleHash([_]) {
|
||||
final path = window.location.hash.replaceAll(_hash, '');
|
||||
final resolved = resolveAbsolute(path);
|
||||
final resolved = resolveAbsolute(path).first;
|
||||
|
||||
if (resolved == null) {
|
||||
_onResolve.add(null);
|
||||
|
@ -120,7 +120,7 @@ class _HashRouter extends _BrowserRouterImpl {
|
|||
}
|
||||
|
||||
void handlePath(String path) {
|
||||
final resolved = resolveAbsolute(path);
|
||||
final resolved = resolveAbsolute(path).first;
|
||||
|
||||
if (resolved == null) {
|
||||
_onResolve.add(null);
|
||||
|
@ -153,7 +153,7 @@ class _PushStateRouter extends _BrowserRouterImpl {
|
|||
|
||||
@override
|
||||
void _goTo(String uri) {
|
||||
final resolved = resolveAbsolute(uri);
|
||||
final resolved = resolveAbsolute(uri).first;
|
||||
var relativeUri = uri;
|
||||
|
||||
if (_basePath?.isNotEmpty == true) {
|
||||
|
@ -177,13 +177,12 @@ class _PushStateRouter extends _BrowserRouterImpl {
|
|||
void handleState(state) {
|
||||
if (state is Map && state.containsKey('path')) {
|
||||
var path = state['path'];
|
||||
final resolved = resolveAbsolute(path);
|
||||
final resolved = resolveAbsolute(path).first;
|
||||
|
||||
if (resolved != null && resolved.route != _current) {
|
||||
//properties.addAll(state['properties'] ?? {});
|
||||
_onResolve.add(resolved);
|
||||
_onRoute.add(_current = resolved.route
|
||||
..state.properties.addAll(state['params'] ?? {}));
|
||||
_onRoute.add(_current = resolved.route);
|
||||
} else {
|
||||
_onResolve.add(null);
|
||||
_onRoute.add(_current = null);
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
final RegExp _equ = new RegExp(r'=$');
|
||||
final RegExp _sym = new RegExp(r'Symbol\("([^"]+)"\)');
|
||||
|
||||
/// Supports accessing members of a Map as though they were actual members.
|
||||
///
|
||||
/// No longer requires reflection. :)
|
||||
@proxy
|
||||
@deprecated
|
||||
class Extensible {
|
||||
/// A set of custom properties that can be assigned to the server.
|
||||
///
|
||||
/// Useful for configuration and extension.
|
||||
Map properties = {};
|
||||
|
||||
operator [](key) => properties[key];
|
||||
operator []=(key, value) => properties[key] = value;
|
||||
|
||||
noSuchMethod(Invocation invocation) {
|
||||
if (invocation.memberName != null) {
|
||||
String name = _sym.firstMatch(invocation.memberName.toString()).group(1);
|
||||
|
||||
if (invocation.isMethod) {
|
||||
return Function.apply(properties[name], invocation.positionalArguments,
|
||||
invocation.namedArguments);
|
||||
} else if (invocation.isGetter) {
|
||||
return properties[name];
|
||||
}
|
||||
}
|
||||
|
||||
super.noSuchMethod(invocation);
|
||||
}
|
||||
}
|
|
@ -4,16 +4,18 @@ import 'router.dart';
|
|||
class MiddlewarePipeline {
|
||||
/// All the possible routes that matched the given path.
|
||||
final List<RoutingResult> routingResults;
|
||||
List _handlers;
|
||||
|
||||
/// An ordered list of every handler delegated to handle this request.
|
||||
List get handlers {
|
||||
if (_handlers != null) return _handlers;
|
||||
final handlers = [];
|
||||
|
||||
for (RoutingResult result in routingResults) {
|
||||
handlers.addAll(result.allHandlers);
|
||||
}
|
||||
|
||||
return handlers;
|
||||
return _handlers = handlers;
|
||||
}
|
||||
|
||||
MiddlewarePipeline(this.routingResults);
|
||||
|
|
|
@ -76,9 +76,6 @@ class Route {
|
|||
/// The virtual path on which this route is mounted.
|
||||
String get path => _path;
|
||||
|
||||
/// Arbitrary state attached to this route.
|
||||
final Extensible state = new Extensible();
|
||||
|
||||
/// The [Route] at the top of the hierarchy this route is found in.
|
||||
Route get absoluteParent {
|
||||
Route result = this;
|
||||
|
@ -314,8 +311,7 @@ class Route {
|
|||
.._path = _path
|
||||
.._pathified = _pathified
|
||||
.._resolver = _resolver
|
||||
.._stub = _stub
|
||||
..state.properties.addAll(state.properties);
|
||||
.._stub = _stub;
|
||||
}
|
||||
|
||||
/// Generates a URI to this route with the given parameters.
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
library angel_route.src.router;
|
||||
|
||||
import 'extensible.dart';
|
||||
import 'routing_exception.dart';
|
||||
import '../string_util.dart';
|
||||
part 'symlink_route.dart';
|
||||
|
@ -266,11 +265,14 @@ class Router {
|
|||
|
||||
/// Finds the first [Route] that matches the given path,
|
||||
/// with the given method.
|
||||
RoutingResult resolve(String absolute, String relative,
|
||||
{String method: 'GET'}) {
|
||||
final cleanAbsolute = stripStraySlashes(absolute);
|
||||
final cleanRelative = stripStraySlashes(relative);
|
||||
bool resolve(String absolute, String relative, List<RoutingResult> out,
|
||||
{String method: 'GET', bool strip: true}) {
|
||||
final cleanAbsolute =
|
||||
strip == false ? absolute : stripStraySlashes(absolute);
|
||||
final cleanRelative =
|
||||
strip == false ? relative : stripStraySlashes(relative);
|
||||
final segments = cleanRelative.split('/').where((str) => str.isNotEmpty);
|
||||
bool success = false;
|
||||
//print(
|
||||
// 'Now resolving $method "/$cleanRelative", absolute: $cleanAbsolute');
|
||||
//print('Path segments: ${segments.toList()}');
|
||||
|
@ -285,8 +287,7 @@ class Router {
|
|||
|
||||
if (match != null) {
|
||||
final cleaned = s.join('/').replaceFirst(match[0], '');
|
||||
var tail = cleanRelative
|
||||
.replaceAll(route._head, '');
|
||||
var tail = cleanRelative.replaceAll(route._head, '');
|
||||
tail = stripStraySlashes(tail);
|
||||
|
||||
if (cleaned.isEmpty) {
|
||||
|
@ -294,9 +295,10 @@ class Router {
|
|||
// 'Matched relative "$cleanRelative" to head ${route._head
|
||||
// .pattern} on $route. Tail: "$tail"');
|
||||
route.router.debug = route.router.debug || debug;
|
||||
final nested =
|
||||
route.router.resolve(cleanAbsolute, tail, method: method);
|
||||
return _dumpResult(
|
||||
var nested = <RoutingResult>[];
|
||||
route.router.resolve(cleanAbsolute, tail, nested,
|
||||
method: method, strip: false);
|
||||
var result = _dumpResult(
|
||||
cleanRelative,
|
||||
new RoutingResult(
|
||||
match: match,
|
||||
|
@ -305,6 +307,8 @@ class Router {
|
|||
shallowRoute: route,
|
||||
shallowRouter: this,
|
||||
tail: tail));
|
||||
out.add(result);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -314,39 +318,35 @@ class Router {
|
|||
final match = route.match(cleanRelative);
|
||||
|
||||
if (match != null) {
|
||||
return _dumpResult(
|
||||
var result = _dumpResult(
|
||||
cleanRelative,
|
||||
new RoutingResult(
|
||||
match: match,
|
||||
params: route.parseParameters(cleanRelative),
|
||||
shallowRoute: route,
|
||||
shallowRouter: this));
|
||||
out.add(result);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//print('Could not resolve path "/$cleanRelative".');
|
||||
return null;
|
||||
return success;
|
||||
}
|
||||
|
||||
/// Returns the result of [resolve] with [path] passed as
|
||||
/// both `absolute` and `relative`.
|
||||
RoutingResult resolveAbsolute(String path, {String method: 'GET'}) =>
|
||||
resolve(path, path, method: method);
|
||||
Iterable<RoutingResult> resolveAbsolute(String path,
|
||||
{String method: 'GET', bool strip: true}) =>
|
||||
resolveAll(path, path, method: method, strip: strip);
|
||||
|
||||
/// Finds every possible [Route] that matches the given path,
|
||||
/// with the given method.
|
||||
Iterable<RoutingResult> resolveAll(String absolute, String relative,
|
||||
{String method: 'GET'}) {
|
||||
final router = clone();
|
||||
{String method: 'GET', bool strip: true}) {
|
||||
final List<RoutingResult> results = [];
|
||||
var result = router.resolve(absolute, relative, method: method);
|
||||
|
||||
while (result != null) {
|
||||
results.add(result);
|
||||
result.router._routes.remove(result.route);
|
||||
result = router.resolve(absolute, relative, method: method);
|
||||
}
|
||||
resolve(absolute, relative, results, method: method, strip: strip);
|
||||
|
||||
// _printDebug(
|
||||
// 'Results of $method "/${absolute.replaceAll(_straySlashes, '')}": ${results.map((r) => r.route).toList()}');
|
||||
|
|
|
@ -6,7 +6,7 @@ class RoutingResult {
|
|||
final Match match;
|
||||
|
||||
/// A nested instance, if a sub-path was matched.
|
||||
final RoutingResult nested;
|
||||
final Iterable<RoutingResult> nested;
|
||||
|
||||
/// All route params matching this route on the current sub-path.
|
||||
final Map<String, dynamic> params = {};
|
||||
|
@ -28,7 +28,7 @@ class RoutingResult {
|
|||
RoutingResult get deepest {
|
||||
var search = this;
|
||||
|
||||
while (search.nested != null) search = search.nested;
|
||||
while (search?.nested?.isNotEmpty == true) search = search.nested.first;
|
||||
|
||||
return search;
|
||||
}
|
||||
|
@ -47,26 +47,35 @@ class RoutingResult {
|
|||
/// All handlers on this sub-path and its children.
|
||||
List get allHandlers {
|
||||
final handlers = [];
|
||||
var search = this;
|
||||
|
||||
while (search != null) {
|
||||
handlers.addAll(search.handlers);
|
||||
search = search.nested;
|
||||
void crawl(RoutingResult result) {
|
||||
handlers.addAll(result.handlers);
|
||||
|
||||
if (result.nested?.isNotEmpty == true) {
|
||||
for (var r in result.nested)
|
||||
crawl(r);
|
||||
}
|
||||
}
|
||||
|
||||
crawl(this);
|
||||
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/// All parameters on this sub-path and its children.
|
||||
Map<String, dynamic> get allParams {
|
||||
final Map<String, dynamic> params = {};
|
||||
var search = this;
|
||||
|
||||
while (search != null) {
|
||||
params.addAll(search.params);
|
||||
search = search.nested;
|
||||
void crawl(RoutingResult result) {
|
||||
params.addAll(result.params);
|
||||
|
||||
if (result.nested?.isNotEmpty == true) {
|
||||
for (var r in result.nested)
|
||||
crawl(r);
|
||||
}
|
||||
}
|
||||
|
||||
crawl(this);
|
||||
return params;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: angel_route
|
||||
description: A powerful, isomorphic routing library for Dart.
|
||||
version: 1.0.8
|
||||
version: 2.0.0
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
homepage: https://github.com/angel-dart/angel_route
|
||||
dev_dependencies:
|
||||
|
|
|
@ -11,7 +11,7 @@ main() {
|
|||
..dumpTree();
|
||||
|
||||
test('nested route groups with chain', () {
|
||||
var r = router.resolveAbsolute('/b/e/f')?.route;
|
||||
var r = router.resolveAbsolute('/b/e/f')?.first?.route;
|
||||
expect(r, isNotNull);
|
||||
expect(r.handlers, hasLength(4));
|
||||
expect(r.handlers, equals(['a', 'c', 'd', 'g']));
|
||||
|
|
|
@ -83,8 +83,8 @@ main() {
|
|||
final res = req.response;
|
||||
|
||||
// Easy middleware pipeline
|
||||
final results = router.resolveAll(req.uri.toString(), req.uri.toString(),
|
||||
method: req.method);
|
||||
final results =
|
||||
router.resolveAbsolute(req.uri.toString(), method: req.method);
|
||||
final pipeline = new MiddlewarePipeline(results);
|
||||
|
||||
if (pipeline.handlers.isEmpty) {
|
||||
|
|
|
@ -8,7 +8,7 @@ void main() {
|
|||
var encoded =
|
||||
'/a/' + Uri.encodeComponent('<<<') + '/b/' + Uri.encodeComponent('???');
|
||||
print(encoded);
|
||||
var result = router.resolveAbsolute(encoded);
|
||||
var result = router.resolveAbsolute(encoded).first;
|
||||
print(result.allParams);
|
||||
expect(result.allParams, {
|
||||
'a': '<<<',
|
||||
|
|
Loading…
Reference in a new issue