Skip to content

Commit

Permalink
feat(MatchRoute): Moved traversal middleware opportunity to after a r…
Browse files Browse the repository at this point in the history
…oute is matched

Traversal middleware now receives the matched route, a preview of route params, and whether or not traversal plans on terminating on that route. Traversal middleware can null out the route to prevent traversal to stop traversing that route. It can mark the candidate as terminal to force traversal to select that route. Lastly, if the route is marked as terminal it can modify the final route params
  • Loading branch information
MikeRyanDev committed Apr 2, 2016
1 parent 9bc9dcd commit 5144caa
Showing 1 changed file with 75 additions and 67 deletions.
142 changes: 75 additions & 67 deletions lib/match-route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ export interface Match {
params: any;
};

export interface TraversalCandidate {
route: Route,
params: any;
isTerminal: boolean;
}


@Injectable()
export class RouteTraverser {
Expand Down Expand Up @@ -59,33 +65,27 @@ export class RouteTraverser {
paramNames = [],
paramValues = []
): Observable<Match> {
const seekers = routes.map<Observable<Match>>(route => Observable.of(route)
.let(route$ => {
const resolved = this._middleware.map(m => m(route$));

return Observable
.merge(...resolved)
.every(signal => !!signal);
})
.mergeMap(canTraverse => {
if( canTraverse ) {
return this._matchRouteDeep(
route,
pathname,
remainingPathname,
paramNames,
paramValues
);
}

return Observable.of(null);
})
const seekers = routes.map<Observable<Match>>(route => {
return this._matchRouteDeep(
route,
pathname,
remainingPathname,
paramNames,
paramValues
)
.catch(error => {
console.error(error);
console.error('Error During Traversa', error);
return Observable.of(null);
})
);

});
});
/**
* A note about this code: it should use Observable.concat
* to merge the seekers into an in-order sequence. However,
* unubscribing from sequences that way seems to throw a ton
* of empty errors. Merging and sorting works correctly, but it
* is very aggressive and probably not as performant as concat
* would have been.
*/
return Observable
.merge(...seekers)
.toArray()
Expand Down Expand Up @@ -113,51 +113,59 @@ export class RouteTraverser {
paramValues = [];
}

if( remainingPathname !== null ) {
const matched = matchPattern(pattern, remainingPathname);
remainingPathname = matched.remainingPathname;
paramNames = [ ...paramNames, ...matched.paramNames ];
paramValues = [ ...paramValues, ...matched.paramValues ];

if( remainingPathname === '' && route.path ) {
const match: Match = {
routes: [ route ],
params: assignParams(paramNames, paramValues)
};

return getIndexRoute(route)
.map(indexRoute => {
if( !!indexRoute ) {
match.routes.push(indexRoute);
return Observable.of(route)
.filter(() => remainingPathname !== null)
.do(() => {
const matched = matchPattern(pattern, remainingPathname);
remainingPathname = matched.remainingPathname;
paramNames = [ ...paramNames, ...matched.paramNames ];
paramValues = [ ...paramValues, ...matched.paramValues ];
})
.filter(() => remainingPathname !== null)
.map<TraversalCandidate>(() => {
return {
route,
params: assignParams(paramNames, paramValues),
isTerminal: remainingPathname === '' && !!route.path
}
})
.let<TraversalCandidate>(compose(...this._middleware))
.filter(({ route }) => !!route)
.mergeMap(({ route, params, isTerminal }) => {
if( isTerminal ) {
const match: Match = {
routes: [ route ],
params
};

return getIndexRoute(route)
.map(indexRoute => {
if( !!indexRoute ) {
match.routes.push(indexRoute);
}

return match;
});
}

return getChildRoutes(route)
.mergeMap(childRoutes => this._matchRoutes(
childRoutes,
pathname,
remainingPathname,
paramNames,
paramValues
))
.map(match => {
if( !!match ) {
match.routes.unshift(route);

return match;
}

return match;
return null;
});
}
}

if( remainingPathname != null ) {
return getChildRoutes(route)
.mergeMap(childRoutes => this._matchRoutes(
childRoutes,
pathname,
remainingPathname,
paramNames,
paramValues
))
.map(match => {
if( !!match ) {
match.routes.unshift(route);

return match;
}

return null;
});
}
else {
return Observable.of(null);
}
});
}
}

Expand Down

0 comments on commit 5144caa

Please sign in to comment.