Comparing version 0.17.0 to 0.17.1
@@ -14,151 +14,195 @@ import { konsole } from './Konsole'; | ||
export type Action = () => Observableable<any>; | ||
export abstract class Route <VALUE = any> { | ||
private _route: undefined; // hack so that TypeScript will do better type checking on Routes | ||
export interface DoRoute { | ||
type: 'do'; | ||
action: Action; | ||
score: number; | ||
static is <VALUE> (route: any): route is Route<VALUE> { | ||
return route instanceof Route; | ||
} | ||
} | ||
export function isDoRoute(route: Route): route is DoRoute { | ||
return route.type === 'do'; | ||
} | ||
export class ScoredRoute <VALUE = any> extends Route<VALUE> { | ||
score: number; | ||
constructor ( | ||
score?: number | ||
) { | ||
super(); | ||
export function isNoRoute(route: Route): route is NoRoute { | ||
return route.type === 'no'; | ||
} | ||
this.score = ScoredRoute.normalizedScore(score); | ||
} | ||
export interface NoRoute { | ||
type: 'no'; | ||
reason: string; | ||
} | ||
static normalizedScore(score?: number) { | ||
return score != null && score >= 0 && score < 1 | ||
? score | ||
: 1; | ||
} | ||
export type Route = DoRoute | NoRoute; | ||
static is (route: Route): route is ScoredRoute { | ||
return route instanceof ScoredRoute; | ||
} | ||
export type RawRoute = Route | { | ||
type?: 'do'; | ||
action: Action; | ||
score?: number; | ||
} | { | ||
type?: 'no'; | ||
reason: string; | ||
} | ||
static combinedScore(score, otherScore) { | ||
return score * otherScore | ||
} | ||
export type GetRouteRaw <ROUTABLE> = (routable: ROUTABLE) => Observableable<Route | RawRoute | Action>; | ||
clone(score?: number): this { | ||
score = ScoredRoute.normalizedScore(score); | ||
export type GetRoute <ROUTABLE> = (routable: ROUTABLE) => Observableable<Route>; | ||
export type GetRoute$ <ROUTABLE> = (routable: ROUTABLE) => Observable<Route>; | ||
return score === this.score | ||
? this | ||
: Object.assign(Object.create(this.constructor.prototype), this, { score }); | ||
} | ||
export type MapRoute <ROUTABLE> = (route: Route) => Observableable<GetRoute<ROUTABLE>>; | ||
cloneWithCombinedScore(score?: number) { | ||
return this.clone(ScoredRoute.combinedScore(this.score, ScoredRoute.normalizedScore(score))); | ||
} | ||
} | ||
export type Handler <ROUTABLE> = (routable: ROUTABLE) => Observableable<any>; | ||
export type Action = () => Observableable<any>; | ||
export interface Match <VALUE> { | ||
value: VALUE; | ||
score?: number; | ||
export class DoRoute extends ScoredRoute<undefined> { | ||
constructor ( | ||
public action: Action, | ||
score?: number | ||
) { | ||
super(score); | ||
} | ||
static is (route: Route): route is DoRoute { | ||
return route instanceof DoRoute; | ||
} | ||
} | ||
export interface NoMatch <VALUE> { | ||
value?: VALUE; | ||
reason: string; | ||
function _do <VALUE = any> ( | ||
action: (value?: VALUE) => Observableable<any>, | ||
score?: number | ||
) { | ||
return (value: VALUE) => new DoRoute(() => action(value), score); | ||
} | ||
export type MatchResult <VALUE> = Match<VALUE> | NoMatch<VALUE>; | ||
export { _do as do } | ||
export type Matcher <ROUTABLE, VALUE> = (routable: ROUTABLE) => Observableable<MatchResult<VALUE> | VALUE>; | ||
export class MatchRoute <VALUE = any> extends ScoredRoute<VALUE> { | ||
constructor( | ||
public value: VALUE, | ||
score?: number | ||
) { | ||
super(score); | ||
} | ||
export type Predicate <ROUTABLE> = Matcher<ROUTABLE, boolean>; | ||
static is <VALUE = any> (route: Route<VALUE>): route is MatchRoute<VALUE> { | ||
return route instanceof MatchRoute; | ||
} | ||
} | ||
export function doRoute ( | ||
action: () => Observableable<any>, | ||
score: number = 1 | ||
): DoRoute { | ||
return { | ||
type: 'do', | ||
action, | ||
score | ||
}; | ||
export function match <VALUE = any> ( | ||
value: VALUE, | ||
score?: number | ||
) { | ||
return () => new MatchRoute(value, score); | ||
} | ||
export const defaultReason = "none"; | ||
export class NoRoute <VALUE = any> extends Route<VALUE> { | ||
static defaultReason = "none"; | ||
constructor ( | ||
public reason = NoRoute.defaultReason, | ||
public value?: VALUE | ||
) { | ||
super(); | ||
} | ||
export function noRoute ( | ||
reason: string = defaultReason | ||
): NoRoute { | ||
return { | ||
type: 'no', | ||
reason | ||
}; | ||
static default = new NoRoute(); | ||
static default$ = Observable.of(NoRoute.default); | ||
static is <VALUE = any> (route: Route): route is NoRoute<VALUE> { | ||
return route instanceof NoRoute; | ||
} | ||
} | ||
export function normalizeRoute (rawRoute: RawRoute): Route { | ||
if (!rawRoute || (rawRoute as NoRoute).reason) | ||
return noRoute(rawRoute && (rawRoute as NoRoute).reason); | ||
if (typeof(rawRoute) === 'function') | ||
return doRoute(rawRoute); | ||
if ((rawRoute as DoRoute).action) | ||
return doRoute((rawRoute as DoRoute).action, (rawRoute as DoRoute).score); | ||
throw new Error('invalid route'); | ||
function _no <VALUE> ( | ||
reason?: string, | ||
value?: VALUE | ||
) { | ||
return () => new NoRoute(reason, value); | ||
} | ||
export const getNormalizedRoute = <ROUTABLE> (routable: ROUTABLE) => (getRoute: GetRouteRaw<ROUTABLE>) => getRoute | ||
? toObservable(getRoute(routable)) | ||
.map(normalizeRoute) | ||
: Observable.of(noRoute()); | ||
export { _no as no } | ||
export function route$ <ROUTABLE> (routable: ROUTABLE, getRoute: GetRouteRaw<ROUTABLE>) { | ||
return Observable.of(getRoute) | ||
.flatMap(getNormalizedRoute(routable)) | ||
.do(route => konsole.log("route: returned a route", route)) | ||
.flatMap(route => isDoRoute(route) | ||
? toObservable(route.action()) | ||
.do(_ => konsole.log("route: called action")) | ||
.map(_ => true) | ||
: Observable.of(false) | ||
); | ||
export type Router <ARG = undefined, VALUE = any> = (arg?: ARG) => Observableable<Route<VALUE> | VALUE>; | ||
const getRouteError = new Error('router must be a function'); | ||
export function getRoute$ <ARG, VALUE> ( | ||
router: Router<ARG, VALUE>, | ||
arg?: ARG | ||
): Observable<Route<VALUE>> { | ||
if (router == null) | ||
return NoRoute.default$; | ||
if (typeof router !== 'function') | ||
return Observable.throw(getRouteError); | ||
return Observable | ||
.of(router) | ||
.flatMap(router => toObservable(router(arg))) | ||
// normalize result | ||
.map(result => { | ||
if (result == null) | ||
return NoRoute.default; | ||
if (Route.is(result)) | ||
return result; | ||
return new MatchRoute(result); | ||
}) | ||
} | ||
export function no <ROUTABLE> ( | ||
reason?: string | ||
): GetRoute$<ROUTABLE> { | ||
return routable => Observable.of(noRoute(reason)); | ||
export function mapRoute$ <ARG, VALUE, ROUTE extends Route<VALUE> = Route<VALUE>> ( | ||
router: Router<ARG, VALUE>, | ||
mapRoute: Router<ROUTE>, | ||
arg?: ARG | ||
) { | ||
return getRoute$(router, arg) | ||
.flatMap(route => getRoute$(mapRoute, route)); | ||
} | ||
export function getRouteDo <ROUTABLE> ( | ||
handler: Handler<ROUTABLE>, | ||
score?: number | ||
): GetRoute$<ROUTABLE> { | ||
return routable => Observable.of(doRoute(() => handler(routable), score)); | ||
export function route$ <ARG, VALUE> ( | ||
router: Router<ARG, VALUE>, | ||
arg?: ARG | ||
) { | ||
return getRoute$(router, arg) | ||
.filter(DoRoute.is) | ||
.flatMap(route => toObservable(route.action())) | ||
.mapTo(true) | ||
.defaultIfEmpty(false); | ||
} | ||
export { getRouteDo as do } | ||
const strictlyFilterError = new Error("route isn't DoRoute or NoRoute"); | ||
export function first <ROUTABLE> ( | ||
... getRoutes: GetRouteRaw<ROUTABLE>[] | ||
): GetRoute$<ROUTABLE> { | ||
return routable => Observable.from(getRoutes) | ||
.concatMap(getNormalizedRoute(routable)) | ||
.filter(isDoRoute) | ||
.take(1) // so that we don't keep going through routers after we find one that matches; | ||
.defaultIfEmpty(noRoute('first')); | ||
function strictlyFilterScored(route: Route): route is ScoredRoute { | ||
if (ScoredRoute.is(route)) | ||
return true; | ||
if (NoRoute.is(route)) | ||
return false; | ||
throw strictlyFilterError; | ||
} | ||
export function combinedScore(score, otherScore) { | ||
return score * otherScore | ||
export function first <VALUE> ( | ||
... routers: Router<undefined, VALUE>[] | ||
): Observable<Route<VALUE>> { | ||
return Observable.from(routers) | ||
// we put concatMap here because it forces everything after it to execute serially | ||
.concatMap(router => getRoute$(router)) | ||
.filter(strictlyFilterScored) | ||
.take(1) // so that we don't keep going through routers after we find one that matches | ||
.defaultIfEmpty(NoRoute.default); | ||
} | ||
export function routeWithCombinedScore(route: DoRoute, newScore: number) { | ||
const score = combinedScore(newScore, route.score); | ||
const minRouteError = new Error("minRoute.action should never be called"); | ||
return route.score === score | ||
? route | ||
: { | ||
... route, | ||
score | ||
} as Route; | ||
} | ||
export const minRoute = doRoute( | ||
const minRoute = new DoRoute( | ||
() => { | ||
console.warn("BestRouter.minRoute.action should never be called"); | ||
throw minRouteError; | ||
}, | ||
@@ -168,14 +212,16 @@ 0 | ||
export function best <ROUTABLE> ( | ||
... getRoutes: GetRouteRaw<ROUTABLE>[] | ||
): GetRoute<ROUTABLE> { | ||
return routable => new Observable<Route>(observer => { | ||
let bestRoute = minRoute; | ||
export function best <VALUE = any> ( | ||
... routers: Router<VALUE> [] | ||
): Observable<Route<VALUE>> { | ||
return new Observable<Route>(observer => { | ||
let bestRoute: ScoredRoute = minRoute; | ||
const subscription = Observable.from(getRoutes) | ||
const subscription = Observable.from(routers) | ||
// we put concatMap here because it forces everything after it to execute serially | ||
.concatMap(router => getRoute$(router)) | ||
// early exit if we've already found a winner (score === 1) | ||
.takeWhile(_ => bestRoute.score < 1) | ||
.concatMap(getNormalizedRoute(routable)) | ||
.filter(isDoRoute) | ||
.filter(strictlyFilterScored) | ||
.subscribe( | ||
(route: DoRoute) => { | ||
route => { | ||
if (route.score > bestRoute.score) { | ||
@@ -194,3 +240,3 @@ bestRoute = route; | ||
? bestRoute | ||
: noRoute('best') | ||
: NoRoute.default | ||
); | ||
@@ -205,159 +251,175 @@ observer.complete(); | ||
export function noop <ROUTABLE> (handler: Handler<ROUTABLE>): GetRouteRaw<ROUTABLE> { | ||
return routable => toObservable(handler(routable)) | ||
.map(_ => noRoute('noop')); | ||
export function noop ( | ||
action: Action | ||
) { | ||
return () => toObservable(action()) | ||
.mapTo(NoRoute.default); | ||
} | ||
export function isMatch <VALUE> (match: MatchResult<any>): match is Match<VALUE> { | ||
return ((match as any).reason === undefined); | ||
export interface MapTypeToRouteClass <VALUE> { | ||
route: Route<VALUE>, | ||
scored: ScoredRoute<VALUE>, | ||
do: DoRoute, | ||
match: MatchRoute<VALUE>, | ||
no: NoRoute<VALUE>, | ||
default: Route, | ||
} | ||
function normalizeMatchResult <VALUE> (response: any): MatchResult<VALUE> { | ||
if (response == null || response === false) | ||
return { | ||
reason: defaultReason | ||
} | ||
export type RouteTypes <VALUE> = keyof MapTypeToRouteClass<VALUE>; | ||
if (typeof(response) === 'object') { | ||
if (response.reason) { | ||
if (typeof(response.reason) !== 'string') | ||
throw new Error('The reason for NoMatch must be a string'); | ||
export function* getTypesFromRoute( | ||
route: Route | ||
) { | ||
if (NoRoute.is(route)) | ||
yield 'no'; | ||
if (DoRoute.is(route)) | ||
yield 'do'; | ||
if (MatchRoute.is(route)) | ||
yield 'match'; | ||
return { | ||
reason: response.reason | ||
} | ||
} | ||
if (ScoredRoute.is(route)) | ||
yield 'scored'; | ||
if (Route.is(route)) | ||
yield 'route'; | ||
yield 'default'; | ||
} | ||
if (response.value !== undefined) { | ||
if (response.score !== undefined && typeof(response.score) !== 'number') | ||
throw new Error('The score for Match must be a number'); | ||
export type MapTypeToRouter <VALUE> = { [P in RouteTypes<VALUE>]: Router<MapTypeToRouteClass<VALUE>[P]> } | ||
return { | ||
value: response.value, | ||
score: response.score || 1 | ||
} | ||
} | ||
function getRouteByType <VALUE> ( | ||
route: Route<VALUE>, | ||
mapTypeToRouter: Partial<MapTypeToRouter<VALUE>> | ||
): Observableable<Route> { | ||
for (let type of getTypesFromRoute(route)) { | ||
const router = mapTypeToRouter[type]; | ||
if (router) | ||
return getRoute$(router, route); | ||
} | ||
return { | ||
value: response, | ||
score: 1 | ||
} | ||
return route; | ||
} | ||
export function getNormalizedMatchResult$ <ROUTABLE, VALUE> (matcher: Matcher<ROUTABLE, VALUE>, routable: ROUTABLE) { | ||
return toObservable(matcher(routable)) | ||
.map(response => normalizeMatchResult<VALUE>(response)); | ||
export function mapRouteByType$ <ARG, VALUE> ( | ||
router: Router<ARG, VALUE>, | ||
mapTypeToRouter: Partial<MapTypeToRouter<VALUE>>, | ||
arg?: ARG | ||
) { | ||
return mapRoute$(router, route => getRouteByType(route, mapTypeToRouter), arg); | ||
} | ||
function getRouteIfMatches <ROUTABLE, VALUE> ( | ||
matcher: Matcher<ROUTABLE, VALUE>, | ||
getThenGetRoute: (value: VALUE) => Observableable<GetRoute<ROUTABLE>>, | ||
elseMapRoute: (route: NoRoute) => Observableable<GetRoute<ROUTABLE>> = route => routable => route | ||
): GetRoute<ROUTABLE> { | ||
return routable => getNormalizedMatchResult$(matcher, routable) | ||
.flatMap(matchResult => isMatch(matchResult) | ||
? toObservable(getThenGetRoute(matchResult.value)) | ||
.flatMap(getNormalizedRoute(routable)) | ||
.map(route => isDoRoute(route) | ||
? routeWithCombinedScore(route, matchResult.score) | ||
: route | ||
) | ||
: toObservable(elseMapRoute(noRoute(matchResult.reason))) | ||
.flatMap(getNormalizedRoute(routable)) | ||
); | ||
const mapRouteIdentity = route => route; | ||
const getMatchError = new Error("ifGet's matchRouter should only return MatchRoute or NoRoute"); | ||
export function ifGet <VALUE> ( | ||
getMatch: Router<undefined, VALUE>, | ||
mapMatchRoute: Router<MatchRoute<VALUE>>, | ||
mapNoRoute?: Router<NoRoute<VALUE>> | ||
) { | ||
return mapRouteByType$(getMatch, { | ||
match: route => mapRouteByType$( | ||
mapMatchRoute, { | ||
scored: _route => _route.cloneWithCombinedScore(route.score) | ||
}, | ||
route | ||
), | ||
no: mapNoRoute || mapRouteIdentity, | ||
default: () => { | ||
throw getMatchError; | ||
} | ||
}); | ||
} | ||
export { getRouteIfMatches as ifGet } | ||
// _if is a special case of ifGet | ||
// value of MatchRoute must be true or false | ||
// if value is false, NoRoute is instead returned | ||
export function predicateToMatcher <ROUTABLE> (predicate: Predicate<ROUTABLE>): Matcher<ROUTABLE, boolean> { | ||
return routable => toObservable(predicate(routable)) | ||
.map((response: any) => { | ||
if (response === true || response === false) | ||
return response; | ||
const ifPredicateError = new Error("if's predicate must have value of true or false"); | ||
const ifPredicateMatchError = new Error("if's predicate must only return MatchRoute or NoRoute"); | ||
if (typeof(response) === 'object') { | ||
if (response.reason) | ||
return response; | ||
if (response.value !== undefined) { | ||
if (response.value === false) | ||
return false; | ||
if (response.value === true) | ||
return response; | ||
throw new Error('When returning a Match from a predicate, the value must be true or false'); | ||
function _if ( | ||
predicate: Router<undefined, boolean>, | ||
mapMatchRoute: Router<MatchRoute<boolean>>, | ||
mapNoRoute?: Router<NoRoute<boolean>> | ||
) { | ||
return ifGet<boolean>( | ||
() => mapRouteByType$( | ||
predicate, { | ||
match: route => { | ||
if (route.value === true) | ||
return route; | ||
if (route.value === false) | ||
return NoRoute.default; | ||
throw ifPredicateError; | ||
}, | ||
no: mapRouteIdentity, | ||
default: () => { | ||
throw ifPredicateMatchError; | ||
} | ||
} | ||
throw new Error('A predicate may only return true, false, a Match of true or false, or a NoMatch'); | ||
}); | ||
), | ||
mapMatchRoute, | ||
mapNoRoute | ||
); | ||
} | ||
function getRouteIfTrue <ROUTABLE> ( | ||
predicate: Predicate<ROUTABLE>, | ||
thenGetRoute: GetRoute<ROUTABLE>, | ||
elseMapRoute: (route: NoRoute) => Observableable<GetRoute<ROUTABLE>> | ||
): GetRoute<ROUTABLE> { | ||
return getRouteIfMatches(predicateToMatcher(predicate), value => thenGetRoute, elseMapRoute); | ||
export { _if as if } | ||
export function ifNo <ARG, VALUE> ( | ||
router: Router<ARG, VALUE>, | ||
mapNoRoute: Router<NoRoute<VALUE>> | ||
) { | ||
return mapRouteByType$(router, { | ||
no: mapNoRoute | ||
}); | ||
} | ||
export { getRouteIfTrue as if } | ||
const beforeError = new Error("before's router must only return DoRoute or NoRoute"); | ||
export function map <ROUTABLE> ( | ||
getRoute: GetRoute<ROUTABLE>, | ||
mapper: MapRoute<ROUTABLE> | ||
): GetRoute$<ROUTABLE> { | ||
return routable => Observable.of(getRoute) | ||
.flatMap(getNormalizedRoute(routable)) | ||
.flatMap(route => toObservable(mapper(route))) | ||
.flatMap(getNormalizedRoute(routable)) | ||
} | ||
export function before <ROUTABLE> ( | ||
beforeHandler: Handler<ROUTABLE>, | ||
getRoute: GetRoute<ROUTABLE> | ||
): GetRoute$<ROUTABLE> { | ||
return map(getRoute, route => routable => isDoRoute(route) | ||
? doRoute( | ||
() => toObservable(beforeHandler(routable)) | ||
export function before <ARG, VALUE> ( | ||
router: Router<ARG, VALUE>, | ||
action: Action | ||
) { | ||
return mapRouteByType$(router, { | ||
do: route => new DoRoute( | ||
() => toObservable(action()) | ||
.flatMap(_ => toObservable(route.action())), | ||
route.score | ||
) | ||
: route | ||
); | ||
), | ||
no: mapRouteIdentity, | ||
default: () => { | ||
throw beforeError; | ||
} | ||
}); | ||
} | ||
const afterError = new Error("after's router must only return DoRoute or NoRoute"); | ||
export function after <ROUTABLE> ( | ||
afterHandler: Handler<ROUTABLE>, | ||
getRoute: GetRoute<ROUTABLE> | ||
): GetRoute$<ROUTABLE> { | ||
return map(getRoute, route => routable => isDoRoute(route) | ||
? doRoute( | ||
export function after <ARG, VALUE> ( | ||
router: Router<ARG, VALUE>, | ||
action: Action | ||
) { | ||
return mapRouteByType$(router, { | ||
do: route => new DoRoute( | ||
() => toObservable(route.action()) | ||
.flatMap(_ => toObservable(afterHandler(routable))), | ||
.flatMap(_ => toObservable(action())), | ||
route.score | ||
) | ||
: route | ||
); | ||
), | ||
no: mapRouteIdentity, | ||
default: () => { | ||
throw afterError; | ||
} | ||
}); | ||
} | ||
function getRouteDefault <ROUTABLE> ( | ||
getRoute: GetRoute<ROUTABLE>, | ||
defaultMapRoute: (route: NoRoute) => Observableable<GetRoute<ROUTABLE>> | ||
function _switch ( | ||
getKey: Router<undefined, string>, | ||
mapKeyToRouter: Record<string, Router> | ||
) { | ||
return map(getRoute, route => isNoRoute(route) | ||
? defaultMapRoute(route) | ||
: routable => route | ||
); | ||
return ifGet(getKey, match => getRoute$(mapKeyToRouter[match.value])); | ||
} | ||
export { getRouteDefault as default } | ||
function getRouteSwitch <ROUTABLE> ( | ||
getKey: (routable: ROUTABLE) => Observableable<string>, | ||
mapKeyToGetRoute: Record<string, GetRoute<ROUTABLE>> | ||
) { | ||
return getRouteIfMatches(getKey, key => mapKeyToGetRoute[key]); | ||
} | ||
export { getRouteSwitch as switch } | ||
export { _switch as switch } |
"use strict"; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
var __spread = (this && this.__spread) || function () { | ||
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); | ||
return ar; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -14,3 +34,3 @@ var isDebug = function () { | ||
if (isDebug() && message) | ||
console.log.apply(console, [message].concat(optionalParams)); | ||
console.log.apply(console, __spread([message], optionalParams)); | ||
}, | ||
@@ -23,3 +43,3 @@ warn: function (message) { | ||
if (isDebug() && message) | ||
console.warn.apply(console, [message].concat(optionalParams)); | ||
console.warn.apply(console, __spread([message], optionalParams)); | ||
}, | ||
@@ -32,5 +52,5 @@ error: function (message) { | ||
if (isDebug() && message) | ||
console.error.apply(console, [message].concat(optionalParams)); | ||
console.error.apply(console, __spread([message], optionalParams)); | ||
} | ||
}; | ||
//# sourceMappingURL=Konsole.js.map |
import { Observable } from 'rxjs'; | ||
export declare type Observableable<T> = T | Observable<T> | Promise<T>; | ||
export declare function toObservable<T>(t: Observableable<T>): Observable<T>; | ||
export declare abstract class Route<VALUE = any> { | ||
private _route; | ||
static is<VALUE>(route: any): route is Route<VALUE>; | ||
} | ||
export declare class ScoredRoute<VALUE = any> extends Route<VALUE> { | ||
score: number; | ||
constructor(score?: number); | ||
static normalizedScore(score?: number): number; | ||
static is(route: Route): route is ScoredRoute; | ||
static combinedScore(score: any, otherScore: any): number; | ||
clone(score?: number): this; | ||
cloneWithCombinedScore(score?: number): this; | ||
} | ||
export declare type Action = () => Observableable<any>; | ||
export interface DoRoute { | ||
type: 'do'; | ||
export declare class DoRoute extends ScoredRoute<undefined> { | ||
action: Action; | ||
score: number; | ||
constructor(action: Action, score?: number); | ||
static is(route: Route): route is DoRoute; | ||
} | ||
export declare function isDoRoute(route: Route): route is DoRoute; | ||
export declare function isNoRoute(route: Route): route is NoRoute; | ||
export interface NoRoute { | ||
type: 'no'; | ||
reason: string; | ||
declare function _do<VALUE = any>(action: (value?: VALUE) => Observableable<any>, score?: number): (value: VALUE) => DoRoute; | ||
export { _do as do }; | ||
export declare class MatchRoute<VALUE = any> extends ScoredRoute<VALUE> { | ||
value: VALUE; | ||
constructor(value: VALUE, score?: number); | ||
static is<VALUE = any>(route: Route<VALUE>): route is MatchRoute<VALUE>; | ||
} | ||
export declare type Route = DoRoute | NoRoute; | ||
export declare type RawRoute = Route | { | ||
type?: 'do'; | ||
action: Action; | ||
score?: number; | ||
} | { | ||
type?: 'no'; | ||
export declare function match<VALUE = any>(value: VALUE, score?: number): () => MatchRoute<VALUE>; | ||
export declare class NoRoute<VALUE = any> extends Route<VALUE> { | ||
reason: string; | ||
}; | ||
export declare type GetRouteRaw<ROUTABLE> = (routable: ROUTABLE) => Observableable<Route | RawRoute | Action>; | ||
export declare type GetRoute<ROUTABLE> = (routable: ROUTABLE) => Observableable<Route>; | ||
export declare type GetRoute$<ROUTABLE> = (routable: ROUTABLE) => Observable<Route>; | ||
export declare type MapRoute<ROUTABLE> = (route: Route) => Observableable<GetRoute<ROUTABLE>>; | ||
export declare type Handler<ROUTABLE> = (routable: ROUTABLE) => Observableable<any>; | ||
export interface Match<VALUE> { | ||
value: VALUE; | ||
score?: number; | ||
static defaultReason: string; | ||
constructor(reason?: string, value?: VALUE); | ||
static default: NoRoute<any>; | ||
static default$: Observable<NoRoute<any>>; | ||
static is<VALUE = any>(route: Route): route is NoRoute<VALUE>; | ||
} | ||
export interface NoMatch<VALUE> { | ||
value?: VALUE; | ||
reason: string; | ||
declare function _no<VALUE>(reason?: string, value?: VALUE): () => NoRoute<VALUE>; | ||
export { _no as no }; | ||
export declare type Router<ARG = undefined, VALUE = any> = (arg?: ARG) => Observableable<Route<VALUE> | VALUE>; | ||
export declare function getRoute$<ARG, VALUE>(router: Router<ARG, VALUE>, arg?: ARG): Observable<Route<VALUE>>; | ||
export declare function mapRoute$<ARG, VALUE, ROUTE extends Route<VALUE> = Route<VALUE>>(router: Router<ARG, VALUE>, mapRoute: Router<ROUTE>, arg?: ARG): Observable<Route<any>>; | ||
export declare function route$<ARG, VALUE>(router: Router<ARG, VALUE>, arg?: ARG): Observable<boolean>; | ||
export declare function first<VALUE>(...routers: Router<undefined, VALUE>[]): Observable<Route<VALUE>>; | ||
export declare function best<VALUE = any>(...routers: Router<VALUE>[]): Observable<Route<VALUE>>; | ||
export declare function noop(action: Action): () => Observable<NoRoute<any>>; | ||
export interface MapTypeToRouteClass<VALUE> { | ||
route: Route<VALUE>; | ||
scored: ScoredRoute<VALUE>; | ||
do: DoRoute; | ||
match: MatchRoute<VALUE>; | ||
no: NoRoute<VALUE>; | ||
default: Route; | ||
} | ||
export declare type MatchResult<VALUE> = Match<VALUE> | NoMatch<VALUE>; | ||
export declare type Matcher<ROUTABLE, VALUE> = (routable: ROUTABLE) => Observableable<MatchResult<VALUE> | VALUE>; | ||
export declare type Predicate<ROUTABLE> = Matcher<ROUTABLE, boolean>; | ||
export declare function doRoute(action: () => Observableable<any>, score?: number): DoRoute; | ||
export declare const defaultReason = "none"; | ||
export declare function noRoute(reason?: string): NoRoute; | ||
export declare function normalizeRoute(rawRoute: RawRoute): Route; | ||
export declare const getNormalizedRoute: <ROUTABLE>(routable: ROUTABLE) => (getRoute: GetRouteRaw<ROUTABLE>) => Observable<Route>; | ||
export declare function route$<ROUTABLE>(routable: ROUTABLE, getRoute: GetRouteRaw<ROUTABLE>): Observable<boolean>; | ||
export declare function no<ROUTABLE>(reason?: string): GetRoute$<ROUTABLE>; | ||
export declare function getRouteDo<ROUTABLE>(handler: Handler<ROUTABLE>, score?: number): GetRoute$<ROUTABLE>; | ||
export { getRouteDo as do }; | ||
export declare function first<ROUTABLE>(...getRoutes: GetRouteRaw<ROUTABLE>[]): GetRoute$<ROUTABLE>; | ||
export declare function combinedScore(score: any, otherScore: any): number; | ||
export declare function routeWithCombinedScore(route: DoRoute, newScore: number): Route; | ||
export declare const minRoute: DoRoute; | ||
export declare function best<ROUTABLE>(...getRoutes: GetRouteRaw<ROUTABLE>[]): GetRoute<ROUTABLE>; | ||
export declare function noop<ROUTABLE>(handler: Handler<ROUTABLE>): GetRouteRaw<ROUTABLE>; | ||
export declare function isMatch<VALUE>(match: MatchResult<any>): match is Match<VALUE>; | ||
export declare function getNormalizedMatchResult$<ROUTABLE, VALUE>(matcher: Matcher<ROUTABLE, VALUE>, routable: ROUTABLE): Observable<MatchResult<VALUE>>; | ||
declare function getRouteIfMatches<ROUTABLE, VALUE>(matcher: Matcher<ROUTABLE, VALUE>, getThenGetRoute: (value: VALUE) => Observableable<GetRoute<ROUTABLE>>, elseMapRoute?: (route: NoRoute) => Observableable<GetRoute<ROUTABLE>>): GetRoute<ROUTABLE>; | ||
export { getRouteIfMatches as ifGet }; | ||
export declare function predicateToMatcher<ROUTABLE>(predicate: Predicate<ROUTABLE>): Matcher<ROUTABLE, boolean>; | ||
declare function getRouteIfTrue<ROUTABLE>(predicate: Predicate<ROUTABLE>, thenGetRoute: GetRoute<ROUTABLE>, elseMapRoute: (route: NoRoute) => Observableable<GetRoute<ROUTABLE>>): GetRoute<ROUTABLE>; | ||
export { getRouteIfTrue as if }; | ||
export declare function map<ROUTABLE>(getRoute: GetRoute<ROUTABLE>, mapper: MapRoute<ROUTABLE>): GetRoute$<ROUTABLE>; | ||
export declare function before<ROUTABLE>(beforeHandler: Handler<ROUTABLE>, getRoute: GetRoute<ROUTABLE>): GetRoute$<ROUTABLE>; | ||
export declare function after<ROUTABLE>(afterHandler: Handler<ROUTABLE>, getRoute: GetRoute<ROUTABLE>): GetRoute$<ROUTABLE>; | ||
declare function getRouteDefault<ROUTABLE>(getRoute: GetRoute<ROUTABLE>, defaultMapRoute: (route: NoRoute) => Observableable<GetRoute<ROUTABLE>>): GetRoute$<ROUTABLE>; | ||
export { getRouteDefault as default }; | ||
declare function getRouteSwitch<ROUTABLE>(getKey: (routable: ROUTABLE) => Observableable<string>, mapKeyToGetRoute: Record<string, GetRoute<ROUTABLE>>): GetRoute<ROUTABLE>; | ||
export { getRouteSwitch as switch }; | ||
export declare type RouteTypes<VALUE> = keyof MapTypeToRouteClass<VALUE>; | ||
export declare function getTypesFromRoute(route: Route): IterableIterator<"default" | "no" | "do" | "match" | "scored" | "route">; | ||
export declare type MapTypeToRouter<VALUE> = { | ||
[P in RouteTypes<VALUE>]: Router<MapTypeToRouteClass<VALUE>[P]>; | ||
}; | ||
export declare function mapRouteByType$<ARG, VALUE>(router: Router<ARG, VALUE>, mapTypeToRouter: Partial<MapTypeToRouter<VALUE>>, arg?: ARG): Observable<Route<any>>; | ||
export declare function ifGet<VALUE>(getMatch: Router<undefined, VALUE>, mapMatchRoute: Router<MatchRoute<VALUE>>, mapNoRoute?: Router<NoRoute<VALUE>>): Observable<Route<any>>; | ||
declare function _if(predicate: Router<undefined, boolean>, mapMatchRoute: Router<MatchRoute<boolean>>, mapNoRoute?: Router<NoRoute<boolean>>): Observable<Route<any>>; | ||
export { _if as if }; | ||
export declare function ifNo<ARG, VALUE>(router: Router<ARG, VALUE>, mapNoRoute: Router<NoRoute<VALUE>>): Observable<Route<any>>; | ||
export declare function before<ARG, VALUE>(router: Router<ARG, VALUE>, action: Action): Observable<Route<any>>; | ||
export declare function after<ARG, VALUE>(router: Router<ARG, VALUE>, action: Action): Observable<Route<any>>; | ||
declare function _switch(getKey: Router<undefined, string>, mapKeyToRouter: Record<string, Router>): Observable<Route<any>>; | ||
export { _switch as switch }; |
"use strict"; | ||
var __assign = (this && this.__assign) || Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return function (d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [0, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
return t; | ||
}; | ||
var __values = (this && this.__values) || function (o) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; | ||
if (m) return m.call(o); | ||
return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var Konsole_1 = require("./Konsole"); | ||
var rxjs_1 = require("rxjs"); | ||
@@ -21,99 +59,163 @@ function toObservable(t) { | ||
exports.toObservable = toObservable; | ||
function isDoRoute(route) { | ||
return route.type === 'do'; | ||
var Route = /** @class */ (function () { | ||
function Route() { | ||
} | ||
Route.is = function (route) { | ||
return route instanceof Route; | ||
}; | ||
return Route; | ||
}()); | ||
exports.Route = Route; | ||
var ScoredRoute = /** @class */ (function (_super) { | ||
__extends(ScoredRoute, _super); | ||
function ScoredRoute(score) { | ||
var _this = _super.call(this) || this; | ||
_this.score = ScoredRoute.normalizedScore(score); | ||
return _this; | ||
} | ||
ScoredRoute.normalizedScore = function (score) { | ||
return score != null && score >= 0 && score < 1 | ||
? score | ||
: 1; | ||
}; | ||
ScoredRoute.is = function (route) { | ||
return route instanceof ScoredRoute; | ||
}; | ||
ScoredRoute.combinedScore = function (score, otherScore) { | ||
return score * otherScore; | ||
}; | ||
ScoredRoute.prototype.clone = function (score) { | ||
score = ScoredRoute.normalizedScore(score); | ||
return score === this.score | ||
? this | ||
: Object.assign(Object.create(this.constructor.prototype), this, { score: score }); | ||
}; | ||
ScoredRoute.prototype.cloneWithCombinedScore = function (score) { | ||
return this.clone(ScoredRoute.combinedScore(this.score, ScoredRoute.normalizedScore(score))); | ||
}; | ||
return ScoredRoute; | ||
}(Route)); | ||
exports.ScoredRoute = ScoredRoute; | ||
var DoRoute = /** @class */ (function (_super) { | ||
__extends(DoRoute, _super); | ||
function DoRoute(action, score) { | ||
var _this = _super.call(this, score) || this; | ||
_this.action = action; | ||
return _this; | ||
} | ||
DoRoute.is = function (route) { | ||
return route instanceof DoRoute; | ||
}; | ||
return DoRoute; | ||
}(ScoredRoute)); | ||
exports.DoRoute = DoRoute; | ||
function _do(action, score) { | ||
return function (value) { return new DoRoute(function () { return action(value); }, score); }; | ||
} | ||
exports.isDoRoute = isDoRoute; | ||
function isNoRoute(route) { | ||
return route.type === 'no'; | ||
} | ||
exports.isNoRoute = isNoRoute; | ||
function doRoute(action, score) { | ||
if (score === void 0) { score = 1; } | ||
return { | ||
type: 'do', | ||
action: action, | ||
score: score | ||
exports.do = _do; | ||
var MatchRoute = /** @class */ (function (_super) { | ||
__extends(MatchRoute, _super); | ||
function MatchRoute(value, score) { | ||
var _this = _super.call(this, score) || this; | ||
_this.value = value; | ||
return _this; | ||
} | ||
MatchRoute.is = function (route) { | ||
return route instanceof MatchRoute; | ||
}; | ||
return MatchRoute; | ||
}(ScoredRoute)); | ||
exports.MatchRoute = MatchRoute; | ||
function match(value, score) { | ||
return function () { return new MatchRoute(value, score); }; | ||
} | ||
exports.doRoute = doRoute; | ||
exports.defaultReason = "none"; | ||
function noRoute(reason) { | ||
if (reason === void 0) { reason = exports.defaultReason; } | ||
return { | ||
type: 'no', | ||
reason: reason | ||
exports.match = match; | ||
var NoRoute = /** @class */ (function (_super) { | ||
__extends(NoRoute, _super); | ||
function NoRoute(reason, value) { | ||
if (reason === void 0) { reason = NoRoute.defaultReason; } | ||
var _this = _super.call(this) || this; | ||
_this.reason = reason; | ||
_this.value = value; | ||
return _this; | ||
} | ||
NoRoute.is = function (route) { | ||
return route instanceof NoRoute; | ||
}; | ||
NoRoute.defaultReason = "none"; | ||
NoRoute.default = new NoRoute(); | ||
NoRoute.default$ = rxjs_1.Observable.of(NoRoute.default); | ||
return NoRoute; | ||
}(Route)); | ||
exports.NoRoute = NoRoute; | ||
function _no(reason, value) { | ||
return function () { return new NoRoute(reason, value); }; | ||
} | ||
exports.noRoute = noRoute; | ||
function normalizeRoute(rawRoute) { | ||
if (!rawRoute || rawRoute.reason) | ||
return noRoute(rawRoute && rawRoute.reason); | ||
if (typeof (rawRoute) === 'function') | ||
return doRoute(rawRoute); | ||
if (rawRoute.action) | ||
return doRoute(rawRoute.action, rawRoute.score); | ||
throw new Error('invalid route'); | ||
exports.no = _no; | ||
var getRouteError = new Error('router must be a function'); | ||
function getRoute$(router, arg) { | ||
if (router == null) | ||
return NoRoute.default$; | ||
if (typeof router !== 'function') | ||
return rxjs_1.Observable.throw(getRouteError); | ||
return rxjs_1.Observable | ||
.of(router) | ||
.flatMap(function (router) { return toObservable(router(arg)); }) | ||
.map(function (result) { | ||
if (result == null) | ||
return NoRoute.default; | ||
if (Route.is(result)) | ||
return result; | ||
return new MatchRoute(result); | ||
}); | ||
} | ||
exports.normalizeRoute = normalizeRoute; | ||
exports.getNormalizedRoute = function (routable) { return function (getRoute) { return getRoute | ||
? toObservable(getRoute(routable)) | ||
.map(normalizeRoute) | ||
: rxjs_1.Observable.of(noRoute()); }; }; | ||
function route$(routable, getRoute) { | ||
return rxjs_1.Observable.of(getRoute) | ||
.flatMap(exports.getNormalizedRoute(routable)) | ||
.do(function (route) { return Konsole_1.konsole.log("route: returned a route", route); }) | ||
.flatMap(function (route) { return isDoRoute(route) | ||
? toObservable(route.action()) | ||
.do(function (_) { return Konsole_1.konsole.log("route: called action"); }) | ||
.map(function (_) { return true; }) | ||
: rxjs_1.Observable.of(false); }); | ||
exports.getRoute$ = getRoute$; | ||
function mapRoute$(router, mapRoute, arg) { | ||
return getRoute$(router, arg) | ||
.flatMap(function (route) { return getRoute$(mapRoute, route); }); | ||
} | ||
exports.mapRoute$ = mapRoute$; | ||
function route$(router, arg) { | ||
return getRoute$(router, arg) | ||
.filter(DoRoute.is) | ||
.flatMap(function (route) { return toObservable(route.action()); }) | ||
.mapTo(true) | ||
.defaultIfEmpty(false); | ||
} | ||
exports.route$ = route$; | ||
function no(reason) { | ||
return function (routable) { return rxjs_1.Observable.of(noRoute(reason)); }; | ||
var strictlyFilterError = new Error("route isn't DoRoute or NoRoute"); | ||
function strictlyFilterScored(route) { | ||
if (ScoredRoute.is(route)) | ||
return true; | ||
if (NoRoute.is(route)) | ||
return false; | ||
throw strictlyFilterError; | ||
} | ||
exports.no = no; | ||
function getRouteDo(handler, score) { | ||
return function (routable) { return rxjs_1.Observable.of(doRoute(function () { return handler(routable); }, score)); }; | ||
} | ||
exports.getRouteDo = getRouteDo; | ||
exports.do = getRouteDo; | ||
function first() { | ||
var getRoutes = []; | ||
var routers = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
getRoutes[_i] = arguments[_i]; | ||
routers[_i] = arguments[_i]; | ||
} | ||
return function (routable) { return rxjs_1.Observable.from(getRoutes) | ||
.concatMap(exports.getNormalizedRoute(routable)) | ||
.filter(isDoRoute) | ||
.take(1) // so that we don't keep going through routers after we find one that matches; | ||
.defaultIfEmpty(noRoute('first')); }; | ||
return rxjs_1.Observable.from(routers) | ||
.concatMap(function (router) { return getRoute$(router); }) | ||
.filter(strictlyFilterScored) | ||
.take(1) // so that we don't keep going through routers after we find one that matches | ||
.defaultIfEmpty(NoRoute.default); | ||
} | ||
exports.first = first; | ||
function combinedScore(score, otherScore) { | ||
return score * otherScore; | ||
} | ||
exports.combinedScore = combinedScore; | ||
function routeWithCombinedScore(route, newScore) { | ||
var score = combinedScore(newScore, route.score); | ||
return route.score === score | ||
? route | ||
: __assign({}, route, { score: score }); | ||
} | ||
exports.routeWithCombinedScore = routeWithCombinedScore; | ||
exports.minRoute = doRoute(function () { | ||
console.warn("BestRouter.minRoute.action should never be called"); | ||
var minRouteError = new Error("minRoute.action should never be called"); | ||
var minRoute = new DoRoute(function () { | ||
throw minRouteError; | ||
}, 0); | ||
function best() { | ||
var getRoutes = []; | ||
var routers = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
getRoutes[_i] = arguments[_i]; | ||
routers[_i] = arguments[_i]; | ||
} | ||
return function (routable) { return new rxjs_1.Observable(function (observer) { | ||
var bestRoute = exports.minRoute; | ||
var subscription = rxjs_1.Observable.from(getRoutes) | ||
return new rxjs_1.Observable(function (observer) { | ||
var bestRoute = minRoute; | ||
var subscription = rxjs_1.Observable.from(routers) | ||
.concatMap(function (router) { return getRoute$(router); }) | ||
.takeWhile(function (_) { return bestRoute.score < 1; }) | ||
.concatMap(exports.getNormalizedRoute(routable)) | ||
.filter(isDoRoute) | ||
.filter(strictlyFilterScored) | ||
.subscribe(function (route) { | ||
@@ -132,118 +234,147 @@ if (route.score > bestRoute.score) { | ||
? bestRoute | ||
: noRoute('best')); | ||
: NoRoute.default); | ||
observer.complete(); | ||
}); | ||
return function () { return subscription.unsubscribe(); }; | ||
}); }; | ||
}); | ||
} | ||
exports.best = best; | ||
function noop(handler) { | ||
return function (routable) { return toObservable(handler(routable)) | ||
.map(function (_) { return noRoute('noop'); }); }; | ||
function noop(action) { | ||
return function () { return toObservable(action()) | ||
.mapTo(NoRoute.default); }; | ||
} | ||
exports.noop = noop; | ||
function isMatch(match) { | ||
return (match.reason === undefined); | ||
function getTypesFromRoute(route) { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!NoRoute.is(route)) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, 'no']; | ||
case 1: | ||
_a.sent(); | ||
_a.label = 2; | ||
case 2: | ||
if (!DoRoute.is(route)) return [3 /*break*/, 4]; | ||
return [4 /*yield*/, 'do']; | ||
case 3: | ||
_a.sent(); | ||
_a.label = 4; | ||
case 4: | ||
if (!MatchRoute.is(route)) return [3 /*break*/, 6]; | ||
return [4 /*yield*/, 'match']; | ||
case 5: | ||
_a.sent(); | ||
_a.label = 6; | ||
case 6: | ||
if (!ScoredRoute.is(route)) return [3 /*break*/, 8]; | ||
return [4 /*yield*/, 'scored']; | ||
case 7: | ||
_a.sent(); | ||
_a.label = 8; | ||
case 8: | ||
if (!Route.is(route)) return [3 /*break*/, 10]; | ||
return [4 /*yield*/, 'route']; | ||
case 9: | ||
_a.sent(); | ||
_a.label = 10; | ||
case 10: return [4 /*yield*/, 'default']; | ||
case 11: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
} | ||
exports.isMatch = isMatch; | ||
function normalizeMatchResult(response) { | ||
if (response == null || response === false) | ||
return { | ||
reason: exports.defaultReason | ||
}; | ||
if (typeof (response) === 'object') { | ||
if (response.reason) { | ||
if (typeof (response.reason) !== 'string') | ||
throw new Error('The reason for NoMatch must be a string'); | ||
return { | ||
reason: response.reason | ||
}; | ||
exports.getTypesFromRoute = getTypesFromRoute; | ||
function getRouteByType(route, mapTypeToRouter) { | ||
try { | ||
for (var _a = __values(getTypesFromRoute(route)), _b = _a.next(); !_b.done; _b = _a.next()) { | ||
var type = _b.value; | ||
var router = mapTypeToRouter[type]; | ||
if (router) | ||
return getRoute$(router, route); | ||
} | ||
if (response.value !== undefined) { | ||
if (response.score !== undefined && typeof (response.score) !== 'number') | ||
throw new Error('The score for Match must be a number'); | ||
return { | ||
value: response.value, | ||
score: response.score || 1 | ||
}; | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_b && !_b.done && (_c = _a.return)) _c.call(_a); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
return { | ||
value: response, | ||
score: 1 | ||
}; | ||
return route; | ||
var e_1, _c; | ||
} | ||
function getNormalizedMatchResult$(matcher, routable) { | ||
return toObservable(matcher(routable)) | ||
.map(function (response) { return normalizeMatchResult(response); }); | ||
function mapRouteByType$(router, mapTypeToRouter, arg) { | ||
return mapRoute$(router, function (route) { return getRouteByType(route, mapTypeToRouter); }, arg); | ||
} | ||
exports.getNormalizedMatchResult$ = getNormalizedMatchResult$; | ||
function getRouteIfMatches(matcher, getThenGetRoute, elseMapRoute) { | ||
if (elseMapRoute === void 0) { elseMapRoute = function (route) { return function (routable) { return route; }; }; } | ||
return function (routable) { return getNormalizedMatchResult$(matcher, routable) | ||
.flatMap(function (matchResult) { return isMatch(matchResult) | ||
? toObservable(getThenGetRoute(matchResult.value)) | ||
.flatMap(exports.getNormalizedRoute(routable)) | ||
.map(function (route) { return isDoRoute(route) | ||
? routeWithCombinedScore(route, matchResult.score) | ||
: route; }) | ||
: toObservable(elseMapRoute(noRoute(matchResult.reason))) | ||
.flatMap(exports.getNormalizedRoute(routable)); }); }; | ||
exports.mapRouteByType$ = mapRouteByType$; | ||
var mapRouteIdentity = function (route) { return route; }; | ||
var getMatchError = new Error("ifGet's matchRouter should only return MatchRoute or NoRoute"); | ||
function ifGet(getMatch, mapMatchRoute, mapNoRoute) { | ||
return mapRouteByType$(getMatch, { | ||
match: function (route) { return mapRouteByType$(mapMatchRoute, { | ||
scored: function (_route) { return _route.cloneWithCombinedScore(route.score); } | ||
}, route); }, | ||
no: mapNoRoute || mapRouteIdentity, | ||
default: function () { | ||
throw getMatchError; | ||
} | ||
}); | ||
} | ||
exports.ifGet = getRouteIfMatches; | ||
function predicateToMatcher(predicate) { | ||
return function (routable) { return toObservable(predicate(routable)) | ||
.map(function (response) { | ||
if (response === true || response === false) | ||
return response; | ||
if (typeof (response) === 'object') { | ||
if (response.reason) | ||
return response; | ||
if (response.value !== undefined) { | ||
if (response.value === false) | ||
return false; | ||
if (response.value === true) | ||
return response; | ||
throw new Error('When returning a Match from a predicate, the value must be true or false'); | ||
} | ||
exports.ifGet = ifGet; | ||
// _if is a special case of ifGet | ||
// value of MatchRoute must be true or false | ||
// if value is false, NoRoute is instead returned | ||
var ifPredicateError = new Error("if's predicate must have value of true or false"); | ||
var ifPredicateMatchError = new Error("if's predicate must only return MatchRoute or NoRoute"); | ||
function _if(predicate, mapMatchRoute, mapNoRoute) { | ||
return ifGet(function () { return mapRouteByType$(predicate, { | ||
match: function (route) { | ||
if (route.value === true) | ||
return route; | ||
if (route.value === false) | ||
return NoRoute.default; | ||
throw ifPredicateError; | ||
}, | ||
no: mapRouteIdentity, | ||
default: function () { | ||
throw ifPredicateMatchError; | ||
} | ||
throw new Error('A predicate may only return true, false, a Match of true or false, or a NoMatch'); | ||
}); }; | ||
}); }, mapMatchRoute, mapNoRoute); | ||
} | ||
exports.predicateToMatcher = predicateToMatcher; | ||
function getRouteIfTrue(predicate, thenGetRoute, elseMapRoute) { | ||
return getRouteIfMatches(predicateToMatcher(predicate), function (value) { return thenGetRoute; }, elseMapRoute); | ||
exports.if = _if; | ||
function ifNo(router, mapNoRoute) { | ||
return mapRouteByType$(router, { | ||
no: mapNoRoute | ||
}); | ||
} | ||
exports.if = getRouteIfTrue; | ||
function map(getRoute, mapper) { | ||
return function (routable) { return rxjs_1.Observable.of(getRoute) | ||
.flatMap(exports.getNormalizedRoute(routable)) | ||
.flatMap(function (route) { return toObservable(mapper(route)); }) | ||
.flatMap(exports.getNormalizedRoute(routable)); }; | ||
exports.ifNo = ifNo; | ||
var beforeError = new Error("before's router must only return DoRoute or NoRoute"); | ||
function before(router, action) { | ||
return mapRouteByType$(router, { | ||
do: function (route) { return new DoRoute(function () { return toObservable(action()) | ||
.flatMap(function (_) { return toObservable(route.action()); }); }, route.score); }, | ||
no: mapRouteIdentity, | ||
default: function () { | ||
throw beforeError; | ||
} | ||
}); | ||
} | ||
exports.map = map; | ||
function before(beforeHandler, getRoute) { | ||
return map(getRoute, function (route) { return function (routable) { return isDoRoute(route) | ||
? doRoute(function () { return toObservable(beforeHandler(routable)) | ||
.flatMap(function (_) { return toObservable(route.action()); }); }, route.score) | ||
: route; }; }); | ||
} | ||
exports.before = before; | ||
function after(afterHandler, getRoute) { | ||
return map(getRoute, function (route) { return function (routable) { return isDoRoute(route) | ||
? doRoute(function () { return toObservable(route.action()) | ||
.flatMap(function (_) { return toObservable(afterHandler(routable)); }); }, route.score) | ||
: route; }; }); | ||
var afterError = new Error("after's router must only return DoRoute or NoRoute"); | ||
function after(router, action) { | ||
return mapRouteByType$(router, { | ||
do: function (route) { return new DoRoute(function () { return toObservable(route.action()) | ||
.flatMap(function (_) { return toObservable(action()); }); }, route.score); }, | ||
no: mapRouteIdentity, | ||
default: function () { | ||
throw afterError; | ||
} | ||
}); | ||
} | ||
exports.after = after; | ||
function getRouteDefault(getRoute, defaultMapRoute) { | ||
return map(getRoute, function (route) { return isNoRoute(route) | ||
? defaultMapRoute(route) | ||
: function (routable) { return route; }; }); | ||
function _switch(getKey, mapKeyToRouter) { | ||
return ifGet(getKey, function (match) { return getRoute$(mapKeyToRouter[match.value]); }); | ||
} | ||
exports.default = getRouteDefault; | ||
function getRouteSwitch(getKey, mapKeyToGetRoute) { | ||
return getRouteIfMatches(getKey, function (key) { return mapKeyToGetRoute[key]; }); | ||
} | ||
exports.switch = getRouteSwitch; | ||
exports.switch = _switch; | ||
//# sourceMappingURL=Router.js.map |
@@ -7,4 +7,4 @@ { | ||
}, | ||
"version": "0.17.0", | ||
"description": "rules-based app engine", | ||
"version": "0.17.1", | ||
"description": "functional rules engine", | ||
"main": "dist/prague.js", | ||
@@ -11,0 +11,0 @@ "types": "dist/prague.d.ts", |
1003
test/router.js
@@ -150,7 +150,7 @@ "use strict"; | ||
describe('p.doRoute', () => { | ||
it('should create an doRoute with supplied action and no score', () => { | ||
describe('new p.DoRoute', () => { | ||
it('should create a DoRoute with supplied action and no score', () => { | ||
let action = () => {}; | ||
let route = p.doRoute(action); | ||
expect(route.type).to.eql('do'); | ||
let route = new p.DoRoute(action); | ||
expect(route instanceof p.DoRoute).to.be.true; | ||
expect(route.action).to.eql(action); | ||
@@ -160,6 +160,6 @@ expect(route.score).to.eql(1); | ||
it('should create an doRoute with supplied action and score', () => { | ||
it('should create a DoRoute with supplied action and score', () => { | ||
let action = () => {}; | ||
let route = p.doRoute(action, 0.5); | ||
expect(route.type).to.eql('do'); | ||
let route = new p.DoRoute(action, 0.5); | ||
expect(route instanceof p.DoRoute).to.be.true; | ||
expect(route.action).to.eql(action); | ||
@@ -171,7 +171,7 @@ expect(route.score).to.eql(.5); | ||
describe('p.noRoute', () => { | ||
describe('p.NoRoute', () => { | ||
it('should create a NoRoute with default reason', () => { | ||
let route = p.noRoute(); | ||
let route = new p.NoRoute(); | ||
expect(route.type).to.eql('no'); | ||
expect(route instanceof p.NoRoute).to.be.true; | ||
expect(route.reason).to.eql('none'); | ||
@@ -183,5 +183,5 @@ expect(route.action).to.be.undefined; | ||
it('should create a NoRoute with supplied reason', () => { | ||
let route = p.noRoute('reason'); | ||
let route = new p.NoRoute('reason'); | ||
expect(route.type).to.eql('no'); | ||
expect(route instanceof p.NoRoute).to.be.true; | ||
expect(route.reason).to.eql('reason'); | ||
@@ -193,195 +193,135 @@ expect(route.action).to.be.undefined; | ||
describe('p.normalizeRoute', () => { | ||
it('should normalize undefined', () => { | ||
let route = p.normalizeRoute(undefined); | ||
describe('p.do', () => { | ||
it('should return a function returning doRoute using supplied action and no score', () => { | ||
let handled; | ||
let route = p.do(m => { handled = m; })(foo); | ||
expect(route.type).to.eql('no'); | ||
expect(route.reason).to.eql('none'); | ||
expect(route.action).to.be.undefined; | ||
expect(route.score).to.be.undefined; | ||
expect(route instanceof p.DoRoute).to.be.true; | ||
expect(route.score).to.eql(1); | ||
route.action(); | ||
expect(handled).to.eql(foo); | ||
}); | ||
it('should normalize { reason }', () => { | ||
let route = p.normalizeRoute({ reason: 'reason' }); | ||
it('should return a function returning doRoute using supplied action and no score', () => { | ||
let handled; | ||
let route = p.do(m => { handled = m; }, .5)(foo); | ||
expect(route.type).to.eql('no'); | ||
expect(route.reason).to.eql('reason'); | ||
expect(route.action).to.be.undefined; | ||
expect(route.score).to.be.undefined; | ||
expect(route instanceof p.DoRoute).to.be.true; | ||
expect(route.score).to.eql(.5); | ||
route.action(); | ||
expect(handled).to.eql(foo); | ||
}); | ||
}); | ||
it('should normalize a noRoute without a reason', () => { | ||
let route = p.normalizeRoute(p.noRoute()); | ||
expect(route.type).to.eql('no'); | ||
describe('p.no', () => { | ||
it('should return a NoRoute with the default reason', () => { | ||
let route = p.no()(foo) | ||
expect(route instanceof p.NoRoute).to.be.true; | ||
expect(route.reason).to.eql('none'); | ||
expect(route.action).to.be.undefined; | ||
expect(route.score).to.be.undefined; | ||
}); | ||
it('should normalize a noRoute with a reason', () => { | ||
let route = p.normalizeRoute(p.noRoute('reason')); | ||
expect(route.type).to.eql('no'); | ||
it('should return a NoRoute with the supplied reason', () => { | ||
let route = p.no('reason')(foo); | ||
expect(route instanceof p.NoRoute).to.be.true; | ||
expect(route.reason).to.eql('reason'); | ||
expect(route.action).to.be.undefined; | ||
expect(route.score).to.be.undefined; | ||
}); | ||
it('should normalize an action', () => { | ||
let action = () => {} | ||
let route = p.normalizeRoute(action); | ||
expect(route.type).to.eql('do'); | ||
expect(route.action).to.eql(action); | ||
expect(route.score).to.eql(1); | ||
expect(route.reason).to.be.undefined; | ||
}); | ||
it('should normalize { action }', () => { | ||
let action = () => {} | ||
let route = p.normalizeRoute({ action }); | ||
expect(route.type).to.eql('do'); | ||
expect(route.action).to.eql(action); | ||
expect(route.score).to.eql(1); | ||
expect(route.reason).to.be.undefined; | ||
}); | ||
it('should normalize { action, score }', () => { | ||
let action = () => {} | ||
let route = p.normalizeRoute({ action, score: .5 }); | ||
expect(route.type).to.eql('do'); | ||
expect(route.action).to.eql(action); | ||
expect(route.score).to.eql(.5); | ||
expect(route.reason).to.be.undefined; | ||
}); | ||
it('should normalize a doRoute without a score', () => { | ||
let action = () => {} | ||
let route = p.normalizeRoute(p.doRoute(action)); | ||
expect(route.type).to.eql('do'); | ||
expect(route.action).to.eql(action); | ||
expect(route.score).to.eql(1); | ||
expect(route.reason).to.be.undefined; | ||
}); | ||
it('should normalize a doRoute with a score', () => { | ||
let action = () => {} | ||
let route = p.normalizeRoute(p.doRoute(action, .5)); | ||
expect(route.type).to.eql('do'); | ||
expect(route.action).to.eql(action); | ||
expect(route.score).to.eql(.5); | ||
expect(route.reason).to.be.undefined; | ||
}); | ||
}); | ||
describe('p.getNormalizedRoute', () => { | ||
it("should treat undefined as NoRoute", (done) => { | ||
Observable | ||
.of(undefined) | ||
.flatMap(p.getNormalizedRoute(foo)) | ||
.subscribe(route => { | ||
expect(route.type).to.eql('no'); | ||
}, passErr, done) | ||
describe('p.getRoute$', () => { | ||
it('should throw on a non-router.', (done) => { | ||
p | ||
.getRoute$("non-route") | ||
.subscribe(throwErr, error => done(), throwErr); | ||
}); | ||
it("should not route to NoRoute", (done) => { | ||
Observable | ||
.of(p.no('reason')) | ||
.flatMap(p.getNormalizedRoute(foo)) | ||
.subscribe(route => { | ||
expect(route.type).to.eql('no'); | ||
expect(route.reason).to.eql('reason'); | ||
}, passErr, done) | ||
it('should throw on a router that throws.', (done) => { | ||
p | ||
.getRoute$(() => { | ||
throw new Error('like this'); | ||
}) | ||
.subscribe(throwErr, error => done(), throwErr); | ||
}); | ||
it("should route to supplied route", (done) => { | ||
Observable | ||
.of(p.do(c => {}, .5)) | ||
.flatMap(p.getNormalizedRoute(foo)) | ||
it('should return a MatchRoute on a function returning a non-route', (done) => { | ||
p | ||
.getRoute$(() => "non-route") | ||
.subscribe(route => { | ||
expect(route.type).to.eql('do'); | ||
expect(route.score).to.eql(.5); | ||
}, passErr, done) | ||
expect(route instanceof p.MatchRoute).to.be.true; | ||
}, passErr, done); | ||
}); | ||
it("should route to un-normalized route", (done) => { | ||
let action = () => {}; | ||
Observable | ||
.of(c => action) | ||
.flatMap(p.getNormalizedRoute(foo)) | ||
.subscribe(route => { | ||
expect(route.type).to.eql('do'); | ||
expect(route.score).to.eql(1); | ||
expect(route.action).to.eql(action); | ||
}, passErr, done) | ||
it('should return a Noroute from an undefined router', (done) => { | ||
p | ||
.getRoute$(undefined) | ||
.subscribe(r => { | ||
expect(r instanceof p.NoRoute).to.be.true; | ||
}, passErr, done); | ||
}); | ||
}); | ||
describe('p.do', () => { | ||
it('should return an doRoute using supplied handler and no score', (done) => { | ||
let handled; | ||
it('should return a route from a Router, passing no value', (done) => { | ||
let route = new p.DoRoute(() => {}); | ||
p.do(m => { handled = m; }) | ||
(foo) | ||
.subscribe(route => { | ||
expect(route.type).to.eql('do'); | ||
expect(route.score).to.eql(1); | ||
route.action(); | ||
expect(handled).to.eql(foo); | ||
p | ||
.getRoute$(() => route) | ||
.subscribe(r => { | ||
expect(r).to.eql(route); | ||
}, passErr, done); | ||
}); | ||
it('should return an doRoute using supplied handler and score', (done) => { | ||
let handled; | ||
p.do(m => { handled = m; }, .5) | ||
(foo) | ||
.subscribe(route => { | ||
expect(route.type).to.eql('do'); | ||
expect(route.score).to.eql(.5); | ||
route.action(); | ||
expect(handled).to.eql(foo); | ||
it('should return a route from a Router, passing the value', (done) => { | ||
let routed; | ||
p | ||
.getRoute$((value) => new p.DoRoute(() => { routed = value }), "value") | ||
.subscribe(r => { | ||
r.action(); | ||
expect(routed).to.eql("value"); | ||
}, passErr, done); | ||
}); | ||
}); | ||
describe('p.no', () => { | ||
it('should return a NoRoute with the default reason', done => { | ||
p.no() | ||
(foo) | ||
.subscribe(route => { | ||
expect(route.type).to.eql('no'); | ||
expect(route.reason).to.eql('none'); | ||
describe('p.route$', () => { | ||
it("should return false on NoRoute with no arg", (done) => { | ||
p.route$( | ||
p.no() | ||
) | ||
.subscribe(t => { | ||
expect(t).to.be.false; | ||
}, passErr, done); | ||
}); | ||
it('should return a NoRoute with the supplied reason', done => { | ||
p.no('reason') | ||
(foo) | ||
.subscribe(route => { | ||
expect(route.type).to.eql('no'); | ||
expect(route.reason).to.eql('reason'); | ||
it("should return false on NoRoute with arg", (done) => { | ||
p.route$( | ||
p.no(), | ||
foo | ||
) | ||
.subscribe(t => { | ||
expect(t).to.be.false; | ||
}, passErr, done); | ||
}); | ||
}); | ||
describe('p.route$', () => { | ||
it("should return false on NoRoute", (done) => { | ||
p.route$(foo, p.no()) | ||
it("should return true on DoRoute with no arg", (done) => { | ||
let routed; | ||
p.route$( | ||
p.do(() => { | ||
routed = true; | ||
}) | ||
) | ||
.subscribe(t => { | ||
expect(t).to.be.false; | ||
expect(t).to.be.true; | ||
expect(routed).to.be.true; | ||
}, passErr, done); | ||
}); | ||
it("should return true on DoRoute", (done) => { | ||
it("should return true on DoRoute with arg", (done) => { | ||
let routed; | ||
p.route$(foo, p.do(() => { | ||
routed = true; | ||
})) | ||
p.route$( | ||
p.do(() => { | ||
routed = true; | ||
}), | ||
foo | ||
) | ||
.subscribe(t => { | ||
@@ -392,7 +332,23 @@ expect(t).to.be.true; | ||
}); | ||
it("should return true on DoRoute, passing arg to action", (done) => { | ||
let routed; | ||
p.route$( | ||
p.do(m => { | ||
routed = m; | ||
}), | ||
foo | ||
) | ||
.subscribe(t => { | ||
expect(t).to.be.true; | ||
expect(routed).to.eql(foo); | ||
}, passErr, done); | ||
}); | ||
}); | ||
describe('p.first', () => { | ||
it('should return false on no routers', (done) => | ||
p.route$(foo, p.first()) | ||
p.route$($ => p.first()) | ||
.subscribe(t => expect(t).to.be.false, passErr, done) | ||
@@ -402,3 +358,3 @@ ); | ||
it('should return false on only null/undefined routers', (done) => | ||
p.route$(foo, p.first( | ||
p.route$($ => p.first( | ||
null, | ||
@@ -411,6 +367,6 @@ undefined | ||
it('should return false on only unsuccessful and null/undefined routers', (done) => | ||
p.route$(foo, p.first( | ||
p.no(), | ||
null, | ||
undefined | ||
p.route$($ => p.first( | ||
p.no(), | ||
null, | ||
undefined | ||
)) | ||
@@ -421,3 +377,3 @@ .subscribe(t => expect(t).to.be.false, passErr, done) | ||
it('should return false on no successful routers', (done) => { | ||
p.route$(foo, p.first( | ||
p.route$($ => p.first( | ||
p.no() | ||
@@ -431,3 +387,3 @@ )) | ||
p.route$(foo, p.first( | ||
p.route$($ => p.first( | ||
p.do(m => { | ||
@@ -446,3 +402,3 @@ routed = true; | ||
p.route$(foo, p.first( | ||
p.route$($ => p.first( | ||
null, | ||
@@ -462,3 +418,3 @@ undefined, | ||
p.route$(foo, p.first( | ||
p.route$($ => p.first( | ||
p.no(), | ||
@@ -475,32 +431,60 @@ p.do(m => { | ||
describe('p.combineScore', () => { | ||
describe('p.ScoredRoute.combinedScore', () => { | ||
it("should return combined score", () => { | ||
expect(p.combinedScore(.4, .25)).to.eql(.1); | ||
expect(p.ScoredRoute.combinedScore(.4, .25)).to.eql(.1); | ||
}); | ||
}) | ||
describe('p.routeWithCombinedScore', () => { | ||
it("should return route with combined score", () => { | ||
expect(p.routeWithCombinedScore( | ||
p.doRoute(() => {}, .4), | ||
.25 | ||
).score).to.eql(.1); | ||
describe('p.doScore.clone', () => { | ||
it("should return original route when supplied score matches route score", () => { | ||
let action = () => {} | ||
let original = new p.DoRoute(action, .4); | ||
let route = original.clone(.4); | ||
expect(route instanceof p.DoRoute).to.be.true; | ||
expect(route).to.eql(original); | ||
}); | ||
}) | ||
describe('p.minRoute', () => { | ||
it("should have a zero score", () => { | ||
let route = p.minRoute; | ||
expect(route.score).to.eql(0); | ||
it("should return route with supplied score", () => { | ||
let action = () => {} | ||
let original = new p.DoRoute(action, .4); | ||
let route = original.clone(.25); | ||
expect(route instanceof p.DoRoute).to.be.true; | ||
expect(route.action).to.eql(action); | ||
expect(route.score).to.eql(.25); | ||
}); | ||
}); | ||
describe('p.doScore.cloneWithCombinedScore', () => { | ||
it("should return original route when score to be combined is 1", () => { | ||
let action = () => {} | ||
let original = new p.DoRoute(action, .4); | ||
let route = original.cloneWithCombinedScore(); | ||
expect(route instanceof p.DoRoute).to.be.true; | ||
expect(route).to.eql(original); | ||
}); | ||
it("should return new route when score to be combined is not 1", () => { | ||
let action = () => {} | ||
let original = new p.DoRoute(action, .4); | ||
let route = original.cloneWithCombinedScore(.25); | ||
expect(route instanceof p.DoRoute).to.be.true; | ||
expect(route.action).to.eql(action); | ||
expect(route.score).to.eql(.1); | ||
}); | ||
}) | ||
describe('p.best', () => { | ||
it('should return false on no routers', (done) => | ||
p.route$(foo, p.best()) | ||
.subscribe(t => expect(t).to.be.false, passErr, done) | ||
); | ||
it('should return NoRoute on no routers', (done) => { | ||
p.route$($ => p.best()) | ||
.subscribe(t => { | ||
expect(t).to.be.false; | ||
}, passErr, done) | ||
}); | ||
it('should return false on only null/undefined routers', (done) => | ||
p.route$(foo, p.best( | ||
it('should return NoRoute on only null/undefined routers', (done) => | ||
p.route$($ => p.best( | ||
null, | ||
@@ -512,4 +496,4 @@ undefined | ||
it('should return false on only unsuccessful and null/undefined routers', (done) => | ||
p.route$(foo, p.best( | ||
it('should return NoRoute on only unsuccessful and null/undefined routers', (done) => | ||
p.route$($ => p.best( | ||
p.no(), | ||
@@ -522,4 +506,4 @@ null, | ||
it('should return false on no successful routers', (done) => { | ||
p.route$(foo, p.best( | ||
it('should return NoRoute on no successful routers', (done) => { | ||
p.route$($ => p.best( | ||
p.no() | ||
@@ -533,3 +517,3 @@ )) | ||
p.route$(foo, p.best( | ||
p.route$($ => p.best( | ||
p.do(m => { | ||
@@ -547,3 +531,3 @@ routed = true; | ||
p.route$(foo, p.best( | ||
p.route$($ => p.best( | ||
null, | ||
@@ -563,3 +547,3 @@ undefined, | ||
p.route$(foo, p.best( | ||
p.route$($ => p.best( | ||
p.no(), | ||
@@ -578,3 +562,3 @@ p.do(m => { | ||
p.route$(foo, p.best( | ||
p.route$($ => p.best( | ||
p.do(m => { | ||
@@ -593,3 +577,3 @@ routed = true; | ||
p.route$(foo, p.best( | ||
p.route$($ => p.best( | ||
p.do(_ => { routed = 'first'; }, 0.75), | ||
@@ -606,3 +590,3 @@ p.do(_ => { routed = 'second'; }, 0.50) | ||
p.route$(foo, p.best( | ||
p.route$($ => p.best( | ||
p.do(_ => { routed = 'first'; }, .5), | ||
@@ -619,3 +603,3 @@ p.do(_ => { routed = 'second'; }, .75) | ||
p.route$(foo, p.best( | ||
p.route$($ => p.best( | ||
p.do(_ => { routed = 'first'; }), | ||
@@ -632,3 +616,3 @@ p.do(_ => { routed = 'second'; }, .75) | ||
p.route$(foo, p.best( | ||
p.route$($ => p.best( | ||
p.do(_ => { routed = 'first'; }, 0.75), | ||
@@ -641,2 +625,3 @@ p.do(_ => { routed = 'second'; }, 0.75) | ||
}); | ||
}); | ||
@@ -648,3 +633,3 @@ | ||
p.route$(foo, p.noop( | ||
p.route$(p.noop( | ||
m => { | ||
@@ -661,100 +646,7 @@ routed = true; | ||
describe('p.isMatch', () => { | ||
it("return true on a match", () => { | ||
expect(p.isMatch({ value: 15 })).to.be.true; | ||
}); | ||
it("return false on no match", () => { | ||
expect(p.isMatch({ reason: 'yo' })).to.be.false; | ||
}); | ||
}); | ||
describe('p.getNormalizedMatchResult$', (done) => { | ||
it("normalizes undefined", () => { | ||
p | ||
.getNormalizedMatchResult$(m => undefined) | ||
.subscribe(match => { | ||
expect(match.value).to.be.undefined; | ||
expect(match.reason).to.eql('none'); | ||
}, passErr, done); | ||
}); | ||
it("normalizes false", () => { | ||
p | ||
.getNormalizedMatchResult$(m => undefined) | ||
.subscribe(match => { | ||
expect(match.value).to.be.undefined; | ||
expect(match.reason).to.eql('none'); | ||
}, passErr, done); | ||
}); | ||
it("normalizes null", () => { | ||
p | ||
.getNormalizedMatchResult$(m => undefined) | ||
.subscribe(match => { | ||
expect(match.value).to.be.undefined; | ||
expect(match.reason).to.eql('none'); | ||
}, passErr, done); | ||
}); | ||
it("normalizes { reason }", () => { | ||
p | ||
.getNormalizedMatchResult$(m => ({ reason: 'reason' })) | ||
.subscribe(match => { | ||
expect(match.reason).to.eql('reason'); | ||
expect(match.value).to.be.undefined; | ||
}, passErr, done); | ||
}); | ||
it("normalizes number", () => { | ||
p | ||
.getNormalizedMatchResult$(m => 15) | ||
.subscribe(match => { | ||
expect(match.value).to.eql(15); | ||
expect(match.score).to.eql(1); | ||
expect(match.reason).to.be.undefined; | ||
}, passErr, done); | ||
}); | ||
it("normalizes object", () => { | ||
p | ||
.getNormalizedMatchResult$(m => ({ dog: 15 })) | ||
.subscribe(match => { | ||
expect(match.value.dog).to.eql(15); | ||
expect(match.reason).to.be.undefined; | ||
}, passErr, done); | ||
}); | ||
it("normalizes { value }", () => { | ||
p | ||
.getNormalizedMatchResult$(m => ({ | ||
value: 15 | ||
})) | ||
.subscribe(match => { | ||
expect(match.value).to.eql(15); | ||
expect(match.score).to.eql(1); | ||
expect(match.reason).to.be.undefined; | ||
}, passErr, done); | ||
}); | ||
it("normalizes { value, score }", () => { | ||
p | ||
.getNormalizedMatchResult$(m => ({ | ||
value: 15, | ||
score: .5 | ||
})) | ||
.subscribe(match => { | ||
expect(match.value).to.eql(15); | ||
expect(match.score).to.eql(.5); | ||
expect(match.reason).to.be.undefined; | ||
}, passErr, done); | ||
}); | ||
}); | ||
describe('p.ifGet', () => { | ||
it("should return false on no match when 'else' router doesn't exist", (done) => | ||
p.route$(notFoo, p.ifGet( | ||
barIfFoo, | ||
value => p.do(throwErr) | ||
p.route$($ => p.ifGet( | ||
() => undefined, | ||
p.do(throwErr) | ||
)) | ||
@@ -765,5 +657,5 @@ .subscribe(t => expect(t).to.be.false, passErr, done) | ||
it("should return false on no match when 'else' router doesn't exist", (done) => | ||
p.route$(notFoo, p.ifGet( | ||
barIfFoo, | ||
value => p.do(throwErr) | ||
p.route$($ => p.ifGet( | ||
() => undefined, | ||
p.do(throwErr) | ||
)) | ||
@@ -774,6 +666,6 @@ .subscribe(t => expect(t).to.be.false, passErr, done) | ||
it("should return false on no match when 'else' router doesn't route", (done) => | ||
p.route$(notFoo, p.ifGet( | ||
barIfFoo, | ||
value => p.do(throwErr), | ||
route => p.no() | ||
p.route$($ => p.ifGet( | ||
() => undefined, | ||
p.do(throwErr), | ||
p.no() | ||
)) | ||
@@ -784,7 +676,9 @@ .subscribe(t => expect(t).to.be.false, passErr, done) | ||
it("should return false on match when 'if' router doesn't route and 'else' router exists", (done) => | ||
p.route$(foo, p.ifGet( | ||
barIfFoo, | ||
value => p.no(), | ||
route => p.do(throwErr) | ||
)) | ||
p.route$( | ||
$ => p.ifGet( | ||
() => true, | ||
p.no(), | ||
p.do(throwErr) | ||
) | ||
) | ||
.subscribe(t => expect(t).to.be.false, passErr, done) | ||
@@ -796,8 +690,10 @@ ); | ||
p.route$(foo, p.ifGet( | ||
barIfFoo, | ||
value => p.do(m => { | ||
routed = true; | ||
}) | ||
)) | ||
p.route$( | ||
$ => p.ifGet( | ||
() => true, | ||
p.do(m => { | ||
routed = true; | ||
}) | ||
) | ||
) | ||
.subscribe(n => { | ||
@@ -811,9 +707,11 @@ expect(routed).to.be.true; | ||
p.route$(foo, p.ifGet( | ||
barIfFoo, | ||
value => p.do(m => { | ||
routed = true; | ||
}), | ||
route => p.do(throwErr) | ||
)) | ||
p.route$( | ||
$ => p.ifGet( | ||
() => true, | ||
p.do(m => { | ||
routed = true; | ||
}), | ||
p.do(throwErr) | ||
) | ||
) | ||
.subscribe(n => { | ||
@@ -827,9 +725,11 @@ expect(routed).to.be.true; | ||
p.route$(notFoo, p.ifGet( | ||
barIfFoo, | ||
value => p.do(throwErr), | ||
route => p.do(m => { | ||
routed = true; | ||
}) | ||
)) | ||
p.route$( | ||
$ => p.ifGet( | ||
() => undefined, | ||
p.do(throwErr), | ||
p.do(m => { | ||
routed = true; | ||
}) | ||
) | ||
) | ||
.subscribe(n => { | ||
@@ -843,9 +743,11 @@ expect(routed).to.be.true; | ||
p.route$(notFoo, p.ifGet( | ||
c => ({ reason: 'reason' }), | ||
value => p.do(throwErr), | ||
route => p.do(m => { | ||
routed = route.reason; | ||
}) | ||
)) | ||
p.route$( | ||
$ => p.ifGet( | ||
p.no('reason'), | ||
p.do(throwErr), | ||
p.do(route => { | ||
routed = route.reason; | ||
}) | ||
) | ||
) | ||
.subscribe(n => { | ||
@@ -859,9 +761,11 @@ expect(routed).to.eql('reason'); | ||
p.route$(foo, p.ifGet( | ||
c => ({ value: 'value' }), | ||
value => p.do(c => { | ||
routed = value; | ||
}), | ||
route => p.do(throwErr) | ||
)) | ||
p.route$( | ||
$ => p.ifGet( | ||
() => 'value', | ||
p.do(match => { | ||
routed = match.value; | ||
}), | ||
p.do(throwErr) | ||
) | ||
) | ||
.subscribe(n => { | ||
@@ -872,23 +776,7 @@ expect(routed).to.eql('value'); | ||
it("should pass value to 'then' handler on match", (done) => { | ||
let routed; | ||
p.route$(foo, p.ifGet( | ||
c => ({ value: 'value' }), | ||
value => p.do(() => { | ||
routed = value; | ||
}), | ||
route => p.do(throwErr) | ||
)) | ||
.subscribe(n => { | ||
expect(routed).to.eql('value'); | ||
}, passErr, done); | ||
}); | ||
it("should return score=1 when score not supplied", (done) => { | ||
p.ifGet( | ||
barIfFoo, | ||
value => p.do(m => {}) | ||
() => 5, | ||
p.do(() => {}) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
@@ -902,6 +790,5 @@ expect(route.score).to.eql(1); | ||
p.ifGet( | ||
m => ({ value: 'dog', score: 0.4 }), | ||
value => p.do(m => {}) | ||
p.match('dog', 0.4), | ||
p.do(m => {}) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
@@ -914,6 +801,6 @@ expect(route.score).to.eql(.4); | ||
let handled; | ||
p.route$(foo, p.ifGet( | ||
m => ({ value: 'dog' }), | ||
value => p.do(() => { | ||
handled = value; | ||
p.route$($ => p.ifGet( | ||
() => 'dog', | ||
p.do(match => { | ||
handled = match.value; | ||
}) | ||
@@ -926,8 +813,7 @@ )) | ||
it("should return combined score when route score supplied", (done) => { | ||
it("should return route score when no match score supplied", (done) => { | ||
p.ifGet( | ||
barIfFoo, | ||
value => p.do(() => {}, .25) | ||
() => "dog", | ||
p.do(() => {}, .25) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
@@ -940,6 +826,5 @@ expect(route.score).to.eql(.25); | ||
p.ifGet( | ||
m => ({ value: 'cat', score: 0.4 }), | ||
value => p.do(() => {}, .25) | ||
p.match('cat', 0.4), | ||
p.do(() => {}, .25) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
@@ -952,7 +837,6 @@ expect(route.score).to.eql(.1); | ||
p.ifGet( | ||
barIfFoo, | ||
value => p.do(throwErr), | ||
route => p.do(() => {}, .5) | ||
() => undefined, | ||
p.do(throwErr), | ||
p.do(() => {}, .5) | ||
) | ||
(notFoo) | ||
.subscribe(route => { | ||
@@ -962,56 +846,22 @@ expect(route.score).to.eql(.5); | ||
}); | ||
}); | ||
describe("p.predicateToMatcher", () => { | ||
it("should pass through true", (done) => { | ||
p.predicateToMatcher(m => true) | ||
(foo) | ||
.subscribe(response => { | ||
expect(response).to.be.true; | ||
it("should pass supplied argument all the way through", (done) => { | ||
let routed; | ||
p.route$( | ||
greeting => p.ifGet( | ||
() => greeting, | ||
p.do(match => { routed = match.value }) | ||
), | ||
"hey" | ||
) | ||
.subscribe(_ => { | ||
expect(routed).to.eql("hey"); | ||
}, passErr, done); | ||
}); | ||
it("should pass through true", (done) => { | ||
p.predicateToMatcher(m => false) | ||
(foo) | ||
.subscribe(response => { | ||
expect(response).to.be.false; | ||
}, passErr, done); | ||
}); | ||
it("should throw on object", (done) => { | ||
p.predicateToMatcher(m => ({ dog: "reason"})) | ||
(foo) | ||
.subscribe(throwErr, error => done(), throwErr); | ||
}); | ||
it("should throw on number", (done) => { | ||
p.predicateToMatcher(m => 15) | ||
(foo) | ||
.subscribe(throwErr, error => done(), throwErr); | ||
}); | ||
it("should pass through { value: true }", (done) => { | ||
p.predicateToMatcher(m => ({ value: true })) | ||
(foo) | ||
.subscribe(response => { | ||
expect(response.value).to.be.true; | ||
}, passErr, done); | ||
}); | ||
it("should treat { value: false } as false", (done) => { | ||
p.predicateToMatcher(m => ({ value: false })) | ||
(foo) | ||
.subscribe(response => { | ||
expect(response).to.be.false; | ||
}, passErr, done); | ||
}); | ||
}); | ||
describe('p.if', () => { | ||
it("should return false on false when 'else' router doesn't exist", (done) => | ||
p.route$(foo, p.if( | ||
m => false, | ||
it("should return NoRoute on false when 'else' router doesn't exist", (done) => | ||
p.route$($ => p.if( | ||
() => false, | ||
p.do(throwErr) | ||
@@ -1022,7 +872,7 @@ )) | ||
it("should return false on false when 'else' router doesn't route", (done) => | ||
p.route$(foo, p.if( | ||
m => false, | ||
it("should return NoRoute on false when 'else' router doesn't route", (done) => | ||
p.route$($ => p.if( | ||
() => false, | ||
p.do(throwErr), | ||
route => p.no() | ||
p.no() | ||
)) | ||
@@ -1032,5 +882,5 @@ .subscribe(t => expect(t).to.be.false, passErr, done) | ||
it("should return false on true when 'if' router doesn't route and 'else' router doesn't exist", (done) => | ||
p.route$(foo, p.if( | ||
m => true, | ||
it("should return NoRoute on true when 'if' router doesn't route and 'else' router doesn't exist", (done) => | ||
p.route$($ => p.if( | ||
() => true, | ||
p.no() | ||
@@ -1041,7 +891,7 @@ )) | ||
it("should return false on true when 'if' router doesn't route and 'else' router exists", (done) => | ||
p.route$(foo, p.if( | ||
m => true, | ||
it("should return NoRoute on true when 'if' router doesn't route and 'else' router exists", (done) => | ||
p.route$($ => p.if( | ||
() => true, | ||
p.no(), | ||
route => p.do(throwErr) | ||
p.do(throwErr) | ||
)) | ||
@@ -1054,5 +904,5 @@ .subscribe(t => expect(t).to.be.false, passErr, done) | ||
p.route$(foo, p.if( | ||
m => true, | ||
p.do(m => { | ||
p.route$($ => p.if( | ||
() => true, | ||
p.do(() => { | ||
routed = true; | ||
@@ -1069,8 +919,8 @@ }) | ||
p.route$(foo, p.if( | ||
m => true, | ||
p.do(m => { | ||
p.route$($ => p.if( | ||
() => true, | ||
p.do(() => { | ||
routed = true; | ||
}), | ||
route => p.do(throwErr) | ||
p.do(throwErr) | ||
)) | ||
@@ -1085,6 +935,6 @@ .subscribe(n => { | ||
p.route$(foo, p.if( | ||
m => false, | ||
p.route$($ => p.if( | ||
() => false, | ||
p.do(throwErr), | ||
route => p.do(m => { | ||
p.do(() => { | ||
routed = true; | ||
@@ -1100,6 +950,5 @@ }) | ||
p.if( | ||
m => true, | ||
p.do(m => {}) | ||
() => true, | ||
p.do(() => {}) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
@@ -1112,6 +961,5 @@ expect(route.score).to.eql(1); | ||
p.if( | ||
m => true, | ||
() => true, | ||
p.do(() => {}, 0.25) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
@@ -1124,7 +972,6 @@ expect(route.score).to.eql(.25); | ||
p.if( | ||
m => false, | ||
() => false, | ||
p.do(throwErr), | ||
route => p.do(m => {}) | ||
p.do(m => {}) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
@@ -1137,7 +984,6 @@ expect(route.score).to.eql(1); | ||
p.if( | ||
m => false, | ||
() => false, | ||
p.do(throwErr), | ||
route => p.do(_ => {}, .5) | ||
p.do(_ => {}, .5) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
@@ -1150,9 +996,6 @@ expect(route.score).to.eql(.5); | ||
p.if( | ||
m => 'foo', | ||
() => 'foo', | ||
p.do(throwErr) | ||
) | ||
(foo) | ||
.subscribe(throwErr, error => { | ||
done(); | ||
}, throwErr); | ||
.subscribe(throwErr, error => done(), throwErr); | ||
}); | ||
@@ -1162,9 +1005,6 @@ | ||
p.if( | ||
m => ({ foo: "foo" }), | ||
() => ({ foo: "foo" }), | ||
p.do(throwErr) | ||
) | ||
(foo) | ||
.subscribe(throwErr, error => { | ||
done(); | ||
}, throwErr); | ||
.subscribe(throwErr, error => done(), throwErr); | ||
}); | ||
@@ -1174,6 +1014,5 @@ | ||
p.if( | ||
m => false, | ||
() => false, | ||
p.do(throwErr) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
@@ -1187,11 +1026,10 @@ expect(route.reason).to.eql("none"); | ||
p.if( | ||
m => ({ reason: 'whatevs' }), | ||
p.no('whatevs'), | ||
p.do(throwErr), | ||
route => p.do(m => { | ||
routed = route.reason; | ||
p.do(no => { | ||
routed = no.reason; | ||
}) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
expect(route.type === 'do'); | ||
expect(route instanceof p.DoRoute).to.be.true; | ||
route.action(); | ||
@@ -1204,8 +1042,7 @@ expect(routed).to.eql("whatevs"); | ||
p.if( | ||
m => ({ reason: 'whatevs' }), | ||
p.no('whatevs'), | ||
p.do(throwErr) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
expect(route.type).to.eql('no'); | ||
expect(route instanceof p.NoRoute).to.be.true; | ||
expect(route.reason).to.eql("whatevs"); | ||
@@ -1219,6 +1056,5 @@ }, passErr, done); | ||
p.if( | ||
m => ({ value: true, score: .5 }), | ||
p.match(true, .5), | ||
p.do(m => { handled = true; }) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
@@ -1235,8 +1071,7 @@ route.action(); | ||
p.if( | ||
m => ({ value: false }), | ||
p.match(false), | ||
p.do(throwErr) | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
expect(route.type).to.eql('no') | ||
expect(route instanceof p.NoRoute).to.be.true; | ||
}, passErr, done); | ||
@@ -1247,8 +1082,7 @@ }); | ||
p.if( | ||
c => true, | ||
undefined | ||
() => true, | ||
() => undefined | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
expect(route.type).to.eql('no') | ||
expect(route instanceof p.NoRoute).to.be.true; | ||
}, passErr, done); | ||
@@ -1259,37 +1093,35 @@ }); | ||
p.if( | ||
c => false, | ||
() => false, | ||
throwErr, | ||
route => undefined | ||
() => undefined | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
expect(route.type).to.eql('no') | ||
expect(route instanceof p.NoRoute).to.be.true; | ||
}, passErr, done); | ||
}); | ||
}); | ||
describe("p.before", () => { | ||
it("should return false with NoRoute", (done) => { | ||
p.route$(foo, p.before( | ||
throwErr, | ||
p.no() | ||
)) | ||
.subscribe(t => expect(t).to.be.false, passErr, done); | ||
it("should pass through NoRoute", (done) => { | ||
p.route$($ => p.before( | ||
p.no(), | ||
throwErr | ||
)).subscribe(t => { | ||
expect(t).to.be.false; | ||
}, passErr, done); | ||
}); | ||
it("should run 'before' handler and then router's action", (done) => { | ||
it("should run 'before' action and then router's action", (done) => { | ||
let handled = false; | ||
let routed = false; | ||
p.route$(foo, p.before( | ||
p.route$($ => p.before( | ||
p.do(() => { | ||
expect(handled).to.be.true; | ||
routed = true; | ||
}), | ||
m => { | ||
expect(routed).to.be.false; | ||
handled = true; | ||
}, | ||
p.do(m => { | ||
expect(handled).to.be.true; | ||
routed = true; | ||
}) | ||
} | ||
)) | ||
@@ -1303,7 +1135,7 @@ .subscribe(t => { | ||
describe("p.before", () => { | ||
describe("p.after", () => { | ||
it("should return false with NoRoute", (done) => { | ||
p.route$(foo, p.after( | ||
throwErr, | ||
p.no() | ||
p.route$($ => p.after( | ||
p.no(), | ||
throwErr | ||
)) | ||
@@ -1318,11 +1150,11 @@ .subscribe(t => expect(t).to.be.false, passErr, done); | ||
p.route$(foo, p.after( | ||
m => { | ||
p.route$($ => p.after( | ||
p.do(() => { | ||
expect(handled).to.be.false; | ||
routed = true; | ||
}), | ||
() => { | ||
expect(routed).to.be.true; | ||
handled = true; | ||
}, | ||
p.do(m => { | ||
expect(handled).to.be.false; | ||
routed = true; | ||
}) | ||
} | ||
)) | ||
@@ -1336,7 +1168,7 @@ .subscribe(t => { | ||
describe("p.default", () => { | ||
describe("p.ifNo", () => { | ||
it("should not be run when main router returns an action route", (done) => { | ||
let routed; | ||
p.route$(foo, p.default( | ||
p.route$($ => p.ifNo( | ||
p.do(m => { | ||
@@ -1355,5 +1187,5 @@ routed = true; | ||
p.route$(foo, p.default( | ||
p.route$($ => p.ifNo( | ||
p.no('reason'), | ||
route => p.do(m => { | ||
p.do(route => { | ||
handled = route.reason; | ||
@@ -1367,10 +1199,20 @@ }) | ||
it('should allow undefined result for getDefaultRouter', (done) =>{ | ||
p.default( | ||
it('should return NoRoute when both router and default router return NoRoute', (done) =>{ | ||
p.ifNo( | ||
p.no('reason'), | ||
p.no('another reason') | ||
) | ||
.subscribe(route => { | ||
expect(route instanceof p.NoRoute).to.be.true; | ||
expect(route.reason).to.eql('another reason'); | ||
}, passErr, done); | ||
}); | ||
it('should allow undefined result for default router', (done) =>{ | ||
p.ifNo( | ||
p.no('reason'), | ||
route => undefined | ||
) | ||
(foo) | ||
.subscribe(route => { | ||
expect(route.type).to.eql('no'); | ||
expect(route instanceof p.NoRoute).to.be.true; | ||
expect(route.reason).to.eql('none'); | ||
@@ -1383,4 +1225,4 @@ }, passErr, done); | ||
it("should pass through no route", (done) => | ||
p.route$(foo, p.do(c => | ||
p.route$(c, p.no()) | ||
p.route$(p.do(() => | ||
p.route$(p.no()) | ||
)) | ||
@@ -1393,4 +1235,4 @@ .subscribe(t => expect(t).to.be.true, passErr, done) | ||
p.route$(foo, p.do(c => | ||
p.route$(c, p.do(c => { | ||
p.route$(p.do(() => | ||
p.route$(p.do(() => { | ||
handled = true; | ||
@@ -1408,7 +1250,5 @@ })) | ||
it("doesn't route on undefined key", done => { | ||
p.route$(foo, p.switch( | ||
c => undefined, { | ||
foo: p.do(throwErr) | ||
} | ||
)) | ||
p.route$($ => p.switch(() => undefined, { | ||
foo: p.do(throwErr) | ||
})) | ||
.subscribe(t => { | ||
@@ -1420,7 +1260,5 @@ expect(t).to.be.false; | ||
it("doesn't route on null key", done => { | ||
p.route$(foo, p.switch( | ||
c => undefined, { | ||
foo: p.do(throwErr) | ||
} | ||
)) | ||
p.route$($ => p.switch(() => null, { | ||
foo: p.do(throwErr) | ||
})) | ||
.subscribe(t => { | ||
@@ -1432,7 +1270,5 @@ expect(t).to.be.false; | ||
it("doesn't route on non-matching key", done => { | ||
p.route$(foo, p.switch( | ||
c => 'bar', { | ||
foo: p.do(throwErr) | ||
} | ||
)) | ||
p.route$($ => p.switch(() => 'bar', { | ||
foo: p.do(throwErr) | ||
})) | ||
.subscribe(t => { | ||
@@ -1445,9 +1281,7 @@ expect(t).to.be.false; | ||
let routed = false; | ||
p.route$(foo, p.switch( | ||
c => 'foo', { | ||
foo: p.do(c => { | ||
routed = true; | ||
}), | ||
} | ||
)) | ||
p.route$($ => p.switch(() => 'foo', { | ||
foo: p.do(() => { | ||
routed = true; | ||
}), | ||
})) | ||
.subscribe(t => { | ||
@@ -1461,10 +1295,8 @@ expect(t).to.be.true; | ||
let routed = false; | ||
p.route$(foo, p.switch( | ||
c => 'foo', { | ||
foo: p.do(c => { | ||
routed = true; | ||
}), | ||
bar: p.do(throwErr) | ||
} | ||
)) | ||
p.route$($ => p.switch(() => 'foo', { | ||
foo: p.do(() => { | ||
routed = true; | ||
}), | ||
bar: p.do(throwErr) | ||
})) | ||
.subscribe(t => { | ||
@@ -1478,10 +1310,8 @@ expect(t).to.be.true; | ||
let routed = false; | ||
p.route$(foo, p.switch( | ||
c => 'foo', { | ||
bar: p.do(throwErr), | ||
foo: p.do(c => { | ||
routed = true; | ||
}) | ||
} | ||
)) | ||
p.route$($ => p.switch(() => 'foo', { | ||
bar: p.do(throwErr), | ||
foo: p.do(() => { | ||
routed = true; | ||
}) | ||
})) | ||
.subscribe(t => { | ||
@@ -1494,7 +1324,5 @@ expect(t).to.be.true; | ||
it("doesn't route when router for key doesn't route", done => { | ||
p.route$(foo, p.switch( | ||
c => 'foo', { | ||
foo: p.no() | ||
} | ||
)) | ||
p.route$($ => p.switch(() => 'foo', { | ||
foo: p.no() | ||
})) | ||
.subscribe(t => { | ||
@@ -1504,21 +1332,2 @@ expect(t).to.be.false; | ||
}); | ||
it("conditionally routes", done => { | ||
let routed; | ||
p.route$(foo, p.switch( | ||
c => 'foo', { | ||
foo: p.if( | ||
c => c.foo === 'foo', | ||
p.do(c => { | ||
routed = true; | ||
}), | ||
reason => p.do(throwErr) | ||
) | ||
} | ||
)) | ||
.subscribe(t => { | ||
expect(t).to.be.true; | ||
expect(routed).to.be.true; | ||
}, passErr, done); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
109676
1974