boring-router
Advanced tools
Comparing version 0.3.0-alpha.5 to 0.3.0-alpha.6
@@ -0,2 +1,4 @@ | ||
import { Location } from 'history'; | ||
export declare function then(handler: () => void): void; | ||
export declare function isPathPrefix(path: string, prefix: string): boolean; | ||
export declare function isLocationEqual(left: Location, right: Location): boolean; |
@@ -14,2 +14,7 @@ "use strict"; | ||
exports.isPathPrefix = isPathPrefix; | ||
function isLocationEqual(left, right) { | ||
let keys = ['pathname', 'search', 'hash']; | ||
return keys.every(key => left[key] === right[key]); | ||
} | ||
exports.isLocationEqual = isLocationEqual; | ||
//# sourceMappingURL=@utils.js.map |
@@ -9,3 +9,3 @@ import { History } from 'history'; | ||
*/ | ||
export declare type RouteMatchBeforeEnter<TRouteMatch extends RouteMatch = RouteMatch> = (next: OmitValueOfKey<TRouteMatch, Exclude<keyof RouteMatch, keyof MatchingRouteMatch>>) => string | boolean | void; | ||
export declare type RouteMatchBeforeEnter<TRouteMatch extends RouteMatch = RouteMatch> = (next: OmitValueOfKey<TRouteMatch, Exclude<keyof RouteMatch, keyof MatchingRouteMatch>>) => Promise<string | boolean | void> | string | boolean | void; | ||
/** | ||
@@ -16,6 +16,6 @@ * Route match before leave callback. | ||
*/ | ||
export declare type RouteMatchBeforeLeave = () => boolean | void; | ||
export declare type RouteMatchAfterEnter = () => void; | ||
export declare type RouteMatchAfterLeave = () => void; | ||
export declare type RouteMatchServiceFactory<TRouteMatch extends RouteMatch> = (match: TRouteMatch) => IRouteService<TRouteMatch>; | ||
export declare type RouteMatchBeforeLeave = () => Promise<boolean | void> | boolean | void; | ||
export declare type RouteMatchAfterEnter = () => Promise<void> | void; | ||
export declare type RouteMatchAfterLeave = () => Promise<void> | void; | ||
export declare type RouteMatchServiceFactory<TRouteMatch extends RouteMatch> = (match: TRouteMatch) => IRouteService<TRouteMatch> | Promise<IRouteService<TRouteMatch>>; | ||
export interface IRouteService<TRouteMatch extends RouteMatch = RouteMatch> { | ||
@@ -22,0 +22,0 @@ beforeEnter?: RouteMatchBeforeEnter<TRouteMatch>; |
@@ -189,6 +189,6 @@ "use strict"; | ||
$service(factory) { | ||
if (this._service) { | ||
if (this._serviceFactory) { | ||
throw new Error(`Service has already been defined for "${this.$name}"`); | ||
} | ||
this._service = factory(this); | ||
this._serviceFactory = factory; | ||
return this; | ||
@@ -251,48 +251,70 @@ } | ||
_beforeLeave() { | ||
for (let callback of this._beforeLeaveCallbacks) { | ||
let result = callback(); | ||
return tslib_1.__awaiter(this, void 0, void 0, function* () { | ||
for (let callback of this._beforeLeaveCallbacks) { | ||
let result = callback(); | ||
if (result === false) { | ||
return false; | ||
} | ||
} | ||
let service = yield this._getService(); | ||
if (!service || !service.beforeLeave) { | ||
return true; | ||
} | ||
let result = service.beforeLeave(); | ||
if (result === false) { | ||
return false; | ||
} | ||
} | ||
let service = this._service; | ||
if (service && service.beforeLeave) { | ||
service.beforeLeave(); | ||
} | ||
return true; | ||
return true; | ||
}); | ||
} | ||
/** @internal */ | ||
_beforeEnter() { | ||
let next = this._matching; | ||
for (let callback of this._beforeEnterCallbacks) { | ||
let result = callback(next); | ||
return tslib_1.__awaiter(this, void 0, void 0, function* () { | ||
let next = this._matching; | ||
for (let callback of this._beforeEnterCallbacks) { | ||
let result = yield callback(next); | ||
if (typeof result === 'string' || result === false) { | ||
return result; | ||
} | ||
} | ||
let service = yield this._getService(); | ||
if (!service || !service.beforeEnter) { | ||
return true; | ||
} | ||
let result = yield service.beforeEnter(next); | ||
if (typeof result === 'string' || result === false) { | ||
return result; | ||
} | ||
} | ||
let service = this._service; | ||
if (service && service.beforeEnter) { | ||
service.beforeEnter(next); | ||
} | ||
return true; | ||
return true; | ||
}); | ||
} | ||
/** @internal */ | ||
_afterLeave() { | ||
for (let callback of this._afterLeaveCallbacks) { | ||
callback(); | ||
} | ||
let service = this._service; | ||
if (service && service.afterLeave) { | ||
service.afterLeave(); | ||
} | ||
return tslib_1.__awaiter(this, void 0, void 0, function* () { | ||
for (let callback of this._afterLeaveCallbacks) { | ||
yield callback(); | ||
} | ||
let service = yield this._getService(); | ||
if (!service) { | ||
return; | ||
} | ||
if (service.afterLeave) { | ||
yield service.afterLeave(); | ||
} | ||
}); | ||
} | ||
/** @internal */ | ||
_afterEnter() { | ||
for (let callback of this._afterEnterCallbacks) { | ||
callback(); | ||
} | ||
let service = this._service; | ||
if (service && service.afterEnter) { | ||
service.afterEnter(); | ||
} | ||
return tslib_1.__awaiter(this, void 0, void 0, function* () { | ||
for (let callback of this._afterEnterCallbacks) { | ||
yield callback(); | ||
} | ||
let service = yield this._getService(); | ||
if (!service) { | ||
return; | ||
} | ||
if (service.afterEnter) { | ||
yield service.afterEnter(); | ||
} | ||
}); | ||
} | ||
@@ -308,2 +330,24 @@ /** @internal */ | ||
} | ||
/** @internal */ | ||
_getService() { | ||
return tslib_1.__awaiter(this, void 0, void 0, function* () { | ||
let instanceOrPromise = this._serviceInstanceOrPromise; | ||
if (instanceOrPromise) { | ||
return instanceOrPromise; | ||
} | ||
let factory = this._serviceFactory; | ||
if (!factory) { | ||
return undefined; | ||
} | ||
let result = (this._serviceInstanceOrPromise = factory(this)); | ||
if (result instanceof Promise) { | ||
result | ||
.then(service => { | ||
this._serviceInstanceOrPromise = service; | ||
}) | ||
.catch(console.error); | ||
} | ||
return result; | ||
}); | ||
} | ||
} | ||
@@ -310,0 +354,0 @@ RouteMatch.fragment = /[^/]+/; |
@@ -23,6 +23,15 @@ "use strict"; | ||
/** @internal */ | ||
this._onLocationChange = ({ pathname, search }, action) => { | ||
this._changing = Promise.resolve(); | ||
/** @internal */ | ||
this._onLocationChange = (location) => { | ||
this._changing = this._changing | ||
.then(() => this._asyncOnLocationChange(location)) | ||
.catch(console.error); | ||
}; | ||
/** @internal */ | ||
this._asyncOnLocationChange = (nextLocation) => tslib_1.__awaiter(this, void 0, void 0, function* () { | ||
let { pathname, search } = nextLocation; | ||
let history = this._history; | ||
let location = history.location; | ||
if (history_1.locationsAreEqual(this._location, location)) { | ||
let location = this._location; | ||
if (location && _utils_1.isLocationEqual(location, nextLocation)) { | ||
return; | ||
@@ -48,2 +57,3 @@ } | ||
} | ||
let reversedLeavingMatches = Array.from(leavingMatchSet).reverse(); | ||
let enteringMatchSet = new Set(nextMatchSet); | ||
@@ -54,6 +64,6 @@ for (let match of previousMatchSet) { | ||
// Process before hooks | ||
for (let match of Array.from(leavingMatchSet).reverse()) { | ||
let result = match._beforeLeave(); | ||
for (let match of reversedLeavingMatches) { | ||
let result = yield match._beforeLeave(); | ||
if (!result) { | ||
this._revert(action); | ||
this._revert(); | ||
return; | ||
@@ -63,3 +73,3 @@ } | ||
for (let match of enteringMatchSet) { | ||
let result = match._beforeEnter(); | ||
let result = yield match._beforeEnter(); | ||
if (typeof result === 'string') { | ||
@@ -70,10 +80,10 @@ history.replace(result); | ||
if (!result) { | ||
this._revert(action); | ||
this._revert(); | ||
return; | ||
} | ||
} | ||
this._location = location; | ||
this._location = nextLocation; | ||
Object.assign(this._source, this._matchingSource); | ||
// Update | ||
for (let match of leavingMatchSet) { | ||
for (let match of reversedLeavingMatches) { | ||
match._update(false, false); | ||
@@ -86,11 +96,11 @@ } | ||
// Process after hooks | ||
for (let match of leavingMatchSet) { | ||
match._afterLeave(); | ||
for (let match of reversedLeavingMatches) { | ||
yield match._afterLeave(); | ||
} | ||
for (let match of enteringMatchSet) { | ||
match._afterEnter(); | ||
yield match._afterEnter(); | ||
} | ||
}; | ||
}); | ||
this._history = history; | ||
this._location = history_1.parsePath(defaultPath); | ||
this._default = history_1.parsePath(defaultPath); | ||
this._fragmentMatcher = | ||
@@ -101,17 +111,7 @@ fragmentMatcher || DEFAULT_FRAGMENT_MATCHER_CALLBACK; | ||
history.listen(this._onLocationChange); | ||
this._onLocationChange(history.location, 'POP'); | ||
this._onLocationChange(history.location); | ||
}); | ||
} | ||
_revert(action) { | ||
let history = this._history; | ||
let location = this._location; | ||
switch (action) { | ||
case 'PUSH': | ||
history.goBack(); | ||
break; | ||
case 'POP': | ||
case 'REPLACE': | ||
history.replace(location); | ||
break; | ||
} | ||
_revert() { | ||
this._history.replace(this._location || this._default); | ||
} | ||
@@ -118,0 +118,0 @@ /** @internal */ |
{ | ||
"name": "boring-router", | ||
"version": "0.3.0-alpha.5", | ||
"version": "0.3.0-alpha.6", | ||
"description": "A light-weight, type-safe, yet reactive router service using MobX.", | ||
@@ -49,3 +49,2 @@ "repository": { | ||
"ts-jest": "^23.1.4", | ||
"tslib": "^1.9.3", | ||
"tslint": "^5.11.0", | ||
@@ -58,4 +57,5 @@ "tslint-language-service": "^0.9.9", | ||
"hyphenate": "^0.2.4", | ||
"tslang": "^0.1.9" | ||
"tslang": "^0.1.9", | ||
"tslib": "^1.9.3" | ||
} | ||
} |
@@ -94,4 +94,7 @@ [](https://www.npmjs.com/package/boring-router) | ||
interface RouteMatch<TParamDict> { | ||
$name: string; | ||
$matched: boolean; | ||
$exact: boolean; | ||
$params: TParamDict; | ||
@@ -102,6 +105,31 @@ | ||
$replace(params?: Partial<TParamDict>, preserveQuery?: boolean): void; | ||
$react(reaction: RouteMatchReaction, exact?: boolean): void; | ||
$beforeEnter(callback: RouteMatchBeforeEnter<this>): this; | ||
$beforeLeave(callback: RouteMatchBeforeLeave): this; | ||
$afterEnter(callback: RouteMatchAfterEnter): this; | ||
$afterLeave(callback: RouteMatchAfterLeave): this; | ||
$service(factory: RouteMatchServiceFactory<this>): this; | ||
static fragment: RegExp; | ||
static rest: RegExp; | ||
} | ||
``` | ||
Within `$beforeEnter` hook and service hook, a special version of `RouteMatch` is available as `MatchingRouteMatch`, providing restricted functionality: | ||
```ts | ||
interface MatchingRouteMatch<TParamDict> { | ||
$name: string; | ||
$exact: boolean; | ||
$params: TParamDict; | ||
$ref(params?: Partial<TParamDict>, preserveQuery?: boolean): string; | ||
$push(params?: Partial<TParamDict>, preserveQuery?: boolean): void; | ||
$replace(params?: Partial<TParamDict>, preserveQuery?: boolean): void; | ||
} | ||
``` | ||
## Examples | ||
@@ -108,0 +136,0 @@ |
46955
18
935
281
8
+ Addedtslib@^1.9.3
+ Addedtslib@1.14.1(transitive)