Comparing version 6.2.6 to 7.0.0
@@ -1,2 +0,1 @@ | ||
//# sourceMappingURL=core.js.map | ||
"use strict"; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,69 +6,69 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
var _router = require('./router'); | ||
Object.defineProperty(exports, 'default', { | ||
Object.defineProperty(exports, "default", { | ||
enumerable: true, | ||
get: function get() { | ||
return _interopRequireDefault(_router).default; | ||
get: function () { | ||
return _router.default; | ||
} | ||
}); | ||
var _transition = require('./transition'); | ||
Object.defineProperty(exports, 'InternalTransition', { | ||
Object.defineProperty(exports, "InternalTransition", { | ||
enumerable: true, | ||
get: function get() { | ||
return _interopRequireDefault(_transition).default; | ||
get: function () { | ||
return _transition.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'logAbort', { | ||
Object.defineProperty(exports, "logAbort", { | ||
enumerable: true, | ||
get: function get() { | ||
get: function () { | ||
return _transition.logAbort; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'STATE_SYMBOL', { | ||
Object.defineProperty(exports, "STATE_SYMBOL", { | ||
enumerable: true, | ||
get: function get() { | ||
get: function () { | ||
return _transition.STATE_SYMBOL; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'PARAMS_SYMBOL', { | ||
Object.defineProperty(exports, "PARAMS_SYMBOL", { | ||
enumerable: true, | ||
get: function get() { | ||
get: function () { | ||
return _transition.PARAMS_SYMBOL; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'QUERY_PARAMS_SYMBOL', { | ||
Object.defineProperty(exports, "QUERY_PARAMS_SYMBOL", { | ||
enumerable: true, | ||
get: function get() { | ||
get: function () { | ||
return _transition.QUERY_PARAMS_SYMBOL; | ||
} | ||
}); | ||
var _transitionState = require('./transition-state'); | ||
Object.defineProperty(exports, 'TransitionState', { | ||
Object.defineProperty(exports, "TransitionState", { | ||
enumerable: true, | ||
get: function get() { | ||
return _interopRequireDefault(_transitionState).default; | ||
get: function () { | ||
return _transitionState.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'TransitionError', { | ||
Object.defineProperty(exports, "TransitionError", { | ||
enumerable: true, | ||
get: function get() { | ||
get: function () { | ||
return _transitionState.TransitionError; | ||
} | ||
}); | ||
var _routeInfo = require('./route-info'); | ||
Object.defineProperty(exports, 'InternalRouteInfo', { | ||
Object.defineProperty(exports, "InternalRouteInfo", { | ||
enumerable: true, | ||
get: function get() { | ||
return _interopRequireDefault(_routeInfo).default; | ||
get: function () { | ||
return _routeInfo.default; | ||
} | ||
}); | ||
var _router = _interopRequireDefault(require("./router")); | ||
var _transition = _interopRequireWildcard(require("./transition")); | ||
var _transitionState = _interopRequireWildcard(require("./transition-state")); | ||
var _routeInfo = _interopRequireDefault(require("./route-info")); | ||
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } |
@@ -16,6 +16,6 @@ import { Promise } from 'rsvp'; | ||
deserialize?(params: Dict<unknown>, transition: Transition): Dict<unknown>; | ||
serialize?(model: {}, params: string[]): {} | undefined; | ||
serialize?(model: {}, params: string[]): Dict<unknown> | undefined; | ||
beforeModel?(transition: Transition): Promise<any> | any; | ||
afterModel?(resolvedModel: any, transition: Transition): Promise<any> | any; | ||
setup?(context: Dict<unknown>, transition: Transition): void; | ||
setup?(context: Dict<unknown> | PromiseLike<Dict<unknown> | null | undefined>, transition: Transition): void; | ||
enter?(transition: Transition): void; | ||
@@ -52,12 +52,14 @@ exit?(transition?: Transition): void; | ||
queryParams?: Dict<unknown>; | ||
context?: Dict<unknown>; | ||
context?: Dict<unknown> | PromiseLike<Dict<unknown> | null | undefined> | null; | ||
isResolved: boolean; | ||
constructor(router: Router<T>, name: string, paramNames: string[], route?: T); | ||
getModel(_transition: InternalTransition<T>): Promise<Dict<unknown> | undefined>; | ||
serialize(_context?: Dict<unknown>): Dict<unknown>; | ||
getModel(_transition: InternalTransition<T>): Promise<Dict<unknown> | null | undefined>; | ||
serialize(_context?: Dict<unknown>): Dict<unknown> | undefined; | ||
resolve(shouldContinue: Continuation, transition: InternalTransition<T>): Promise<ResolvedRouteInfo<T>>; | ||
becomeResolved(transition: InternalTransition<T> | null, resolvedContext: Dict<unknown>): ResolvedRouteInfo<T>; | ||
shouldSupercede(routeInfo?: InternalRouteInfo<T>): boolean; | ||
route: T | undefined; | ||
routePromise: Promise<T>; | ||
get route(): T | undefined; | ||
set route(route: T | undefined); | ||
get routePromise(): Promise<T>; | ||
set routePromise(routePromise: Promise<T>); | ||
protected log(transition: InternalTransition<T>, message: string): void; | ||
@@ -80,8 +82,8 @@ private updateRoute; | ||
constructor(router: Router<T>, name: string, paramNames: string[], params: Dict<unknown>, route?: T); | ||
getModel(transition: InternalTransition<T>): Promise<Dict<unknown> | undefined>; | ||
getModel(transition: InternalTransition<T>): Promise<Dict<unknown> | null | undefined>; | ||
} | ||
export declare class UnresolvedRouteInfoByObject<T extends Route> extends InternalRouteInfo<T> { | ||
serializer?: SerializerFunc; | ||
constructor(router: Router<T>, name: string, paramNames: string[], context: Dict<unknown>); | ||
getModel(transition: InternalTransition<T>): Promise<Dict<unknown> | undefined>; | ||
constructor(router: Router<T>, name: string, paramNames: string[], context: Dict<unknown> | PromiseLike<Dict<unknown>>); | ||
getModel(transition: InternalTransition<T>): Promise<Dict<unknown> | null | undefined>; | ||
/** | ||
@@ -96,4 +98,4 @@ @private | ||
*/ | ||
serialize(model?: IModel): any; | ||
serialize(model?: IModel): Dict<unknown> | undefined; | ||
} | ||
export {}; |
@@ -1,494 +0,485 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.UnresolvedRouteInfoByObject = exports.UnresolvedRouteInfoByParam = exports.ResolvedRouteInfo = undefined; | ||
exports.toReadOnlyRouteInfo = toReadOnlyRouteInfo; | ||
exports.UnresolvedRouteInfoByObject = exports.UnresolvedRouteInfoByParam = exports.ResolvedRouteInfo = exports.default = void 0; | ||
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; | ||
var _rsvp = require("rsvp"); | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _transition2 = require("./transition"); | ||
exports.toReadOnlyRouteInfo = toReadOnlyRouteInfo; | ||
var _utils = require("./utils"); | ||
var _rsvp = require('rsvp'); | ||
let ROUTE_INFOS = new WeakMap(); | ||
var _transition2 = require('./transition'); | ||
function toReadOnlyRouteInfo(routeInfos, queryParams = {}, includeAttributes = false) { | ||
return routeInfos.map((info, i) => { | ||
let { | ||
name, | ||
params, | ||
paramNames, | ||
context, | ||
route | ||
} = info; | ||
var _utils = require('./utils'); | ||
if (ROUTE_INFOS.has(info) && includeAttributes) { | ||
let routeInfo = ROUTE_INFOS.get(info); | ||
routeInfo = attachMetadata(route, routeInfo); | ||
let routeInfoWithAttribute = createRouteInfoWithAttributes(routeInfo, context); | ||
ROUTE_INFOS.set(info, routeInfoWithAttribute); | ||
return routeInfoWithAttribute; | ||
} | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
let routeInfo = { | ||
find(predicate, thisArg) { | ||
let publicInfo; | ||
let arr = []; | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
if (predicate.length === 3) { | ||
arr = routeInfos.map(info => ROUTE_INFOS.get(info)); | ||
} | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
for (let i = 0; routeInfos.length > i; i++) { | ||
publicInfo = ROUTE_INFOS.get(routeInfos[i]); | ||
var ROUTE_INFOS = new WeakMap(); | ||
function toReadOnlyRouteInfo(routeInfos) { | ||
var queryParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var includeAttributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | ||
if (predicate.call(thisArg, publicInfo, i, arr)) { | ||
return publicInfo; | ||
} | ||
} | ||
return routeInfos.map(function (info, i) { | ||
var name = info.name, | ||
params = info.params, | ||
paramNames = info.paramNames, | ||
context = info.context, | ||
route = info.route; | ||
return undefined; | ||
}, | ||
if (ROUTE_INFOS.has(info) && includeAttributes) { | ||
var _routeInfo = ROUTE_INFOS.get(info); | ||
_routeInfo = attachMetadata(route, _routeInfo); | ||
var routeInfoWithAttribute = createRouteInfoWithAttributes(_routeInfo, context); | ||
ROUTE_INFOS.set(info, routeInfoWithAttribute); | ||
return routeInfoWithAttribute; | ||
get name() { | ||
return name; | ||
}, | ||
get paramNames() { | ||
return paramNames; | ||
}, | ||
get metadata() { | ||
return buildRouteInfoMetadata(info.route); | ||
}, | ||
get parent() { | ||
let parent = routeInfos[i - 1]; | ||
if (parent === undefined) { | ||
return null; | ||
} | ||
var routeInfo = { | ||
find(predicate, thisArg) { | ||
var publicInfo = void 0; | ||
var arr = []; | ||
if (predicate.length === 3) { | ||
arr = routeInfos.map(function (info) { | ||
return ROUTE_INFOS.get(info); | ||
}); | ||
} | ||
for (var _i = 0; routeInfos.length > _i; _i++) { | ||
publicInfo = ROUTE_INFOS.get(routeInfos[_i]); | ||
if (predicate.call(thisArg, publicInfo, _i, arr)) { | ||
return publicInfo; | ||
} | ||
} | ||
return undefined; | ||
}, | ||
get name() { | ||
return name; | ||
}, | ||
get paramNames() { | ||
return paramNames; | ||
}, | ||
get metadata() { | ||
return buildRouteInfoMetadata(info.route); | ||
}, | ||
get parent() { | ||
var parent = routeInfos[i - 1]; | ||
if (parent === undefined) { | ||
return null; | ||
} | ||
return ROUTE_INFOS.get(parent); | ||
}, | ||
get child() { | ||
var child = routeInfos[i + 1]; | ||
if (child === undefined) { | ||
return null; | ||
} | ||
return ROUTE_INFOS.get(child); | ||
}, | ||
get localName() { | ||
var parts = this.name.split('.'); | ||
return parts[parts.length - 1]; | ||
}, | ||
get params() { | ||
return params; | ||
}, | ||
get queryParams() { | ||
return queryParams; | ||
} | ||
}; | ||
if (includeAttributes) { | ||
routeInfo = createRouteInfoWithAttributes(routeInfo, context); | ||
return ROUTE_INFOS.get(parent); | ||
}, | ||
get child() { | ||
let child = routeInfos[i + 1]; | ||
if (child === undefined) { | ||
return null; | ||
} | ||
ROUTE_INFOS.set(info, routeInfo); | ||
return routeInfo; | ||
}); | ||
return ROUTE_INFOS.get(child); | ||
}, | ||
get localName() { | ||
let parts = this.name.split('.'); | ||
return parts[parts.length - 1]; | ||
}, | ||
get params() { | ||
return params; | ||
}, | ||
get queryParams() { | ||
return queryParams; | ||
} | ||
}; | ||
if (includeAttributes) { | ||
routeInfo = createRouteInfoWithAttributes(routeInfo, context); | ||
} | ||
ROUTE_INFOS.set(info, routeInfo); | ||
return routeInfo; | ||
}); | ||
} | ||
function createRouteInfoWithAttributes(routeInfo, context) { | ||
var attributes = { | ||
get attributes() { | ||
return context; | ||
} | ||
}; | ||
if (!Object.isExtensible(routeInfo) || routeInfo.hasOwnProperty('attributes')) { | ||
return Object.freeze(Object.assign({}, routeInfo, attributes)); | ||
let attributes = { | ||
get attributes() { | ||
return context; | ||
} | ||
return Object.assign(routeInfo, attributes); | ||
}; | ||
if (!Object.isExtensible(routeInfo) || routeInfo.hasOwnProperty('attributes')) { | ||
return Object.freeze(Object.assign({}, routeInfo, attributes)); | ||
} | ||
return Object.assign(routeInfo, attributes); | ||
} | ||
function buildRouteInfoMetadata(route) { | ||
if (route !== undefined && route !== null && route.buildRouteInfoMetadata !== undefined) { | ||
return route.buildRouteInfoMetadata(); | ||
} | ||
return null; | ||
if (route !== undefined && route !== null && route.buildRouteInfoMetadata !== undefined) { | ||
return route.buildRouteInfoMetadata(); | ||
} | ||
return null; | ||
} | ||
function attachMetadata(route, routeInfo) { | ||
var metadata = { | ||
get metadata() { | ||
return buildRouteInfoMetadata(route); | ||
} | ||
}; | ||
if (!Object.isExtensible(routeInfo) || routeInfo.hasOwnProperty('metadata')) { | ||
return Object.freeze(Object.assign({}, routeInfo, metadata)); | ||
let metadata = { | ||
get metadata() { | ||
return buildRouteInfoMetadata(route); | ||
} | ||
return Object.assign(routeInfo, metadata); | ||
}; | ||
if (!Object.isExtensible(routeInfo) || routeInfo.hasOwnProperty('metadata')) { | ||
return Object.freeze(Object.assign({}, routeInfo, metadata)); | ||
} | ||
return Object.assign(routeInfo, metadata); | ||
} | ||
var InternalRouteInfo = function () { | ||
function InternalRouteInfo(router, name, paramNames, route) { | ||
_classCallCheck(this, InternalRouteInfo); | ||
class InternalRouteInfo { | ||
constructor(router, name, paramNames, route) { | ||
this._routePromise = undefined; | ||
this._route = null; | ||
this.params = {}; | ||
this.isResolved = false; | ||
this.name = name; | ||
this.paramNames = paramNames; | ||
this.router = router; | ||
this._routePromise = undefined; | ||
this._route = null; | ||
this.params = {}; | ||
this.isResolved = false; | ||
this.name = name; | ||
this.paramNames = paramNames; | ||
this.router = router; | ||
if (route) { | ||
this._processRoute(route); | ||
} | ||
if (route) { | ||
this._processRoute(route); | ||
} | ||
} | ||
_createClass(InternalRouteInfo, [{ | ||
key: 'getModel', | ||
value: function getModel(_transition) { | ||
return _rsvp.Promise.resolve(this.context); | ||
} | ||
}, { | ||
key: 'serialize', | ||
value: function serialize(_context) { | ||
return this.params || {}; | ||
} | ||
}, { | ||
key: 'resolve', | ||
value: function resolve(shouldContinue, transition) { | ||
var _this = this; | ||
getModel(_transition) { | ||
return _rsvp.Promise.resolve(this.context); | ||
} | ||
return _rsvp.Promise.resolve(this.routePromise).then(function (route) { | ||
return _this.checkForAbort(shouldContinue, route); | ||
}).then(function () { | ||
return _this.runBeforeModelHook(transition); | ||
}).then(function () { | ||
return _this.checkForAbort(shouldContinue, null); | ||
}).then(function () { | ||
return _this.getModel(transition); | ||
}).then(function (resolvedModel) { | ||
return _this.checkForAbort(shouldContinue, resolvedModel); | ||
}).then(function (resolvedModel) { | ||
return _this.runAfterModelHook(transition, resolvedModel); | ||
}).then(function (resolvedModel) { | ||
return _this.becomeResolved(transition, resolvedModel); | ||
}); | ||
} | ||
}, { | ||
key: 'becomeResolved', | ||
value: function becomeResolved(transition, resolvedContext) { | ||
var params = this.serialize(resolvedContext); | ||
if (transition) { | ||
this.stashResolvedModel(transition, resolvedContext); | ||
transition[_transition2.PARAMS_SYMBOL] = transition[_transition2.PARAMS_SYMBOL] || {}; | ||
transition[_transition2.PARAMS_SYMBOL][this.name] = params; | ||
} | ||
var context = void 0; | ||
var contextsMatch = resolvedContext === this.context; | ||
if ('context' in this || !contextsMatch) { | ||
context = resolvedContext; | ||
} | ||
var cached = ROUTE_INFOS.get(this); | ||
var resolved = new ResolvedRouteInfo(this.router, this.name, this.paramNames, params, this.route, context); | ||
if (cached !== undefined) { | ||
ROUTE_INFOS.set(resolved, cached); | ||
} | ||
return resolved; | ||
} | ||
}, { | ||
key: 'shouldSupercede', | ||
value: function shouldSupercede(routeInfo) { | ||
// Prefer this newer routeInfo over `other` if: | ||
// 1) The other one doesn't exist | ||
// 2) The names don't match | ||
// 3) This route has a context that doesn't match | ||
// the other one (or the other one doesn't have one). | ||
// 4) This route has parameters that don't match the other. | ||
if (!routeInfo) { | ||
return true; | ||
} | ||
var contextsMatch = routeInfo.context === this.context; | ||
return routeInfo.name !== this.name || 'context' in this && !contextsMatch || this.hasOwnProperty('params') && !paramsMatch(this.params, routeInfo.params); | ||
} | ||
}, { | ||
key: 'log', | ||
value: function log(transition, message) { | ||
if (transition.log) { | ||
transition.log(this.name + ': ' + message); | ||
} | ||
} | ||
}, { | ||
key: 'updateRoute', | ||
value: function updateRoute(route) { | ||
route._internalName = this.name; | ||
return this.route = route; | ||
} | ||
}, { | ||
key: 'runBeforeModelHook', | ||
value: function runBeforeModelHook(transition) { | ||
if (transition.trigger) { | ||
transition.trigger(true, 'willResolveModel', transition, this.route); | ||
} | ||
var result = void 0; | ||
if (this.route) { | ||
if (this.route.beforeModel !== undefined) { | ||
result = this.route.beforeModel(transition); | ||
} | ||
} | ||
if ((0, _transition2.isTransition)(result)) { | ||
result = null; | ||
} | ||
return _rsvp.Promise.resolve(result); | ||
} | ||
}, { | ||
key: 'runAfterModelHook', | ||
value: function runAfterModelHook(transition, resolvedModel) { | ||
// Stash the resolved model on the payload. | ||
// This makes it possible for users to swap out | ||
// the resolved model in afterModel. | ||
var name = this.name; | ||
this.stashResolvedModel(transition, resolvedModel); | ||
var result = void 0; | ||
if (this.route !== undefined) { | ||
if (this.route.afterModel !== undefined) { | ||
result = this.route.afterModel(resolvedModel, transition); | ||
} | ||
} | ||
result = (0, _transition2.prepareResult)(result); | ||
return _rsvp.Promise.resolve(result).then(function () { | ||
// Ignore the fulfilled value returned from afterModel. | ||
// Return the value stashed in resolvedModels, which | ||
// might have been swapped out in afterModel. | ||
return transition.resolvedModels[name]; | ||
}); | ||
} | ||
}, { | ||
key: 'checkForAbort', | ||
value: function checkForAbort(shouldContinue, value) { | ||
return _rsvp.Promise.resolve(shouldContinue()).then(function () { | ||
// We don't care about shouldContinue's resolve value; | ||
// pass along the original value passed to this fn. | ||
return value; | ||
}, null); | ||
} | ||
}, { | ||
key: 'stashResolvedModel', | ||
value: function stashResolvedModel(transition, resolvedModel) { | ||
transition.resolvedModels = transition.resolvedModels || {}; | ||
transition.resolvedModels[this.name] = resolvedModel; | ||
} | ||
}, { | ||
key: 'fetchRoute', | ||
value: function fetchRoute() { | ||
var route = this.router.getRoute(this.name); | ||
return this._processRoute(route); | ||
} | ||
}, { | ||
key: '_processRoute', | ||
value: function _processRoute(route) { | ||
var _this2 = this; | ||
serialize(_context) { | ||
return this.params || {}; | ||
} | ||
// Setup a routePromise so that we can wait for asynchronously loaded routes | ||
this.routePromise = _rsvp.Promise.resolve(route); | ||
// Wait until the 'route' property has been updated when chaining to a route | ||
// that is a promise | ||
if ((0, _utils.isPromise)(route)) { | ||
this.routePromise = this.routePromise.then(function (r) { | ||
return _this2.updateRoute(r); | ||
}); | ||
// set to undefined to avoid recursive loop in the route getter | ||
return this.route = undefined; | ||
} else if (route) { | ||
return this.updateRoute(route); | ||
} | ||
return undefined; | ||
} | ||
}, { | ||
key: 'route', | ||
get: function get() { | ||
// _route could be set to either a route object or undefined, so we | ||
// compare against null to know when it's been set | ||
if (this._route !== null) { | ||
return this._route; | ||
} | ||
return this.fetchRoute(); | ||
}, | ||
set: function set(route) { | ||
this._route = route; | ||
} | ||
}, { | ||
key: 'routePromise', | ||
get: function get() { | ||
if (this._routePromise) { | ||
return this._routePromise; | ||
} | ||
this.fetchRoute(); | ||
return this._routePromise; | ||
}, | ||
set: function set(routePromise) { | ||
this._routePromise = routePromise; | ||
} | ||
}]); | ||
resolve(shouldContinue, transition) { | ||
return _rsvp.Promise.resolve(this.routePromise).then(route => this.checkForAbort(shouldContinue, route)).then(() => this.runBeforeModelHook(transition)).then(() => this.checkForAbort(shouldContinue, null)).then(() => this.getModel(transition)).then(resolvedModel => this.checkForAbort(shouldContinue, resolvedModel)).then(resolvedModel => this.runAfterModelHook(transition, resolvedModel)).then(resolvedModel => this.becomeResolved(transition, resolvedModel)); | ||
} | ||
return InternalRouteInfo; | ||
}(); | ||
becomeResolved(transition, resolvedContext) { | ||
let params = this.serialize(resolvedContext); | ||
exports.default = InternalRouteInfo; | ||
if (transition) { | ||
this.stashResolvedModel(transition, resolvedContext); | ||
transition[_transition2.PARAMS_SYMBOL] = transition[_transition2.PARAMS_SYMBOL] || {}; | ||
transition[_transition2.PARAMS_SYMBOL][this.name] = params; | ||
} | ||
var ResolvedRouteInfo = exports.ResolvedRouteInfo = function (_InternalRouteInfo) { | ||
_inherits(ResolvedRouteInfo, _InternalRouteInfo); | ||
let context; | ||
let contextsMatch = resolvedContext === this.context; | ||
function ResolvedRouteInfo(router, name, paramNames, params, route, context) { | ||
_classCallCheck(this, ResolvedRouteInfo); | ||
if ('context' in this || !contextsMatch) { | ||
context = resolvedContext; | ||
} | ||
var _this3 = _possibleConstructorReturn(this, (ResolvedRouteInfo.__proto__ || Object.getPrototypeOf(ResolvedRouteInfo)).call(this, router, name, paramNames, route)); | ||
let cached = ROUTE_INFOS.get(this); | ||
let resolved = new ResolvedRouteInfo(this.router, this.name, this.paramNames, params, this.route, context); | ||
_this3.params = params; | ||
_this3.isResolved = true; | ||
_this3.context = context; | ||
return _this3; | ||
if (cached !== undefined) { | ||
ROUTE_INFOS.set(resolved, cached); | ||
} | ||
_createClass(ResolvedRouteInfo, [{ | ||
key: 'resolve', | ||
value: function resolve(_shouldContinue, transition) { | ||
// A ResolvedRouteInfo just resolved with itself. | ||
if (transition && transition.resolvedModels) { | ||
transition.resolvedModels[this.name] = this.context; | ||
} | ||
return _rsvp.Promise.resolve(this); | ||
} | ||
}]); | ||
return resolved; | ||
} | ||
return ResolvedRouteInfo; | ||
}(InternalRouteInfo); | ||
shouldSupercede(routeInfo) { | ||
// Prefer this newer routeInfo over `other` if: | ||
// 1) The other one doesn't exist | ||
// 2) The names don't match | ||
// 3) This route has a context that doesn't match | ||
// the other one (or the other one doesn't have one). | ||
// 4) This route has parameters that don't match the other. | ||
if (!routeInfo) { | ||
return true; | ||
} | ||
var UnresolvedRouteInfoByParam = exports.UnresolvedRouteInfoByParam = function (_InternalRouteInfo2) { | ||
_inherits(UnresolvedRouteInfoByParam, _InternalRouteInfo2); | ||
let contextsMatch = routeInfo.context === this.context; | ||
return routeInfo.name !== this.name || 'context' in this && !contextsMatch || this.hasOwnProperty('params') && !paramsMatch(this.params, routeInfo.params); | ||
} | ||
function UnresolvedRouteInfoByParam(router, name, paramNames, params, route) { | ||
_classCallCheck(this, UnresolvedRouteInfoByParam); | ||
get route() { | ||
// _route could be set to either a route object or undefined, so we | ||
// compare against null to know when it's been set | ||
if (this._route !== null) { | ||
return this._route; | ||
} | ||
var _this4 = _possibleConstructorReturn(this, (UnresolvedRouteInfoByParam.__proto__ || Object.getPrototypeOf(UnresolvedRouteInfoByParam)).call(this, router, name, paramNames, route)); | ||
return this.fetchRoute(); | ||
} | ||
_this4.params = {}; | ||
_this4.params = params; | ||
return _this4; | ||
set route(route) { | ||
this._route = route; | ||
} | ||
get routePromise() { | ||
if (this._routePromise) { | ||
return this._routePromise; | ||
} | ||
_createClass(UnresolvedRouteInfoByParam, [{ | ||
key: 'getModel', | ||
value: function getModel(transition) { | ||
var fullParams = this.params; | ||
if (transition && transition[_transition2.QUERY_PARAMS_SYMBOL]) { | ||
fullParams = {}; | ||
(0, _utils.merge)(fullParams, this.params); | ||
fullParams.queryParams = transition[_transition2.QUERY_PARAMS_SYMBOL]; | ||
} | ||
var route = this.route; | ||
var result = undefined; | ||
if (route.deserialize) { | ||
result = route.deserialize(fullParams, transition); | ||
} else if (route.model) { | ||
result = route.model(fullParams, transition); | ||
} | ||
if (result && (0, _transition2.isTransition)(result)) { | ||
result = undefined; | ||
} | ||
return _rsvp.Promise.resolve(result); | ||
} | ||
}]); | ||
this.fetchRoute(); | ||
return this._routePromise; | ||
} | ||
return UnresolvedRouteInfoByParam; | ||
}(InternalRouteInfo); | ||
set routePromise(routePromise) { | ||
this._routePromise = routePromise; | ||
} | ||
var UnresolvedRouteInfoByObject = exports.UnresolvedRouteInfoByObject = function (_InternalRouteInfo3) { | ||
_inherits(UnresolvedRouteInfoByObject, _InternalRouteInfo3); | ||
log(transition, message) { | ||
if (transition.log) { | ||
transition.log(this.name + ': ' + message); | ||
} | ||
} | ||
function UnresolvedRouteInfoByObject(router, name, paramNames, context) { | ||
_classCallCheck(this, UnresolvedRouteInfoByObject); | ||
updateRoute(route) { | ||
route._internalName = this.name; | ||
return this.route = route; | ||
} | ||
var _this5 = _possibleConstructorReturn(this, (UnresolvedRouteInfoByObject.__proto__ || Object.getPrototypeOf(UnresolvedRouteInfoByObject)).call(this, router, name, paramNames)); | ||
runBeforeModelHook(transition) { | ||
if (transition.trigger) { | ||
transition.trigger(true, 'willResolveModel', transition, this.route); | ||
} | ||
_this5.context = context; | ||
_this5.serializer = _this5.router.getSerializer(name); | ||
return _this5; | ||
let result; | ||
if (this.route) { | ||
if (this.route.beforeModel !== undefined) { | ||
result = this.route.beforeModel(transition); | ||
} | ||
} | ||
_createClass(UnresolvedRouteInfoByObject, [{ | ||
key: 'getModel', | ||
value: function getModel(transition) { | ||
if (this.router.log !== undefined) { | ||
this.router.log(this.name + ': resolving provided model'); | ||
} | ||
return _get(UnresolvedRouteInfoByObject.prototype.__proto__ || Object.getPrototypeOf(UnresolvedRouteInfoByObject.prototype), 'getModel', this).call(this, transition); | ||
} | ||
/** | ||
@private | ||
Serializes a route using its custom `serialize` method or | ||
by a default that looks up the expected property name from | ||
the dynamic segment. | ||
@param {Object} model the model to be serialized for this route | ||
*/ | ||
if ((0, _transition2.isTransition)(result)) { | ||
result = null; | ||
} | ||
}, { | ||
key: 'serialize', | ||
value: function serialize(model) { | ||
var paramNames = this.paramNames, | ||
context = this.context; | ||
return _rsvp.Promise.resolve(result); | ||
} | ||
if (!model) { | ||
model = context; | ||
} | ||
var object = {}; | ||
if ((0, _utils.isParam)(model)) { | ||
object[paramNames[0]] = model; | ||
return object; | ||
} | ||
// Use custom serialize if it exists. | ||
if (this.serializer) { | ||
// invoke this.serializer unbound (getSerializer returns a stateless function) | ||
return this.serializer.call(null, model, paramNames); | ||
} else if (this.route !== undefined) { | ||
if (this.route.serialize) { | ||
return this.route.serialize(model, paramNames); | ||
} | ||
} | ||
if (paramNames.length !== 1) { | ||
return; | ||
} | ||
var name = paramNames[0]; | ||
if (/_id$/.test(name)) { | ||
object[name] = model.id; | ||
} else { | ||
object[name] = model; | ||
} | ||
return object; | ||
} | ||
}]); | ||
runAfterModelHook(transition, resolvedModel) { | ||
// Stash the resolved model on the payload. | ||
// This makes it possible for users to swap out | ||
// the resolved model in afterModel. | ||
let name = this.name; | ||
this.stashResolvedModel(transition, resolvedModel); | ||
let result; | ||
return UnresolvedRouteInfoByObject; | ||
}(InternalRouteInfo); | ||
if (this.route !== undefined) { | ||
if (this.route.afterModel !== undefined) { | ||
result = this.route.afterModel(resolvedModel, transition); | ||
} | ||
} | ||
function paramsMatch(a, b) { | ||
if (!a !== !b) { | ||
// Only one is null. | ||
return false; | ||
result = (0, _transition2.prepareResult)(result); | ||
return _rsvp.Promise.resolve(result).then(() => { | ||
// Ignore the fulfilled value returned from afterModel. | ||
// Return the value stashed in resolvedModels, which | ||
// might have been swapped out in afterModel. | ||
return transition.resolvedModels[name]; | ||
}); | ||
} | ||
checkForAbort(shouldContinue, value) { | ||
return _rsvp.Promise.resolve(shouldContinue()).then(function () { | ||
// We don't care about shouldContinue's resolve value; | ||
// pass along the original value passed to this fn. | ||
return value; | ||
}, null); | ||
} | ||
stashResolvedModel(transition, resolvedModel) { | ||
transition.resolvedModels = transition.resolvedModels || {}; | ||
transition.resolvedModels[this.name] = resolvedModel; | ||
} | ||
fetchRoute() { | ||
let route = this.router.getRoute(this.name); | ||
return this._processRoute(route); | ||
} | ||
_processRoute(route) { | ||
// Setup a routePromise so that we can wait for asynchronously loaded routes | ||
this.routePromise = _rsvp.Promise.resolve(route); // Wait until the 'route' property has been updated when chaining to a route | ||
// that is a promise | ||
if ((0, _utils.isPromise)(route)) { | ||
this.routePromise = this.routePromise.then(r => { | ||
return this.updateRoute(r); | ||
}); // set to undefined to avoid recursive loop in the route getter | ||
return this.route = undefined; | ||
} else if (route) { | ||
return this.updateRoute(route); | ||
} | ||
if (!a) { | ||
// Both must be null. | ||
return true; | ||
return undefined; | ||
} | ||
} | ||
exports.default = InternalRouteInfo; | ||
class ResolvedRouteInfo extends InternalRouteInfo { | ||
constructor(router, name, paramNames, params, route, context) { | ||
super(router, name, paramNames, route); | ||
this.params = params; | ||
this.isResolved = true; | ||
this.context = context; | ||
} | ||
resolve(_shouldContinue, transition) { | ||
// A ResolvedRouteInfo just resolved with itself. | ||
if (transition && transition.resolvedModels) { | ||
transition.resolvedModels[this.name] = this.context; | ||
} | ||
// Note: this assumes that both params have the same | ||
// number of keys, but since we're comparing the | ||
// same routes, they should. | ||
for (var k in a) { | ||
if (a.hasOwnProperty(k) && a[k] !== b[k]) { | ||
return false; | ||
} | ||
return _rsvp.Promise.resolve(this); | ||
} | ||
} | ||
exports.ResolvedRouteInfo = ResolvedRouteInfo; | ||
class UnresolvedRouteInfoByParam extends InternalRouteInfo { | ||
constructor(router, name, paramNames, params, route) { | ||
super(router, name, paramNames, route); | ||
this.params = {}; | ||
this.params = params; | ||
} | ||
getModel(transition) { | ||
let fullParams = this.params; | ||
if (transition && transition[_transition2.QUERY_PARAMS_SYMBOL]) { | ||
fullParams = {}; | ||
(0, _utils.merge)(fullParams, this.params); | ||
fullParams.queryParams = transition[_transition2.QUERY_PARAMS_SYMBOL]; | ||
} | ||
let route = this.route; | ||
let result; | ||
if (route.deserialize) { | ||
result = route.deserialize(fullParams, transition); | ||
} else if (route.model) { | ||
result = route.model(fullParams, transition); | ||
} | ||
if (result && (0, _transition2.isTransition)(result)) { | ||
result = undefined; | ||
} | ||
return _rsvp.Promise.resolve(result); | ||
} | ||
} | ||
exports.UnresolvedRouteInfoByParam = UnresolvedRouteInfoByParam; | ||
class UnresolvedRouteInfoByObject extends InternalRouteInfo { | ||
constructor(router, name, paramNames, context) { | ||
super(router, name, paramNames); | ||
this.context = context; | ||
this.serializer = this.router.getSerializer(name); | ||
} | ||
getModel(transition) { | ||
if (this.router.log !== undefined) { | ||
this.router.log(this.name + ': resolving provided model'); | ||
} | ||
return super.getModel(transition); | ||
} | ||
/** | ||
@private | ||
Serializes a route using its custom `serialize` method or | ||
by a default that looks up the expected property name from | ||
the dynamic segment. | ||
@param {Object} model the model to be serialized for this route | ||
*/ | ||
serialize(model) { | ||
let { | ||
paramNames, | ||
context | ||
} = this; | ||
if (!model) { | ||
model = context; | ||
} | ||
let object = {}; | ||
if ((0, _utils.isParam)(model)) { | ||
object[paramNames[0]] = model; | ||
return object; | ||
} // Use custom serialize if it exists. | ||
if (this.serializer) { | ||
// invoke this.serializer unbound (getSerializer returns a stateless function) | ||
return this.serializer.call(null, model, paramNames); | ||
} else if (this.route !== undefined) { | ||
if (this.route.serialize) { | ||
return this.route.serialize(model, paramNames); | ||
} | ||
} | ||
if (paramNames.length !== 1) { | ||
return; | ||
} | ||
let name = paramNames[0]; | ||
if (/_id$/.test(name)) { | ||
object[name] = model.id; | ||
} else { | ||
object[name] = model; | ||
} | ||
return object; | ||
} | ||
} | ||
exports.UnresolvedRouteInfoByObject = UnresolvedRouteInfoByObject; | ||
function paramsMatch(a, b) { | ||
if (!a !== !b) { | ||
// Only one is null. | ||
return false; | ||
} | ||
if (!a) { | ||
// Both must be null. | ||
return true; | ||
} | ||
//# sourceMappingURL=route-info.js.map | ||
} // Note: this assumes that both params have the same | ||
// number of keys, but since we're comparing the | ||
// same routes, they should. | ||
for (let k in a) { | ||
if (a.hasOwnProperty(k) && a[k] !== b[k]) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} |
@@ -10,3 +10,3 @@ import RouteRecognizer, { MatchCallback } from 'route-recognizer'; | ||
export interface SerializerFunc { | ||
(model: {}, params: string[]): unknown; | ||
(model: {}, params: string[]): Dict<unknown>; | ||
} | ||
@@ -228,5 +228,5 @@ export interface ParsedHandler { | ||
*/ | ||
generate(routeName: string, ...args: any[]): string; | ||
generate(routeName: string, ...args: unknown[]): string; | ||
applyIntent(routeName: string, contexts: Dict<unknown>[]): TransitionState<T>; | ||
isActiveIntent(routeName: string, contexts: any[], queryParams?: Dict<unknown>, _state?: TransitionState<T>): boolean; | ||
isActiveIntent(routeName: string, contexts: unknown[], queryParams?: Dict<unknown> | null, _state?: TransitionState<T>): boolean; | ||
isActive(routeName: string, ...args: unknown[]): boolean; | ||
@@ -233,0 +233,0 @@ trigger(name: string, ...args: any[]): void; |
@@ -1,897 +0,918 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.default = void 0; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _routeRecognizer = _interopRequireDefault(require("route-recognizer")); | ||
var _routeRecognizer = require('route-recognizer'); | ||
var _rsvp = require("rsvp"); | ||
var _routeRecognizer2 = _interopRequireDefault(_routeRecognizer); | ||
var _routeInfo = require("./route-info"); | ||
var _rsvp = require('rsvp'); | ||
var _transition = _interopRequireWildcard(require("./transition")); | ||
var _routeInfo = require('./route-info'); | ||
var _transitionAbortedError = _interopRequireDefault(require("./transition-aborted-error")); | ||
var _transition = require('./transition'); | ||
var _namedTransitionIntent = _interopRequireDefault(require("./transition-intent/named-transition-intent")); | ||
var _transition2 = _interopRequireDefault(_transition); | ||
var _urlTransitionIntent = _interopRequireDefault(require("./transition-intent/url-transition-intent")); | ||
var _transitionAbortedError = require('./transition-aborted-error'); | ||
var _transitionState = _interopRequireDefault(require("./transition-state")); | ||
var _transitionAbortedError2 = _interopRequireDefault(_transitionAbortedError); | ||
var _utils = require("./utils"); | ||
var _namedTransitionIntent = require('./transition-intent/named-transition-intent'); | ||
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } | ||
var _namedTransitionIntent2 = _interopRequireDefault(_namedTransitionIntent); | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
var _urlTransitionIntent = require('./transition-intent/url-transition-intent'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _urlTransitionIntent2 = _interopRequireDefault(_urlTransitionIntent); | ||
class Router { | ||
constructor(logger) { | ||
this._lastQueryParams = {}; | ||
this.state = undefined; | ||
this.oldState = undefined; | ||
this.activeTransition = undefined; | ||
this.currentRouteInfos = undefined; | ||
this._changedQueryParams = undefined; | ||
this.currentSequence = 0; | ||
this.log = logger; | ||
this.recognizer = new _routeRecognizer.default(); | ||
this.reset(); | ||
} | ||
/** | ||
The main entry point into the router. The API is essentially | ||
the same as the `map` method in `route-recognizer`. | ||
This method extracts the String handler at the last `.to()` | ||
call and uses it as the name of the whole route. | ||
@param {Function} callback | ||
*/ | ||
var _transitionState = require('./transition-state'); | ||
var _transitionState2 = _interopRequireDefault(_transitionState); | ||
map(callback) { | ||
this.recognizer.map(callback, function (recognizer, routes) { | ||
for (let i = routes.length - 1, proceed = true; i >= 0 && proceed; --i) { | ||
let route = routes[i]; | ||
let handler = route.handler; | ||
recognizer.add(routes, { | ||
as: handler | ||
}); | ||
proceed = route.path === '/' || route.path === '' || handler.slice(-6) === '.index'; | ||
} | ||
}); | ||
} | ||
var _utils = require('./utils'); | ||
hasRoute(route) { | ||
return this.recognizer.hasRoute(route); | ||
} | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
queryParamsTransition(changelist, wasTransitioning, oldState, newState) { | ||
this.fireQueryParamDidChange(newState, changelist); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
if (!wasTransitioning && this.activeTransition) { | ||
// One of the routes in queryParamsDidChange | ||
// caused a transition. Just return that transition. | ||
return this.activeTransition; | ||
} else { | ||
// Running queryParamsDidChange didn't change anything. | ||
// Just update query params and be on our way. | ||
// We have to return a noop transition that will | ||
// perform a URL update at the end. This gives | ||
// the user the ability to set the url update | ||
// method (default is replaceState). | ||
let newTransition = new _transition.default(this, undefined, undefined); | ||
newTransition.queryParamsOnly = true; | ||
oldState.queryParams = this.finalizeQueryParamChange(newState.routeInfos, newState.queryParams, newTransition); | ||
newTransition[_transition.QUERY_PARAMS_SYMBOL] = newState.queryParams; | ||
this.toReadOnlyInfos(newTransition, newState); | ||
this.routeWillChange(newTransition); | ||
newTransition.promise = newTransition.promise.then(result => { | ||
if (!newTransition.isAborted) { | ||
this._updateURL(newTransition, oldState); | ||
var Router = function () { | ||
function Router(logger) { | ||
_classCallCheck(this, Router); | ||
this.didTransition(this.currentRouteInfos); | ||
this.toInfos(newTransition, newState.routeInfos, true); | ||
this.routeDidChange(newTransition); | ||
} | ||
this._lastQueryParams = {}; | ||
this.state = undefined; | ||
this.oldState = undefined; | ||
this.activeTransition = undefined; | ||
this.currentRouteInfos = undefined; | ||
this._changedQueryParams = undefined; | ||
this.currentSequence = 0; | ||
this.log = logger; | ||
this.recognizer = new _routeRecognizer2.default(); | ||
this.reset(); | ||
return result; | ||
}, null, (0, _utils.promiseLabel)('Transition complete')); | ||
return newTransition; | ||
} | ||
/** | ||
The main entry point into the router. The API is essentially | ||
the same as the `map` method in `route-recognizer`. | ||
This method extracts the String handler at the last `.to()` | ||
call and uses it as the name of the whole route. | ||
@param {Function} callback | ||
*/ | ||
} | ||
transitionByIntent(intent, isIntermediate) { | ||
try { | ||
return this.getTransitionByIntent(intent, isIntermediate); | ||
} catch (e) { | ||
return new _transition.default(this, intent, undefined, e, undefined); | ||
} | ||
} | ||
_createClass(Router, [{ | ||
key: 'map', | ||
value: function map(callback) { | ||
this.recognizer.map(callback, function (recognizer, routes) { | ||
for (var i = routes.length - 1, proceed = true; i >= 0 && proceed; --i) { | ||
var route = routes[i]; | ||
var handler = route.handler; | ||
recognizer.add(routes, { as: handler }); | ||
proceed = route.path === '/' || route.path === '' || handler.slice(-6) === '.index'; | ||
} | ||
}); | ||
} | ||
}, { | ||
key: 'hasRoute', | ||
value: function hasRoute(route) { | ||
return this.recognizer.hasRoute(route); | ||
} | ||
}, { | ||
key: 'queryParamsTransition', | ||
value: function queryParamsTransition(changelist, wasTransitioning, oldState, newState) { | ||
var _this = this; | ||
recognize(url) { | ||
let intent = new _urlTransitionIntent.default(this, url); | ||
let newState = this.generateNewState(intent); | ||
this.fireQueryParamDidChange(newState, changelist); | ||
if (!wasTransitioning && this.activeTransition) { | ||
// One of the routes in queryParamsDidChange | ||
// caused a transition. Just return that transition. | ||
return this.activeTransition; | ||
} else { | ||
// Running queryParamsDidChange didn't change anything. | ||
// Just update query params and be on our way. | ||
// We have to return a noop transition that will | ||
// perform a URL update at the end. This gives | ||
// the user the ability to set the url update | ||
// method (default is replaceState). | ||
var newTransition = new _transition2.default(this, undefined, undefined); | ||
newTransition.queryParamsOnly = true; | ||
oldState.queryParams = this.finalizeQueryParamChange(newState.routeInfos, newState.queryParams, newTransition); | ||
newTransition[_transition.QUERY_PARAMS_SYMBOL] = newState.queryParams; | ||
this.toReadOnlyInfos(newTransition, newState); | ||
this.routeWillChange(newTransition); | ||
newTransition.promise = newTransition.promise.then(function (result) { | ||
if (!newTransition.isAborted) { | ||
_this._updateURL(newTransition, oldState); | ||
_this.didTransition(_this.currentRouteInfos); | ||
_this.toInfos(newTransition, newState.routeInfos, true); | ||
_this.routeDidChange(newTransition); | ||
} | ||
return result; | ||
}, null, (0, _utils.promiseLabel)('Transition complete')); | ||
return newTransition; | ||
} | ||
} | ||
}, { | ||
key: 'transitionByIntent', | ||
value: function transitionByIntent(intent, isIntermediate) { | ||
try { | ||
return this.getTransitionByIntent(intent, isIntermediate); | ||
} catch (e) { | ||
return new _transition2.default(this, intent, undefined, e, undefined); | ||
} | ||
} | ||
}, { | ||
key: 'recognize', | ||
value: function recognize(url) { | ||
var intent = new _urlTransitionIntent2.default(this, url); | ||
var newState = this.generateNewState(intent); | ||
if (newState === null) { | ||
return newState; | ||
} | ||
var readonlyInfos = (0, _routeInfo.toReadOnlyRouteInfo)(newState.routeInfos, newState.queryParams); | ||
return readonlyInfos[readonlyInfos.length - 1]; | ||
} | ||
}, { | ||
key: 'recognizeAndLoad', | ||
value: function recognizeAndLoad(url) { | ||
var intent = new _urlTransitionIntent2.default(this, url); | ||
var newState = this.generateNewState(intent); | ||
if (newState === null) { | ||
return _rsvp.Promise.reject(`URL ${url} was not recognized`); | ||
} | ||
var newTransition = new _transition2.default(this, intent, newState, undefined); | ||
return newTransition.then(function () { | ||
var routeInfosWithAttributes = (0, _routeInfo.toReadOnlyRouteInfo)(newState.routeInfos, newTransition[_transition.QUERY_PARAMS_SYMBOL], true); | ||
return routeInfosWithAttributes[routeInfosWithAttributes.length - 1]; | ||
}); | ||
} | ||
}, { | ||
key: 'generateNewState', | ||
value: function generateNewState(intent) { | ||
try { | ||
return intent.applyToState(this.state, false); | ||
} catch (e) { | ||
return null; | ||
} | ||
} | ||
}, { | ||
key: 'getTransitionByIntent', | ||
value: function getTransitionByIntent(intent, isIntermediate) { | ||
var _this2 = this; | ||
if (newState === null) { | ||
return newState; | ||
} | ||
var wasTransitioning = !!this.activeTransition; | ||
var oldState = wasTransitioning ? this.activeTransition[_transition.STATE_SYMBOL] : this.state; | ||
var newTransition = void 0; | ||
var newState = intent.applyToState(oldState, isIntermediate); | ||
var queryParamChangelist = (0, _utils.getChangelist)(oldState.queryParams, newState.queryParams); | ||
if (routeInfosEqual(newState.routeInfos, oldState.routeInfos)) { | ||
// This is a no-op transition. See if query params changed. | ||
if (queryParamChangelist) { | ||
var _newTransition = this.queryParamsTransition(queryParamChangelist, wasTransitioning, oldState, newState); | ||
_newTransition.queryParamsOnly = true; | ||
return _newTransition; | ||
} | ||
// No-op. No need to create a new transition. | ||
return this.activeTransition || new _transition2.default(this, undefined, undefined); | ||
} | ||
if (isIntermediate) { | ||
var transition = new _transition2.default(this, undefined, undefined); | ||
this.toReadOnlyInfos(transition, newState); | ||
this.setupContexts(newState); | ||
this.routeWillChange(transition); | ||
return this.activeTransition; | ||
} | ||
// Create a new transition to the destination route. | ||
newTransition = new _transition2.default(this, intent, newState, undefined, this.activeTransition); | ||
// transition is to same route with same params, only query params differ. | ||
// not caught above probably because refresh() has been used | ||
if (routeInfosSameExceptQueryParams(newState.routeInfos, oldState.routeInfos)) { | ||
newTransition.queryParamsOnly = true; | ||
} | ||
this.toReadOnlyInfos(newTransition, newState); | ||
// Abort and usurp any previously active transition. | ||
if (this.activeTransition) { | ||
this.activeTransition.redirect(newTransition); | ||
} | ||
this.activeTransition = newTransition; | ||
// Transition promises by default resolve with resolved state. | ||
// For our purposes, swap out the promise to resolve | ||
// after the transition has been finalized. | ||
newTransition.promise = newTransition.promise.then(function (result) { | ||
return _this2.finalizeTransition(newTransition, result); | ||
}, null, (0, _utils.promiseLabel)('Settle transition promise when transition is finalized')); | ||
if (!wasTransitioning) { | ||
this.notifyExistingHandlers(newState, newTransition); | ||
} | ||
this.fireQueryParamDidChange(newState, queryParamChangelist); | ||
return newTransition; | ||
} | ||
/** | ||
@private | ||
Begins and returns a Transition based on the provided | ||
arguments. Accepts arguments in the form of both URL | ||
transitions and named transitions. | ||
@param {Router} router | ||
@param {Array[Object]} args arguments passed to transitionTo, | ||
replaceWith, or handleURL | ||
*/ | ||
let readonlyInfos = (0, _routeInfo.toReadOnlyRouteInfo)(newState.routeInfos, newState.queryParams); | ||
return readonlyInfos[readonlyInfos.length - 1]; | ||
} | ||
}, { | ||
key: 'doTransition', | ||
value: function doTransition(name) { | ||
var modelsArray = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var isIntermediate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | ||
recognizeAndLoad(url) { | ||
let intent = new _urlTransitionIntent.default(this, url); | ||
let newState = this.generateNewState(intent); | ||
var lastArg = modelsArray[modelsArray.length - 1]; | ||
var queryParams = {}; | ||
if (lastArg !== undefined && lastArg.hasOwnProperty('queryParams')) { | ||
queryParams = modelsArray.pop().queryParams; | ||
} | ||
var intent = void 0; | ||
if (name === undefined) { | ||
(0, _utils.log)(this, 'Updating query params'); | ||
// A query param update is really just a transition | ||
// into the route you're already on. | ||
var routeInfos = this.state.routeInfos; | ||
if (newState === null) { | ||
return _rsvp.Promise.reject(`URL ${url} was not recognized`); | ||
} | ||
intent = new _namedTransitionIntent2.default(this, routeInfos[routeInfos.length - 1].name, undefined, [], queryParams); | ||
} else if (name.charAt(0) === '/') { | ||
(0, _utils.log)(this, 'Attempting URL transition to ' + name); | ||
intent = new _urlTransitionIntent2.default(this, name); | ||
} else { | ||
(0, _utils.log)(this, 'Attempting transition to ' + name); | ||
intent = new _namedTransitionIntent2.default(this, name, undefined, modelsArray, queryParams); | ||
} | ||
return this.transitionByIntent(intent, isIntermediate); | ||
} | ||
/** | ||
@private | ||
Updates the URL (if necessary) and calls `setupContexts` | ||
to update the router's array of `currentRouteInfos`. | ||
*/ | ||
let newTransition = new _transition.default(this, intent, newState, undefined); | ||
return newTransition.then(() => { | ||
let routeInfosWithAttributes = (0, _routeInfo.toReadOnlyRouteInfo)(newState.routeInfos, newTransition[_transition.QUERY_PARAMS_SYMBOL], true); | ||
return routeInfosWithAttributes[routeInfosWithAttributes.length - 1]; | ||
}); | ||
} | ||
}, { | ||
key: 'finalizeTransition', | ||
value: function finalizeTransition(transition, newState) { | ||
try { | ||
(0, _utils.log)(transition.router, transition.sequence, 'Resolved all models on destination route; finalizing transition.'); | ||
var routeInfos = newState.routeInfos; | ||
// Run all the necessary enter/setup/exit hooks | ||
this.setupContexts(newState, transition); | ||
// Check if a redirect occurred in enter/setup | ||
if (transition.isAborted) { | ||
// TODO: cleaner way? distinguish b/w targetRouteInfos? | ||
this.state.routeInfos = this.currentRouteInfos; | ||
return _rsvp.Promise.reject((0, _transition.logAbort)(transition)); | ||
} | ||
this._updateURL(transition, newState); | ||
transition.isActive = false; | ||
this.activeTransition = undefined; | ||
this.triggerEvent(this.currentRouteInfos, true, 'didTransition', []); | ||
this.didTransition(this.currentRouteInfos); | ||
this.toInfos(transition, newState.routeInfos, true); | ||
this.routeDidChange(transition); | ||
(0, _utils.log)(this, transition.sequence, 'TRANSITION COMPLETE.'); | ||
// Resolve with the final route. | ||
return routeInfos[routeInfos.length - 1].route; | ||
} catch (e) { | ||
if (!(e instanceof _transitionAbortedError2.default)) { | ||
var infos = transition[_transition.STATE_SYMBOL].routeInfos; | ||
transition.trigger(true, 'error', e, transition, infos[infos.length - 1].route); | ||
transition.abort(); | ||
} | ||
throw e; | ||
} | ||
} | ||
/** | ||
@private | ||
Takes an Array of `RouteInfo`s, figures out which ones are | ||
exiting, entering, or changing contexts, and calls the | ||
proper route hooks. | ||
For example, consider the following tree of routes. Each route is | ||
followed by the URL segment it handles. | ||
``` | ||
|~index ("/") | ||
| |~posts ("/posts") | ||
| | |-showPost ("/:id") | ||
| | |-newPost ("/new") | ||
| | |-editPost ("/edit") | ||
| |~about ("/about/:id") | ||
``` | ||
Consider the following transitions: | ||
1. A URL transition to `/posts/1`. | ||
1. Triggers the `*model` callbacks on the | ||
`index`, `posts`, and `showPost` routes | ||
2. Triggers the `enter` callback on the same | ||
3. Triggers the `setup` callback on the same | ||
2. A direct transition to `newPost` | ||
1. Triggers the `exit` callback on `showPost` | ||
2. Triggers the `enter` callback on `newPost` | ||
3. Triggers the `setup` callback on `newPost` | ||
3. A direct transition to `about` with a specified | ||
context object | ||
1. Triggers the `exit` callback on `newPost` | ||
and `posts` | ||
2. Triggers the `serialize` callback on `about` | ||
3. Triggers the `enter` callback on `about` | ||
4. Triggers the `setup` callback on `about` | ||
@param {Router} transition | ||
@param {TransitionState} newState | ||
*/ | ||
generateNewState(intent) { | ||
try { | ||
return intent.applyToState(this.state, false); | ||
} catch (e) { | ||
return null; | ||
} | ||
} | ||
}, { | ||
key: 'setupContexts', | ||
value: function setupContexts(newState, transition) { | ||
var partition = this.partitionRoutes(this.state, newState); | ||
var i = void 0, | ||
l = void 0, | ||
route = void 0; | ||
for (i = 0, l = partition.exited.length; i < l; i++) { | ||
route = partition.exited[i].route; | ||
delete route.context; | ||
if (route !== undefined) { | ||
if (route._internalReset !== undefined) { | ||
route._internalReset(true, transition); | ||
} | ||
if (route.exit !== undefined) { | ||
route.exit(transition); | ||
} | ||
} | ||
} | ||
var oldState = this.oldState = this.state; | ||
this.state = newState; | ||
var currentRouteInfos = this.currentRouteInfos = partition.unchanged.slice(); | ||
try { | ||
for (i = 0, l = partition.reset.length; i < l; i++) { | ||
route = partition.reset[i].route; | ||
if (route !== undefined) { | ||
if (route._internalReset !== undefined) { | ||
route._internalReset(false, transition); | ||
} | ||
} | ||
} | ||
for (i = 0, l = partition.updatedContext.length; i < l; i++) { | ||
this.routeEnteredOrUpdated(currentRouteInfos, partition.updatedContext[i], false, transition); | ||
} | ||
for (i = 0, l = partition.entered.length; i < l; i++) { | ||
this.routeEnteredOrUpdated(currentRouteInfos, partition.entered[i], true, transition); | ||
} | ||
} catch (e) { | ||
this.state = oldState; | ||
this.currentRouteInfos = oldState.routeInfos; | ||
throw e; | ||
} | ||
this.state.queryParams = this.finalizeQueryParamChange(currentRouteInfos, newState.queryParams, transition); | ||
} | ||
/** | ||
@private | ||
Fires queryParamsDidChange event | ||
*/ | ||
getTransitionByIntent(intent, isIntermediate) { | ||
let wasTransitioning = !!this.activeTransition; | ||
let oldState = wasTransitioning ? this.activeTransition[_transition.STATE_SYMBOL] : this.state; | ||
let newTransition; | ||
let newState = intent.applyToState(oldState, isIntermediate); | ||
let queryParamChangelist = (0, _utils.getChangelist)(oldState.queryParams, newState.queryParams); | ||
}, { | ||
key: 'fireQueryParamDidChange', | ||
value: function fireQueryParamDidChange(newState, queryParamChangelist) { | ||
// If queryParams changed trigger event | ||
if (queryParamChangelist) { | ||
// This is a little hacky but we need some way of storing | ||
// changed query params given that no activeTransition | ||
// is guaranteed to have occurred. | ||
this._changedQueryParams = queryParamChangelist.all; | ||
this.triggerEvent(newState.routeInfos, true, 'queryParamsDidChange', [queryParamChangelist.changed, queryParamChangelist.all, queryParamChangelist.removed]); | ||
this._changedQueryParams = undefined; | ||
} | ||
} | ||
/** | ||
@private | ||
Helper method used by setupContexts. Handles errors or redirects | ||
that may happen in enter/setup. | ||
*/ | ||
if (routeInfosEqual(newState.routeInfos, oldState.routeInfos)) { | ||
// This is a no-op transition. See if query params changed. | ||
if (queryParamChangelist) { | ||
let newTransition = this.queryParamsTransition(queryParamChangelist, wasTransitioning, oldState, newState); | ||
newTransition.queryParamsOnly = true; | ||
return newTransition; | ||
} // No-op. No need to create a new transition. | ||
}, { | ||
key: 'routeEnteredOrUpdated', | ||
value: function routeEnteredOrUpdated(currentRouteInfos, routeInfo, enter, transition) { | ||
var route = routeInfo.route, | ||
context = routeInfo.context; | ||
function _routeEnteredOrUpdated(route) { | ||
if (enter) { | ||
if (route.enter !== undefined) { | ||
route.enter(transition); | ||
} | ||
} | ||
if (transition && transition.isAborted) { | ||
throw new _transitionAbortedError2.default(); | ||
} | ||
route.context = context; | ||
if (route.contextDidChange !== undefined) { | ||
route.contextDidChange(); | ||
} | ||
if (route.setup !== undefined) { | ||
route.setup(context, transition); | ||
} | ||
if (transition && transition.isAborted) { | ||
throw new _transitionAbortedError2.default(); | ||
} | ||
currentRouteInfos.push(routeInfo); | ||
return route; | ||
} | ||
// If the route doesn't exist, it means we haven't resolved the route promise yet | ||
if (route === undefined) { | ||
routeInfo.routePromise = routeInfo.routePromise.then(_routeEnteredOrUpdated); | ||
} else { | ||
_routeEnteredOrUpdated(route); | ||
} | ||
return true; | ||
} | ||
/** | ||
@private | ||
This function is called when transitioning from one URL to | ||
another to determine which routes are no longer active, | ||
which routes are newly active, and which routes remain | ||
active but have their context changed. | ||
Take a list of old routes and new routes and partition | ||
them into four buckets: | ||
* unchanged: the route was active in both the old and | ||
new URL, and its context remains the same | ||
* updated context: the route was active in both the | ||
old and new URL, but its context changed. The route's | ||
`setup` method, if any, will be called with the new | ||
context. | ||
* exited: the route was active in the old URL, but is | ||
no longer active. | ||
* entered: the route was not active in the old URL, but | ||
is now active. | ||
The PartitionedRoutes structure has four fields: | ||
* `updatedContext`: a list of `RouteInfo` objects that | ||
represent routes that remain active but have a changed | ||
context | ||
* `entered`: a list of `RouteInfo` objects that represent | ||
routes that are newly active | ||
* `exited`: a list of `RouteInfo` objects that are no | ||
longer active. | ||
* `unchanged`: a list of `RouteInfo` objects that remain active. | ||
@param {Array[InternalRouteInfo]} oldRoutes a list of the route | ||
information for the previous URL (or `[]` if this is the | ||
first handled transition) | ||
@param {Array[InternalRouteInfo]} newRoutes a list of the route | ||
information for the new URL | ||
@return {Partition} | ||
*/ | ||
}, { | ||
key: 'partitionRoutes', | ||
value: function partitionRoutes(oldState, newState) { | ||
var oldRouteInfos = oldState.routeInfos; | ||
var newRouteInfos = newState.routeInfos; | ||
var routes = { | ||
updatedContext: [], | ||
exited: [], | ||
entered: [], | ||
unchanged: [], | ||
reset: [] | ||
}; | ||
var routeChanged = void 0, | ||
contextChanged = false, | ||
i = void 0, | ||
l = void 0; | ||
for (i = 0, l = newRouteInfos.length; i < l; i++) { | ||
var oldRouteInfo = oldRouteInfos[i], | ||
newRouteInfo = newRouteInfos[i]; | ||
if (!oldRouteInfo || oldRouteInfo.route !== newRouteInfo.route) { | ||
routeChanged = true; | ||
} | ||
if (routeChanged) { | ||
routes.entered.push(newRouteInfo); | ||
if (oldRouteInfo) { | ||
routes.exited.unshift(oldRouteInfo); | ||
} | ||
} else if (contextChanged || oldRouteInfo.context !== newRouteInfo.context) { | ||
contextChanged = true; | ||
routes.updatedContext.push(newRouteInfo); | ||
} else { | ||
routes.unchanged.push(oldRouteInfo); | ||
} | ||
} | ||
for (i = newRouteInfos.length, l = oldRouteInfos.length; i < l; i++) { | ||
routes.exited.unshift(oldRouteInfos[i]); | ||
} | ||
routes.reset = routes.updatedContext.slice(); | ||
routes.reset.reverse(); | ||
return routes; | ||
} | ||
}, { | ||
key: '_updateURL', | ||
value: function _updateURL(transition, state) { | ||
var urlMethod = transition.urlMethod; | ||
if (!urlMethod) { | ||
return; | ||
} | ||
var routeInfos = state.routeInfos; | ||
var routeName = routeInfos[routeInfos.length - 1].name; | ||
return this.activeTransition || new _transition.default(this, undefined, undefined); | ||
} | ||
var params = {}; | ||
for (var i = routeInfos.length - 1; i >= 0; --i) { | ||
var routeInfo = routeInfos[i]; | ||
(0, _utils.merge)(params, routeInfo.params); | ||
if (routeInfo.route.inaccessibleByURL) { | ||
urlMethod = null; | ||
} | ||
} | ||
if (urlMethod) { | ||
params.queryParams = transition._visibleQueryParams || state.queryParams; | ||
var url = this.recognizer.generate(routeName, params); | ||
// transitions during the initial transition must always use replaceURL. | ||
// When the app boots, you are at a url, e.g. /foo. If some route | ||
// redirects to bar as part of the initial transition, you don't want to | ||
// add a history entry for /foo. If you do, pressing back will immediately | ||
// hit the redirect again and take you back to /bar, thus killing the back | ||
// button | ||
var initial = transition.isCausedByInitialTransition; | ||
// say you are at / and you click a link to route /foo. In /foo's | ||
// route, the transition is aborted using replacewith('/bar'). | ||
// Because the current url is still /, the history entry for / is | ||
// removed from the history. Clicking back will take you to the page | ||
// you were on before /, which is often not even the app, thus killing | ||
// the back button. That's why updateURL is always correct for an | ||
// aborting transition that's not the initial transition | ||
var replaceAndNotAborting = urlMethod === 'replace' && !transition.isCausedByAbortingTransition; | ||
// because calling refresh causes an aborted transition, this needs to be | ||
// special cased - if the initial transition is a replace transition, the | ||
// urlMethod should be honored here. | ||
var isQueryParamsRefreshTransition = transition.queryParamsOnly && urlMethod === 'replace'; | ||
// say you are at / and you a `replaceWith(/foo)` is called. Then, that | ||
// transition is aborted with `replaceWith(/bar)`. At the end, we should | ||
// end up with /bar replacing /. We are replacing the replace. We only | ||
// will replace the initial route if all subsequent aborts are also | ||
// replaces. However, there is some ambiguity around the correct behavior | ||
// here. | ||
var replacingReplace = urlMethod === 'replace' && transition.isCausedByAbortingReplaceTransition; | ||
if (initial || replaceAndNotAborting || isQueryParamsRefreshTransition || replacingReplace) { | ||
this.replaceURL(url); | ||
} else { | ||
this.updateURL(url); | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'finalizeQueryParamChange', | ||
value: function finalizeQueryParamChange(resolvedHandlers, newQueryParams, transition) { | ||
// We fire a finalizeQueryParamChange event which | ||
// gives the new route hierarchy a chance to tell | ||
// us which query params it's consuming and what | ||
// their final values are. If a query param is | ||
// no longer consumed in the final route hierarchy, | ||
// its serialized segment will be removed | ||
// from the URL. | ||
for (var k in newQueryParams) { | ||
if (newQueryParams.hasOwnProperty(k) && newQueryParams[k] === null) { | ||
delete newQueryParams[k]; | ||
} | ||
} | ||
var finalQueryParamsArray = []; | ||
this.triggerEvent(resolvedHandlers, true, 'finalizeQueryParamChange', [newQueryParams, finalQueryParamsArray, transition]); | ||
if (transition) { | ||
transition._visibleQueryParams = {}; | ||
} | ||
var finalQueryParams = {}; | ||
for (var i = 0, len = finalQueryParamsArray.length; i < len; ++i) { | ||
var qp = finalQueryParamsArray[i]; | ||
finalQueryParams[qp.key] = qp.value; | ||
if (transition && qp.visible !== false) { | ||
transition._visibleQueryParams[qp.key] = qp.value; | ||
} | ||
} | ||
return finalQueryParams; | ||
} | ||
}, { | ||
key: 'toReadOnlyInfos', | ||
value: function toReadOnlyInfos(newTransition, newState) { | ||
var oldRouteInfos = this.state.routeInfos; | ||
this.fromInfos(newTransition, oldRouteInfos); | ||
this.toInfos(newTransition, newState.routeInfos); | ||
this._lastQueryParams = newState.queryParams; | ||
} | ||
}, { | ||
key: 'fromInfos', | ||
value: function fromInfos(newTransition, oldRouteInfos) { | ||
if (newTransition !== undefined && oldRouteInfos.length > 0) { | ||
var fromInfos = (0, _routeInfo.toReadOnlyRouteInfo)(oldRouteInfos, Object.assign({}, this._lastQueryParams), true); | ||
newTransition.from = fromInfos[fromInfos.length - 1] || null; | ||
} | ||
} | ||
}, { | ||
key: 'toInfos', | ||
value: function toInfos(newTransition, newRouteInfos) { | ||
var includeAttributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | ||
if (isIntermediate) { | ||
let transition = new _transition.default(this, undefined, undefined); | ||
this.toReadOnlyInfos(transition, newState); | ||
this.setupContexts(newState); | ||
this.routeWillChange(transition); | ||
return this.activeTransition; | ||
} // Create a new transition to the destination route. | ||
if (newTransition !== undefined && newRouteInfos.length > 0) { | ||
var toInfos = (0, _routeInfo.toReadOnlyRouteInfo)(newRouteInfos, Object.assign({}, newTransition[_transition.QUERY_PARAMS_SYMBOL]), includeAttributes); | ||
newTransition.to = toInfos[toInfos.length - 1] || null; | ||
} | ||
} | ||
}, { | ||
key: 'notifyExistingHandlers', | ||
value: function notifyExistingHandlers(newState, newTransition) { | ||
var oldRouteInfos = this.state.routeInfos, | ||
changing = [], | ||
i = void 0, | ||
oldRouteInfoLen = void 0, | ||
oldHandler = void 0, | ||
newRouteInfo = void 0; | ||
oldRouteInfoLen = oldRouteInfos.length; | ||
for (i = 0; i < oldRouteInfoLen; i++) { | ||
oldHandler = oldRouteInfos[i]; | ||
newRouteInfo = newState.routeInfos[i]; | ||
if (!newRouteInfo || oldHandler.name !== newRouteInfo.name) { | ||
break; | ||
} | ||
if (!newRouteInfo.isResolved) { | ||
changing.push(oldHandler); | ||
} | ||
} | ||
this.triggerEvent(oldRouteInfos, true, 'willTransition', [newTransition]); | ||
this.routeWillChange(newTransition); | ||
this.willTransition(oldRouteInfos, newState.routeInfos, newTransition); | ||
} | ||
/** | ||
Clears the current and target route routes and triggers exit | ||
on each of them starting at the leaf and traversing up through | ||
its ancestors. | ||
*/ | ||
}, { | ||
key: 'reset', | ||
value: function reset() { | ||
if (this.state) { | ||
(0, _utils.forEach)(this.state.routeInfos.slice().reverse(), function (routeInfo) { | ||
var route = routeInfo.route; | ||
if (route !== undefined) { | ||
if (route.exit !== undefined) { | ||
route.exit(); | ||
} | ||
} | ||
return true; | ||
}); | ||
} | ||
this.oldState = undefined; | ||
this.state = new _transitionState2.default(); | ||
this.currentRouteInfos = undefined; | ||
} | ||
/** | ||
let handler = routeInfo.handler; | ||
The entry point for handling a change to the URL (usually | ||
via the back and forward button). | ||
Returns an Array of handlers and the parameters associated | ||
with those parameters. | ||
@param {String} url a URL to process | ||
@return {Array} an Array of `[handler, parameter]` tuples | ||
*/ | ||
newTransition = new _transition.default(this, intent, newState, undefined, this.activeTransition); // transition is to same route with same params, only query params differ. | ||
// not caught above probably because refresh() has been used | ||
}, { | ||
key: 'handleURL', | ||
value: function handleURL(url) { | ||
// Perform a URL-based transition, but don't change | ||
// the URL afterward, since it already happened. | ||
if (url.charAt(0) !== '/') { | ||
url = '/' + url; | ||
} | ||
return this.doTransition(url).method(null); | ||
} | ||
/** | ||
Transition into the specified named route. | ||
If necessary, trigger the exit callback on any routes | ||
that are no longer represented by the target route. | ||
@param {String} name the name of the route | ||
*/ | ||
if (routeInfosSameExceptQueryParams(newState.routeInfos, oldState.routeInfos)) { | ||
newTransition.queryParamsOnly = true; | ||
} | ||
}, { | ||
key: 'transitionTo', | ||
value: function transitionTo(name) { | ||
for (var _len = arguments.length, contexts = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
contexts[_key - 1] = arguments[_key]; | ||
} | ||
this.toReadOnlyInfos(newTransition, newState); // Abort and usurp any previously active transition. | ||
if (typeof name === 'object') { | ||
contexts.push(name); | ||
return this.doTransition(undefined, contexts, false); | ||
} | ||
return this.doTransition(name, contexts); | ||
if (this.activeTransition) { | ||
this.activeTransition.redirect(newTransition); | ||
} | ||
this.activeTransition = newTransition; // Transition promises by default resolve with resolved state. | ||
// For our purposes, swap out the promise to resolve | ||
// after the transition has been finalized. | ||
newTransition.promise = newTransition.promise.then(result => { | ||
return this.finalizeTransition(newTransition, result); | ||
}, null, (0, _utils.promiseLabel)('Settle transition promise when transition is finalized')); | ||
if (!wasTransitioning) { | ||
this.notifyExistingHandlers(newState, newTransition); | ||
} | ||
this.fireQueryParamDidChange(newState, queryParamChangelist); | ||
return newTransition; | ||
} | ||
/** | ||
@private | ||
Begins and returns a Transition based on the provided | ||
arguments. Accepts arguments in the form of both URL | ||
transitions and named transitions. | ||
@param {Router} router | ||
@param {Array[Object]} args arguments passed to transitionTo, | ||
replaceWith, or handleURL | ||
*/ | ||
doTransition(name, modelsArray = [], isIntermediate = false) { | ||
let lastArg = modelsArray[modelsArray.length - 1]; | ||
let queryParams = {}; | ||
if (lastArg !== undefined && lastArg.hasOwnProperty('queryParams')) { | ||
queryParams = modelsArray.pop().queryParams; | ||
} | ||
let intent; | ||
if (name === undefined) { | ||
(0, _utils.log)(this, 'Updating query params'); // A query param update is really just a transition | ||
// into the route you're already on. | ||
let { | ||
routeInfos | ||
} = this.state; | ||
intent = new _namedTransitionIntent.default(this, routeInfos[routeInfos.length - 1].name, undefined, [], queryParams); | ||
} else if (name.charAt(0) === '/') { | ||
(0, _utils.log)(this, 'Attempting URL transition to ' + name); | ||
intent = new _urlTransitionIntent.default(this, name); | ||
} else { | ||
(0, _utils.log)(this, 'Attempting transition to ' + name); | ||
intent = new _namedTransitionIntent.default(this, name, undefined, modelsArray, queryParams); | ||
} | ||
return this.transitionByIntent(intent, isIntermediate); | ||
} | ||
/** | ||
@private | ||
Updates the URL (if necessary) and calls `setupContexts` | ||
to update the router's array of `currentRouteInfos`. | ||
*/ | ||
finalizeTransition(transition, newState) { | ||
try { | ||
(0, _utils.log)(transition.router, transition.sequence, 'Resolved all models on destination route; finalizing transition.'); | ||
let routeInfos = newState.routeInfos; // Run all the necessary enter/setup/exit hooks | ||
this.setupContexts(newState, transition); // Check if a redirect occurred in enter/setup | ||
if (transition.isAborted) { | ||
// TODO: cleaner way? distinguish b/w targetRouteInfos? | ||
this.state.routeInfos = this.currentRouteInfos; | ||
return _rsvp.Promise.reject((0, _transition.logAbort)(transition)); | ||
} | ||
this._updateURL(transition, newState); | ||
transition.isActive = false; | ||
this.activeTransition = undefined; | ||
this.triggerEvent(this.currentRouteInfos, true, 'didTransition', []); | ||
this.didTransition(this.currentRouteInfos); | ||
this.toInfos(transition, newState.routeInfos, true); | ||
this.routeDidChange(transition); | ||
(0, _utils.log)(this, transition.sequence, 'TRANSITION COMPLETE.'); // Resolve with the final route. | ||
return routeInfos[routeInfos.length - 1].route; | ||
} catch (e) { | ||
if (!(e instanceof _transitionAbortedError.default)) { | ||
let infos = transition[_transition.STATE_SYMBOL].routeInfos; | ||
transition.trigger(true, 'error', e, transition, infos[infos.length - 1].route); | ||
transition.abort(); | ||
} | ||
throw e; | ||
} | ||
} | ||
/** | ||
@private | ||
Takes an Array of `RouteInfo`s, figures out which ones are | ||
exiting, entering, or changing contexts, and calls the | ||
proper route hooks. | ||
For example, consider the following tree of routes. Each route is | ||
followed by the URL segment it handles. | ||
``` | ||
|~index ("/") | ||
| |~posts ("/posts") | ||
| | |-showPost ("/:id") | ||
| | |-newPost ("/new") | ||
| | |-editPost ("/edit") | ||
| |~about ("/about/:id") | ||
``` | ||
Consider the following transitions: | ||
1. A URL transition to `/posts/1`. | ||
1. Triggers the `*model` callbacks on the | ||
`index`, `posts`, and `showPost` routes | ||
2. Triggers the `enter` callback on the same | ||
3. Triggers the `setup` callback on the same | ||
2. A direct transition to `newPost` | ||
1. Triggers the `exit` callback on `showPost` | ||
2. Triggers the `enter` callback on `newPost` | ||
3. Triggers the `setup` callback on `newPost` | ||
3. A direct transition to `about` with a specified | ||
context object | ||
1. Triggers the `exit` callback on `newPost` | ||
and `posts` | ||
2. Triggers the `serialize` callback on `about` | ||
3. Triggers the `enter` callback on `about` | ||
4. Triggers the `setup` callback on `about` | ||
@param {Router} transition | ||
@param {TransitionState} newState | ||
*/ | ||
setupContexts(newState, transition) { | ||
let partition = this.partitionRoutes(this.state, newState); | ||
let i, l, route; | ||
for (i = 0, l = partition.exited.length; i < l; i++) { | ||
route = partition.exited[i].route; | ||
delete route.context; | ||
if (route !== undefined) { | ||
if (route._internalReset !== undefined) { | ||
route._internalReset(true, transition); | ||
} | ||
}, { | ||
key: 'intermediateTransitionTo', | ||
value: function intermediateTransitionTo(name) { | ||
for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { | ||
args[_key2 - 1] = arguments[_key2]; | ||
} | ||
return this.doTransition(name, args, true); | ||
if (route.exit !== undefined) { | ||
route.exit(transition); | ||
} | ||
}, { | ||
key: 'refresh', | ||
value: function refresh(pivotRoute) { | ||
var previousTransition = this.activeTransition; | ||
var state = previousTransition ? previousTransition[_transition.STATE_SYMBOL] : this.state; | ||
var routeInfos = state.routeInfos; | ||
if (pivotRoute === undefined) { | ||
pivotRoute = routeInfos[0].route; | ||
} | ||
(0, _utils.log)(this, 'Starting a refresh transition'); | ||
var name = routeInfos[routeInfos.length - 1].name; | ||
var intent = new _namedTransitionIntent2.default(this, name, pivotRoute, [], this._changedQueryParams || state.queryParams); | ||
var newTransition = this.transitionByIntent(intent, false); | ||
// if the previous transition is a replace transition, that needs to be preserved | ||
if (previousTransition && previousTransition.urlMethod === 'replace') { | ||
newTransition.method(previousTransition.urlMethod); | ||
} | ||
return newTransition; | ||
} | ||
/** | ||
Identical to `transitionTo` except that the current URL will be replaced | ||
if possible. | ||
This method is intended primarily for use with `replaceState`. | ||
@param {String} name the name of the route | ||
*/ | ||
} | ||
} | ||
}, { | ||
key: 'replaceWith', | ||
value: function replaceWith(name) { | ||
return this.doTransition(name).method('replace'); | ||
let oldState = this.oldState = this.state; | ||
this.state = newState; | ||
let currentRouteInfos = this.currentRouteInfos = partition.unchanged.slice(); | ||
try { | ||
for (i = 0, l = partition.reset.length; i < l; i++) { | ||
route = partition.reset[i].route; | ||
if (route !== undefined) { | ||
if (route._internalReset !== undefined) { | ||
route._internalReset(false, transition); | ||
} | ||
} | ||
/** | ||
Take a named route and context objects and generate a | ||
URL. | ||
@param {String} name the name of the route to generate | ||
a URL for | ||
@param {...Object} objects a list of objects to serialize | ||
@return {String} a URL | ||
*/ | ||
} | ||
}, { | ||
key: 'generate', | ||
value: function generate(routeName) { | ||
for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { | ||
args[_key3 - 1] = arguments[_key3]; | ||
} | ||
for (i = 0, l = partition.updatedContext.length; i < l; i++) { | ||
this.routeEnteredOrUpdated(currentRouteInfos, partition.updatedContext[i], false, transition); | ||
} | ||
var partitionedArgs = (0, _utils.extractQueryParams)(args), | ||
suppliedParams = partitionedArgs[0], | ||
queryParams = partitionedArgs[1]; | ||
// Construct a TransitionIntent with the provided params | ||
// and apply it to the present state of the router. | ||
var intent = new _namedTransitionIntent2.default(this, routeName, undefined, suppliedParams); | ||
var state = intent.applyToState(this.state, false); | ||
var params = {}; | ||
for (var i = 0, len = state.routeInfos.length; i < len; ++i) { | ||
var routeInfo = state.routeInfos[i]; | ||
var routeParams = routeInfo.serialize(); | ||
(0, _utils.merge)(params, routeParams); | ||
} | ||
params.queryParams = queryParams; | ||
return this.recognizer.generate(routeName, params); | ||
for (i = 0, l = partition.entered.length; i < l; i++) { | ||
this.routeEnteredOrUpdated(currentRouteInfos, partition.entered[i], true, transition); | ||
} | ||
} catch (e) { | ||
this.state = oldState; | ||
this.currentRouteInfos = oldState.routeInfos; | ||
throw e; | ||
} | ||
this.state.queryParams = this.finalizeQueryParamChange(currentRouteInfos, newState.queryParams, transition); | ||
} | ||
/** | ||
@private | ||
Fires queryParamsDidChange event | ||
*/ | ||
fireQueryParamDidChange(newState, queryParamChangelist) { | ||
// If queryParams changed trigger event | ||
if (queryParamChangelist) { | ||
// This is a little hacky but we need some way of storing | ||
// changed query params given that no activeTransition | ||
// is guaranteed to have occurred. | ||
this._changedQueryParams = queryParamChangelist.all; | ||
this.triggerEvent(newState.routeInfos, true, 'queryParamsDidChange', [queryParamChangelist.changed, queryParamChangelist.all, queryParamChangelist.removed]); | ||
this._changedQueryParams = undefined; | ||
} | ||
} | ||
/** | ||
@private | ||
Helper method used by setupContexts. Handles errors or redirects | ||
that may happen in enter/setup. | ||
*/ | ||
routeEnteredOrUpdated(currentRouteInfos, routeInfo, enter, transition) { | ||
let route = routeInfo.route, | ||
context = routeInfo.context; | ||
function _routeEnteredOrUpdated(route) { | ||
if (enter) { | ||
if (route.enter !== undefined) { | ||
route.enter(transition); | ||
} | ||
}, { | ||
key: 'applyIntent', | ||
value: function applyIntent(routeName, contexts) { | ||
var intent = new _namedTransitionIntent2.default(this, routeName, undefined, contexts); | ||
var state = this.activeTransition && this.activeTransition[_transition.STATE_SYMBOL] || this.state; | ||
return intent.applyToState(state, false); | ||
} | ||
}, { | ||
key: 'isActiveIntent', | ||
value: function isActiveIntent(routeName, contexts, queryParams, _state) { | ||
var state = _state || this.state, | ||
targetRouteInfos = state.routeInfos, | ||
routeInfo = void 0, | ||
len = void 0; | ||
if (!targetRouteInfos.length) { | ||
return false; | ||
} | ||
var targetHandler = targetRouteInfos[targetRouteInfos.length - 1].name; | ||
var recogHandlers = this.recognizer.handlersFor(targetHandler); | ||
var index = 0; | ||
for (len = recogHandlers.length; index < len; ++index) { | ||
routeInfo = targetRouteInfos[index]; | ||
if (routeInfo.name === routeName) { | ||
break; | ||
} | ||
} | ||
if (index === recogHandlers.length) { | ||
// The provided route name isn't even in the route hierarchy. | ||
return false; | ||
} | ||
var testState = new _transitionState2.default(); | ||
testState.routeInfos = targetRouteInfos.slice(0, index + 1); | ||
recogHandlers = recogHandlers.slice(0, index + 1); | ||
var intent = new _namedTransitionIntent2.default(this, targetHandler, undefined, contexts); | ||
var newState = intent.applyToHandlers(testState, recogHandlers, targetHandler, true, true); | ||
var routesEqual = routeInfosEqual(newState.routeInfos, testState.routeInfos); | ||
if (!queryParams || !routesEqual) { | ||
return routesEqual; | ||
} | ||
// Get a hash of QPs that will still be active on new route | ||
var activeQPsOnNewHandler = {}; | ||
(0, _utils.merge)(activeQPsOnNewHandler, queryParams); | ||
var activeQueryParams = state.queryParams; | ||
for (var key in activeQueryParams) { | ||
if (activeQueryParams.hasOwnProperty(key) && activeQPsOnNewHandler.hasOwnProperty(key)) { | ||
activeQPsOnNewHandler[key] = activeQueryParams[key]; | ||
} | ||
} | ||
return routesEqual && !(0, _utils.getChangelist)(activeQPsOnNewHandler, queryParams); | ||
} | ||
}, { | ||
key: 'isActive', | ||
value: function isActive(routeName) { | ||
for (var _len4 = arguments.length, args = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { | ||
args[_key4 - 1] = arguments[_key4]; | ||
} | ||
} | ||
var partitionedArgs = (0, _utils.extractQueryParams)(args); | ||
return this.isActiveIntent(routeName, partitionedArgs[0], partitionedArgs[1]); | ||
if (transition && transition.isAborted) { | ||
throw new _transitionAbortedError.default(); | ||
} | ||
route.context = context; | ||
if (route.contextDidChange !== undefined) { | ||
route.contextDidChange(); | ||
} | ||
if (route.setup !== undefined) { | ||
route.setup(context, transition); | ||
} | ||
if (transition && transition.isAborted) { | ||
throw new _transitionAbortedError.default(); | ||
} | ||
currentRouteInfos.push(routeInfo); | ||
return route; | ||
} // If the route doesn't exist, it means we haven't resolved the route promise yet | ||
if (route === undefined) { | ||
routeInfo.routePromise = routeInfo.routePromise.then(_routeEnteredOrUpdated); | ||
} else { | ||
_routeEnteredOrUpdated(route); | ||
} | ||
return true; | ||
} | ||
/** | ||
@private | ||
This function is called when transitioning from one URL to | ||
another to determine which routes are no longer active, | ||
which routes are newly active, and which routes remain | ||
active but have their context changed. | ||
Take a list of old routes and new routes and partition | ||
them into four buckets: | ||
* unchanged: the route was active in both the old and | ||
new URL, and its context remains the same | ||
* updated context: the route was active in both the | ||
old and new URL, but its context changed. The route's | ||
`setup` method, if any, will be called with the new | ||
context. | ||
* exited: the route was active in the old URL, but is | ||
no longer active. | ||
* entered: the route was not active in the old URL, but | ||
is now active. | ||
The PartitionedRoutes structure has four fields: | ||
* `updatedContext`: a list of `RouteInfo` objects that | ||
represent routes that remain active but have a changed | ||
context | ||
* `entered`: a list of `RouteInfo` objects that represent | ||
routes that are newly active | ||
* `exited`: a list of `RouteInfo` objects that are no | ||
longer active. | ||
* `unchanged`: a list of `RouteInfo` objects that remain active. | ||
@param {Array[InternalRouteInfo]} oldRoutes a list of the route | ||
information for the previous URL (or `[]` if this is the | ||
first handled transition) | ||
@param {Array[InternalRouteInfo]} newRoutes a list of the route | ||
information for the new URL | ||
@return {Partition} | ||
*/ | ||
partitionRoutes(oldState, newState) { | ||
let oldRouteInfos = oldState.routeInfos; | ||
let newRouteInfos = newState.routeInfos; | ||
let routes = { | ||
updatedContext: [], | ||
exited: [], | ||
entered: [], | ||
unchanged: [], | ||
reset: [] | ||
}; | ||
let routeChanged, | ||
contextChanged = false, | ||
i, | ||
l; | ||
for (i = 0, l = newRouteInfos.length; i < l; i++) { | ||
let oldRouteInfo = oldRouteInfos[i], | ||
newRouteInfo = newRouteInfos[i]; | ||
if (!oldRouteInfo || oldRouteInfo.route !== newRouteInfo.route) { | ||
routeChanged = true; | ||
} | ||
if (routeChanged) { | ||
routes.entered.push(newRouteInfo); | ||
if (oldRouteInfo) { | ||
routes.exited.unshift(oldRouteInfo); | ||
} | ||
}, { | ||
key: 'trigger', | ||
value: function trigger(name) { | ||
for (var _len5 = arguments.length, args = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) { | ||
args[_key5 - 1] = arguments[_key5]; | ||
} | ||
} else if (contextChanged || oldRouteInfo.context !== newRouteInfo.context) { | ||
contextChanged = true; | ||
routes.updatedContext.push(newRouteInfo); | ||
} else { | ||
routes.unchanged.push(oldRouteInfo); | ||
} | ||
} | ||
this.triggerEvent(this.currentRouteInfos, false, name, args); | ||
for (i = newRouteInfos.length, l = oldRouteInfos.length; i < l; i++) { | ||
routes.exited.unshift(oldRouteInfos[i]); | ||
} | ||
routes.reset = routes.updatedContext.slice(); | ||
routes.reset.reverse(); | ||
return routes; | ||
} | ||
_updateURL(transition, state) { | ||
let urlMethod = transition.urlMethod; | ||
if (!urlMethod) { | ||
return; | ||
} | ||
let { | ||
routeInfos | ||
} = state; | ||
let { | ||
name: routeName | ||
} = routeInfos[routeInfos.length - 1]; | ||
let params = {}; | ||
for (let i = routeInfos.length - 1; i >= 0; --i) { | ||
let routeInfo = routeInfos[i]; | ||
(0, _utils.merge)(params, routeInfo.params); | ||
if (routeInfo.route.inaccessibleByURL) { | ||
urlMethod = null; | ||
} | ||
} | ||
if (urlMethod) { | ||
params.queryParams = transition._visibleQueryParams || state.queryParams; | ||
let url = this.recognizer.generate(routeName, params); // transitions during the initial transition must always use replaceURL. | ||
// When the app boots, you are at a url, e.g. /foo. If some route | ||
// redirects to bar as part of the initial transition, you don't want to | ||
// add a history entry for /foo. If you do, pressing back will immediately | ||
// hit the redirect again and take you back to /bar, thus killing the back | ||
// button | ||
let initial = transition.isCausedByInitialTransition; // say you are at / and you click a link to route /foo. In /foo's | ||
// route, the transition is aborted using replacewith('/bar'). | ||
// Because the current url is still /, the history entry for / is | ||
// removed from the history. Clicking back will take you to the page | ||
// you were on before /, which is often not even the app, thus killing | ||
// the back button. That's why updateURL is always correct for an | ||
// aborting transition that's not the initial transition | ||
let replaceAndNotAborting = urlMethod === 'replace' && !transition.isCausedByAbortingTransition; // because calling refresh causes an aborted transition, this needs to be | ||
// special cased - if the initial transition is a replace transition, the | ||
// urlMethod should be honored here. | ||
let isQueryParamsRefreshTransition = transition.queryParamsOnly && urlMethod === 'replace'; // say you are at / and you a `replaceWith(/foo)` is called. Then, that | ||
// transition is aborted with `replaceWith(/bar)`. At the end, we should | ||
// end up with /bar replacing /. We are replacing the replace. We only | ||
// will replace the initial route if all subsequent aborts are also | ||
// replaces. However, there is some ambiguity around the correct behavior | ||
// here. | ||
let replacingReplace = urlMethod === 'replace' && transition.isCausedByAbortingReplaceTransition; | ||
if (initial || replaceAndNotAborting || isQueryParamsRefreshTransition || replacingReplace) { | ||
this.replaceURL(url); | ||
} else { | ||
this.updateURL(url); | ||
} | ||
} | ||
} | ||
finalizeQueryParamChange(resolvedHandlers, newQueryParams, transition) { | ||
// We fire a finalizeQueryParamChange event which | ||
// gives the new route hierarchy a chance to tell | ||
// us which query params it's consuming and what | ||
// their final values are. If a query param is | ||
// no longer consumed in the final route hierarchy, | ||
// its serialized segment will be removed | ||
// from the URL. | ||
for (let k in newQueryParams) { | ||
if (newQueryParams.hasOwnProperty(k) && newQueryParams[k] === null) { | ||
delete newQueryParams[k]; | ||
} | ||
} | ||
let finalQueryParamsArray = []; | ||
this.triggerEvent(resolvedHandlers, true, 'finalizeQueryParamChange', [newQueryParams, finalQueryParamsArray, transition]); | ||
if (transition) { | ||
transition._visibleQueryParams = {}; | ||
} | ||
let finalQueryParams = {}; | ||
for (let i = 0, len = finalQueryParamsArray.length; i < len; ++i) { | ||
let qp = finalQueryParamsArray[i]; | ||
finalQueryParams[qp.key] = qp.value; | ||
if (transition && qp.visible !== false) { | ||
transition._visibleQueryParams[qp.key] = qp.value; | ||
} | ||
} | ||
return finalQueryParams; | ||
} | ||
toReadOnlyInfos(newTransition, newState) { | ||
let oldRouteInfos = this.state.routeInfos; | ||
this.fromInfos(newTransition, oldRouteInfos); | ||
this.toInfos(newTransition, newState.routeInfos); | ||
this._lastQueryParams = newState.queryParams; | ||
} | ||
fromInfos(newTransition, oldRouteInfos) { | ||
if (newTransition !== undefined && oldRouteInfos.length > 0) { | ||
let fromInfos = (0, _routeInfo.toReadOnlyRouteInfo)(oldRouteInfos, Object.assign({}, this._lastQueryParams), true); | ||
newTransition.from = fromInfos[fromInfos.length - 1] || null; | ||
} | ||
} | ||
toInfos(newTransition, newRouteInfos, includeAttributes = false) { | ||
if (newTransition !== undefined && newRouteInfos.length > 0) { | ||
let toInfos = (0, _routeInfo.toReadOnlyRouteInfo)(newRouteInfos, Object.assign({}, newTransition[_transition.QUERY_PARAMS_SYMBOL]), includeAttributes); | ||
newTransition.to = toInfos[toInfos.length - 1] || null; | ||
} | ||
} | ||
notifyExistingHandlers(newState, newTransition) { | ||
let oldRouteInfos = this.state.routeInfos, | ||
changing = [], | ||
i, | ||
oldRouteInfoLen, | ||
oldHandler, | ||
newRouteInfo; | ||
oldRouteInfoLen = oldRouteInfos.length; | ||
for (i = 0; i < oldRouteInfoLen; i++) { | ||
oldHandler = oldRouteInfos[i]; | ||
newRouteInfo = newState.routeInfos[i]; | ||
if (!newRouteInfo || oldHandler.name !== newRouteInfo.name) { | ||
break; | ||
} | ||
if (!newRouteInfo.isResolved) { | ||
changing.push(oldHandler); | ||
} | ||
} | ||
this.triggerEvent(oldRouteInfos, true, 'willTransition', [newTransition]); | ||
this.routeWillChange(newTransition); | ||
this.willTransition(oldRouteInfos, newState.routeInfos, newTransition); | ||
} | ||
/** | ||
Clears the current and target route routes and triggers exit | ||
on each of them starting at the leaf and traversing up through | ||
its ancestors. | ||
*/ | ||
reset() { | ||
if (this.state) { | ||
(0, _utils.forEach)(this.state.routeInfos.slice().reverse(), function (routeInfo) { | ||
let route = routeInfo.route; | ||
if (route !== undefined) { | ||
if (route.exit !== undefined) { | ||
route.exit(); | ||
} | ||
} | ||
}]); | ||
return Router; | ||
}(); | ||
return true; | ||
}); | ||
} | ||
this.oldState = undefined; | ||
this.state = new _transitionState.default(); | ||
this.currentRouteInfos = undefined; | ||
} | ||
/** | ||
let handler = routeInfo.handler; | ||
The entry point for handling a change to the URL (usually | ||
via the back and forward button). | ||
Returns an Array of handlers and the parameters associated | ||
with those parameters. | ||
@param {String} url a URL to process | ||
@return {Array} an Array of `[handler, parameter]` tuples | ||
*/ | ||
handleURL(url) { | ||
// Perform a URL-based transition, but don't change | ||
// the URL afterward, since it already happened. | ||
if (url.charAt(0) !== '/') { | ||
url = '/' + url; | ||
} | ||
return this.doTransition(url).method(null); | ||
} | ||
/** | ||
Transition into the specified named route. | ||
If necessary, trigger the exit callback on any routes | ||
that are no longer represented by the target route. | ||
@param {String} name the name of the route | ||
*/ | ||
transitionTo(name, ...contexts) { | ||
if (typeof name === 'object') { | ||
contexts.push(name); | ||
return this.doTransition(undefined, contexts, false); | ||
} | ||
return this.doTransition(name, contexts); | ||
} | ||
intermediateTransitionTo(name, ...args) { | ||
return this.doTransition(name, args, true); | ||
} | ||
refresh(pivotRoute) { | ||
let previousTransition = this.activeTransition; | ||
let state = previousTransition ? previousTransition[_transition.STATE_SYMBOL] : this.state; | ||
let routeInfos = state.routeInfos; | ||
if (pivotRoute === undefined) { | ||
pivotRoute = routeInfos[0].route; | ||
} | ||
(0, _utils.log)(this, 'Starting a refresh transition'); | ||
let name = routeInfos[routeInfos.length - 1].name; | ||
let intent = new _namedTransitionIntent.default(this, name, pivotRoute, [], this._changedQueryParams || state.queryParams); | ||
let newTransition = this.transitionByIntent(intent, false); // if the previous transition is a replace transition, that needs to be preserved | ||
if (previousTransition && previousTransition.urlMethod === 'replace') { | ||
newTransition.method(previousTransition.urlMethod); | ||
} | ||
return newTransition; | ||
} | ||
/** | ||
Identical to `transitionTo` except that the current URL will be replaced | ||
if possible. | ||
This method is intended primarily for use with `replaceState`. | ||
@param {String} name the name of the route | ||
*/ | ||
replaceWith(name) { | ||
return this.doTransition(name).method('replace'); | ||
} | ||
/** | ||
Take a named route and context objects and generate a | ||
URL. | ||
@param {String} name the name of the route to generate | ||
a URL for | ||
@param {...Object} objects a list of objects to serialize | ||
@return {String} a URL | ||
*/ | ||
generate(routeName, ...args) { | ||
let partitionedArgs = (0, _utils.extractQueryParams)(args), | ||
suppliedParams = partitionedArgs[0], | ||
queryParams = partitionedArgs[1]; // Construct a TransitionIntent with the provided params | ||
// and apply it to the present state of the router. | ||
let intent = new _namedTransitionIntent.default(this, routeName, undefined, suppliedParams); | ||
let state = intent.applyToState(this.state, false); | ||
let params = {}; | ||
for (let i = 0, len = state.routeInfos.length; i < len; ++i) { | ||
let routeInfo = state.routeInfos[i]; | ||
let routeParams = routeInfo.serialize(); | ||
(0, _utils.merge)(params, routeParams); | ||
} | ||
params.queryParams = queryParams; | ||
return this.recognizer.generate(routeName, params); | ||
} | ||
applyIntent(routeName, contexts) { | ||
let intent = new _namedTransitionIntent.default(this, routeName, undefined, contexts); | ||
let state = this.activeTransition && this.activeTransition[_transition.STATE_SYMBOL] || this.state; | ||
return intent.applyToState(state, false); | ||
} | ||
isActiveIntent(routeName, contexts, queryParams, _state) { | ||
let state = _state || this.state, | ||
targetRouteInfos = state.routeInfos, | ||
routeInfo, | ||
len; | ||
if (!targetRouteInfos.length) { | ||
return false; | ||
} | ||
let targetHandler = targetRouteInfos[targetRouteInfos.length - 1].name; | ||
let recogHandlers = this.recognizer.handlersFor(targetHandler); | ||
let index = 0; | ||
for (len = recogHandlers.length; index < len; ++index) { | ||
routeInfo = targetRouteInfos[index]; | ||
if (routeInfo.name === routeName) { | ||
break; | ||
} | ||
} | ||
if (index === recogHandlers.length) { | ||
// The provided route name isn't even in the route hierarchy. | ||
return false; | ||
} | ||
let testState = new _transitionState.default(); | ||
testState.routeInfos = targetRouteInfos.slice(0, index + 1); | ||
recogHandlers = recogHandlers.slice(0, index + 1); | ||
let intent = new _namedTransitionIntent.default(this, targetHandler, undefined, contexts); | ||
let newState = intent.applyToHandlers(testState, recogHandlers, targetHandler, true, true); | ||
let routesEqual = routeInfosEqual(newState.routeInfos, testState.routeInfos); | ||
if (!queryParams || !routesEqual) { | ||
return routesEqual; | ||
} // Get a hash of QPs that will still be active on new route | ||
let activeQPsOnNewHandler = {}; | ||
(0, _utils.merge)(activeQPsOnNewHandler, queryParams); | ||
let activeQueryParams = state.queryParams; | ||
for (let key in activeQueryParams) { | ||
if (activeQueryParams.hasOwnProperty(key) && activeQPsOnNewHandler.hasOwnProperty(key)) { | ||
activeQPsOnNewHandler[key] = activeQueryParams[key]; | ||
} | ||
} | ||
return routesEqual && !(0, _utils.getChangelist)(activeQPsOnNewHandler, queryParams); | ||
} | ||
isActive(routeName, ...args) { | ||
let partitionedArgs = (0, _utils.extractQueryParams)(args); | ||
return this.isActiveIntent(routeName, partitionedArgs[0], partitionedArgs[1]); | ||
} | ||
trigger(name, ...args) { | ||
this.triggerEvent(this.currentRouteInfos, false, name, args); | ||
} | ||
} | ||
exports.default = Router; | ||
function routeInfosEqual(routeInfos, otherRouteInfos) { | ||
if (routeInfos.length !== otherRouteInfos.length) { | ||
return false; | ||
if (routeInfos.length !== otherRouteInfos.length) { | ||
return false; | ||
} | ||
for (let i = 0, len = routeInfos.length; i < len; ++i) { | ||
if (routeInfos[i] !== otherRouteInfos[i]) { | ||
return false; | ||
} | ||
for (var i = 0, len = routeInfos.length; i < len; ++i) { | ||
if (routeInfos[i] !== otherRouteInfos[i]) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
return true; | ||
} | ||
function routeInfosSameExceptQueryParams(routeInfos, otherRouteInfos) { | ||
if (routeInfos.length !== otherRouteInfos.length) { | ||
return false; | ||
if (routeInfos.length !== otherRouteInfos.length) { | ||
return false; | ||
} | ||
for (let i = 0, len = routeInfos.length; i < len; ++i) { | ||
if (routeInfos[i].name !== otherRouteInfos[i].name) { | ||
return false; | ||
} | ||
for (var i = 0, len = routeInfos.length; i < len; ++i) { | ||
if (routeInfos[i].name !== otherRouteInfos[i].name) { | ||
return false; | ||
} | ||
if (!paramsEqual(routeInfos[i].params, otherRouteInfos[i].params)) { | ||
return false; | ||
} | ||
if (!paramsEqual(routeInfos[i].params, otherRouteInfos[i].params)) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
return true; | ||
} | ||
function paramsEqual(params, otherParams) { | ||
if (!params && !otherParams) { | ||
return true; | ||
} else if (!params && !!otherParams || !!params && !otherParams) { | ||
// one is falsy but other is not; | ||
return false; | ||
if (!params && !otherParams) { | ||
return true; | ||
} else if (!params && !!otherParams || !!params && !otherParams) { | ||
// one is falsy but other is not; | ||
return false; | ||
} | ||
let keys = Object.keys(params); | ||
let otherKeys = Object.keys(otherParams); | ||
if (keys.length !== otherKeys.length) { | ||
return false; | ||
} | ||
for (let i = 0, len = keys.length; i < len; ++i) { | ||
let key = keys[i]; | ||
if (params[key] !== otherParams[key]) { | ||
return false; | ||
} | ||
var keys = Object.keys(params); | ||
var otherKeys = Object.keys(otherParams); | ||
if (keys.length !== otherKeys.length) { | ||
return false; | ||
} | ||
for (var i = 0, len = keys.length; i < len; ++i) { | ||
var key = keys[i]; | ||
if (params[key] !== otherParams[key]) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
//# sourceMappingURL=router.js.map | ||
} | ||
return true; | ||
} |
@@ -1,22 +0,28 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
var TransitionAbortedError = function () { | ||
TransitionAbortedError.prototype = Object.create(Error.prototype); | ||
TransitionAbortedError.prototype.constructor = TransitionAbortedError; | ||
function TransitionAbortedError(message) { | ||
var error = Error.call(this, message); | ||
this.name = 'TransitionAborted'; | ||
this.message = message || 'TransitionAborted'; | ||
if (Error.captureStackTrace) { | ||
Error.captureStackTrace(this, TransitionAbortedError); | ||
} else { | ||
this.stack = error.stack; | ||
} | ||
exports.default = void 0; | ||
const TransitionAbortedError = function () { | ||
TransitionAbortedError.prototype = Object.create(Error.prototype); | ||
TransitionAbortedError.prototype.constructor = TransitionAbortedError; | ||
function TransitionAbortedError(message) { | ||
let error = Error.call(this, message); | ||
this.name = 'TransitionAborted'; | ||
this.message = message || 'TransitionAborted'; | ||
if (Error.captureStackTrace) { | ||
Error.captureStackTrace(this, TransitionAbortedError); | ||
} else { | ||
this.stack = error.stack; | ||
} | ||
return TransitionAbortedError; | ||
} | ||
return TransitionAbortedError; | ||
}(); | ||
exports.default = TransitionAbortedError; | ||
//# sourceMappingURL=transition-aborted-error.js.map | ||
var _default = TransitionAbortedError; | ||
exports.default = _default; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.TransitionIntent = void 0; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
class TransitionIntent { | ||
constructor(router, data = {}) { | ||
this.router = router; | ||
this.data = data; | ||
} | ||
var TransitionIntent = exports.TransitionIntent = function TransitionIntent(router) { | ||
var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
} | ||
_classCallCheck(this, TransitionIntent); | ||
this.router = router; | ||
this.data = data; | ||
}; | ||
//# sourceMappingURL=transition-intent.js.map | ||
exports.TransitionIntent = TransitionIntent; |
@@ -9,11 +9,11 @@ import { Dict } from '../core'; | ||
pivotHandler?: Route; | ||
contexts: Dict<unknown>[]; | ||
contexts: unknown[]; | ||
queryParams: Dict<unknown>; | ||
preTransitionState?: TransitionState<T>; | ||
constructor(router: Router<T>, name: string, pivotHandler: Route | undefined, contexts?: Dict<unknown>[], queryParams?: Dict<unknown>, data?: {}); | ||
constructor(router: Router<T>, name: string, pivotHandler: Route | undefined, contexts?: unknown[], queryParams?: Dict<unknown>, data?: {}); | ||
applyToState(oldState: TransitionState<T>, isIntermediate: boolean): TransitionState<T>; | ||
applyToHandlers(oldState: TransitionState<T>, parsedHandlers: ParsedHandler[], targetRouteName: string, isIntermediate: boolean, checkingIfActive: boolean): TransitionState<T>; | ||
invalidateChildren(handlerInfos: InternalRouteInfo<T>[], invalidateIndex: number): void; | ||
getHandlerInfoForDynamicSegment(name: string, names: string[], objects: Dict<unknown>[], oldHandlerInfo: InternalRouteInfo<T>, _targetRouteName: string, i: number): InternalRouteInfo<T> | UnresolvedRouteInfoByObject<T>; | ||
createParamHandlerInfo(name: string, names: string[], objects: Dict<unknown>[], oldHandlerInfo: InternalRouteInfo<T>): UnresolvedRouteInfoByParam<T>; | ||
getHandlerInfoForDynamicSegment(name: string, names: string[], objects: unknown[], oldHandlerInfo: InternalRouteInfo<T>, _targetRouteName: string, i: number): InternalRouteInfo<T> | UnresolvedRouteInfoByObject<T>; | ||
createParamHandlerInfo(name: string, names: string[], objects: unknown[], oldHandlerInfo: InternalRouteInfo<T>): UnresolvedRouteInfoByParam<T>; | ||
} |
@@ -1,210 +0,200 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.default = void 0; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _routeInfo = require("../route-info"); | ||
var _routeInfo = require('../route-info'); | ||
var _transitionIntent = require("../transition-intent"); | ||
var _transitionIntent = require('../transition-intent'); | ||
var _transitionState = _interopRequireDefault(require("../transition-state")); | ||
var _transitionState = require('../transition-state'); | ||
var _utils = require("../utils"); | ||
var _transitionState2 = _interopRequireDefault(_transitionState); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _utils = require('../utils'); | ||
class NamedTransitionIntent extends _transitionIntent.TransitionIntent { | ||
constructor(router, name, pivotHandler, contexts = [], queryParams = {}, data) { | ||
super(router, data); | ||
this.preTransitionState = undefined; | ||
this.name = name; | ||
this.pivotHandler = pivotHandler; | ||
this.contexts = contexts; | ||
this.queryParams = queryParams; | ||
} | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
applyToState(oldState, isIntermediate) { | ||
// TODO: WTF fix me | ||
let partitionedArgs = (0, _utils.extractQueryParams)([this.name].concat(this.contexts)), | ||
pureArgs = partitionedArgs[0], | ||
handlers = this.router.recognizer.handlersFor(pureArgs[0]); | ||
let targetRouteName = handlers[handlers.length - 1].handler; | ||
return this.applyToHandlers(oldState, handlers, targetRouteName, isIntermediate, false); | ||
} | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
applyToHandlers(oldState, parsedHandlers, targetRouteName, isIntermediate, checkingIfActive) { | ||
let i, len; | ||
let newState = new _transitionState.default(); | ||
let objects = this.contexts.slice(0); | ||
let invalidateIndex = parsedHandlers.length; // Pivot handlers are provided for refresh transitions | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
if (this.pivotHandler) { | ||
for (i = 0, len = parsedHandlers.length; i < len; ++i) { | ||
if (parsedHandlers[i].handler === this.pivotHandler._internalName) { | ||
invalidateIndex = i; | ||
break; | ||
} | ||
} | ||
} | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
for (i = parsedHandlers.length - 1; i >= 0; --i) { | ||
let result = parsedHandlers[i]; | ||
let name = result.handler; | ||
let oldHandlerInfo = oldState.routeInfos[i]; | ||
let newHandlerInfo = null; | ||
var NamedTransitionIntent = function (_TransitionIntent) { | ||
_inherits(NamedTransitionIntent, _TransitionIntent); | ||
if (result.names.length > 0) { | ||
if (i >= invalidateIndex) { | ||
newHandlerInfo = this.createParamHandlerInfo(name, result.names, objects, oldHandlerInfo); | ||
} else { | ||
newHandlerInfo = this.getHandlerInfoForDynamicSegment(name, result.names, objects, oldHandlerInfo, targetRouteName, i); | ||
} | ||
} else { | ||
// This route has no dynamic segment. | ||
// Therefore treat as a param-based handlerInfo | ||
// with empty params. This will cause the `model` | ||
// hook to be called with empty params, which is desirable. | ||
newHandlerInfo = this.createParamHandlerInfo(name, result.names, objects, oldHandlerInfo); | ||
} | ||
function NamedTransitionIntent(router, name, pivotHandler) { | ||
var contexts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : []; | ||
var queryParams = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; | ||
var data = arguments[5]; | ||
if (checkingIfActive) { | ||
// If we're performing an isActive check, we want to | ||
// serialize URL params with the provided context, but | ||
// ignore mismatches between old and new context. | ||
newHandlerInfo = newHandlerInfo.becomeResolved(null, newHandlerInfo.context); | ||
let oldContext = oldHandlerInfo && oldHandlerInfo.context; | ||
_classCallCheck(this, NamedTransitionIntent); | ||
if (result.names.length > 0 && oldHandlerInfo.context !== undefined && newHandlerInfo.context === oldContext) { | ||
// If contexts match in isActive test, assume params also match. | ||
// This allows for flexibility in not requiring that every last | ||
// handler provide a `serialize` method | ||
newHandlerInfo.params = oldHandlerInfo && oldHandlerInfo.params; | ||
} | ||
var _this = _possibleConstructorReturn(this, (NamedTransitionIntent.__proto__ || Object.getPrototypeOf(NamedTransitionIntent)).call(this, router, data)); | ||
newHandlerInfo.context = oldContext; | ||
} | ||
_this.preTransitionState = undefined; | ||
_this.name = name; | ||
_this.pivotHandler = pivotHandler; | ||
_this.contexts = contexts; | ||
_this.queryParams = queryParams; | ||
return _this; | ||
let handlerToUse = oldHandlerInfo; | ||
if (i >= invalidateIndex || newHandlerInfo.shouldSupercede(oldHandlerInfo)) { | ||
invalidateIndex = Math.min(i, invalidateIndex); | ||
handlerToUse = newHandlerInfo; | ||
} | ||
if (isIntermediate && !checkingIfActive) { | ||
handlerToUse = handlerToUse.becomeResolved(null, handlerToUse.context); | ||
} | ||
newState.routeInfos.unshift(handlerToUse); | ||
} | ||
_createClass(NamedTransitionIntent, [{ | ||
key: 'applyToState', | ||
value: function applyToState(oldState, isIntermediate) { | ||
// TODO: WTF fix me | ||
var partitionedArgs = (0, _utils.extractQueryParams)([this.name].concat(this.contexts)), | ||
pureArgs = partitionedArgs[0], | ||
handlers = this.router.recognizer.handlersFor(pureArgs[0]); | ||
var targetRouteName = handlers[handlers.length - 1].handler; | ||
return this.applyToHandlers(oldState, handlers, targetRouteName, isIntermediate, false); | ||
} | ||
}, { | ||
key: 'applyToHandlers', | ||
value: function applyToHandlers(oldState, parsedHandlers, targetRouteName, isIntermediate, checkingIfActive) { | ||
var i = void 0, | ||
len = void 0; | ||
var newState = new _transitionState2.default(); | ||
var objects = this.contexts.slice(0); | ||
var invalidateIndex = parsedHandlers.length; | ||
// Pivot handlers are provided for refresh transitions | ||
if (this.pivotHandler) { | ||
for (i = 0, len = parsedHandlers.length; i < len; ++i) { | ||
if (parsedHandlers[i].handler === this.pivotHandler._internalName) { | ||
invalidateIndex = i; | ||
break; | ||
} | ||
} | ||
} | ||
for (i = parsedHandlers.length - 1; i >= 0; --i) { | ||
var result = parsedHandlers[i]; | ||
var name = result.handler; | ||
var oldHandlerInfo = oldState.routeInfos[i]; | ||
var newHandlerInfo = null; | ||
if (result.names.length > 0) { | ||
if (i >= invalidateIndex) { | ||
newHandlerInfo = this.createParamHandlerInfo(name, result.names, objects, oldHandlerInfo); | ||
} else { | ||
newHandlerInfo = this.getHandlerInfoForDynamicSegment(name, result.names, objects, oldHandlerInfo, targetRouteName, i); | ||
} | ||
} else { | ||
// This route has no dynamic segment. | ||
// Therefore treat as a param-based handlerInfo | ||
// with empty params. This will cause the `model` | ||
// hook to be called with empty params, which is desirable. | ||
newHandlerInfo = this.createParamHandlerInfo(name, result.names, objects, oldHandlerInfo); | ||
} | ||
if (checkingIfActive) { | ||
// If we're performing an isActive check, we want to | ||
// serialize URL params with the provided context, but | ||
// ignore mismatches between old and new context. | ||
newHandlerInfo = newHandlerInfo.becomeResolved(null, newHandlerInfo.context); | ||
var oldContext = oldHandlerInfo && oldHandlerInfo.context; | ||
if (result.names.length > 0 && oldHandlerInfo.context !== undefined && newHandlerInfo.context === oldContext) { | ||
// If contexts match in isActive test, assume params also match. | ||
// This allows for flexibility in not requiring that every last | ||
// handler provide a `serialize` method | ||
newHandlerInfo.params = oldHandlerInfo && oldHandlerInfo.params; | ||
} | ||
newHandlerInfo.context = oldContext; | ||
} | ||
var handlerToUse = oldHandlerInfo; | ||
if (i >= invalidateIndex || newHandlerInfo.shouldSupercede(oldHandlerInfo)) { | ||
invalidateIndex = Math.min(i, invalidateIndex); | ||
handlerToUse = newHandlerInfo; | ||
} | ||
if (isIntermediate && !checkingIfActive) { | ||
handlerToUse = handlerToUse.becomeResolved(null, handlerToUse.context); | ||
} | ||
newState.routeInfos.unshift(handlerToUse); | ||
} | ||
if (objects.length > 0) { | ||
throw new Error('More context objects were passed than there are dynamic segments for the route: ' + targetRouteName); | ||
} | ||
if (!isIntermediate) { | ||
this.invalidateChildren(newState.routeInfos, invalidateIndex); | ||
} | ||
(0, _utils.merge)(newState.queryParams, this.queryParams || {}); | ||
return newState; | ||
} | ||
}, { | ||
key: 'invalidateChildren', | ||
value: function invalidateChildren(handlerInfos, invalidateIndex) { | ||
for (var i = invalidateIndex, l = handlerInfos.length; i < l; ++i) { | ||
var handlerInfo = handlerInfos[i]; | ||
if (handlerInfo.isResolved) { | ||
var _handlerInfos$i = handlerInfos[i], | ||
name = _handlerInfos$i.name, | ||
params = _handlerInfos$i.params, | ||
route = _handlerInfos$i.route, | ||
paramNames = _handlerInfos$i.paramNames; | ||
if (objects.length > 0) { | ||
throw new Error('More context objects were passed than there are dynamic segments for the route: ' + targetRouteName); | ||
} | ||
handlerInfos[i] = new _routeInfo.UnresolvedRouteInfoByParam(this.router, name, paramNames, params, route); | ||
} | ||
} | ||
if (!isIntermediate) { | ||
this.invalidateChildren(newState.routeInfos, invalidateIndex); | ||
} | ||
(0, _utils.merge)(newState.queryParams, this.queryParams || {}); | ||
return newState; | ||
} | ||
invalidateChildren(handlerInfos, invalidateIndex) { | ||
for (let i = invalidateIndex, l = handlerInfos.length; i < l; ++i) { | ||
let handlerInfo = handlerInfos[i]; | ||
if (handlerInfo.isResolved) { | ||
let { | ||
name, | ||
params, | ||
route, | ||
paramNames | ||
} = handlerInfos[i]; | ||
handlerInfos[i] = new _routeInfo.UnresolvedRouteInfoByParam(this.router, name, paramNames, params, route); | ||
} | ||
} | ||
} | ||
getHandlerInfoForDynamicSegment(name, names, objects, oldHandlerInfo, _targetRouteName, i) { | ||
let objectToUse; | ||
if (objects.length > 0) { | ||
// Use the objects provided for this transition. | ||
objectToUse = objects[objects.length - 1]; | ||
if ((0, _utils.isParam)(objectToUse)) { | ||
return this.createParamHandlerInfo(name, names, objects, oldHandlerInfo); | ||
} else { | ||
objects.pop(); | ||
} | ||
} else if (oldHandlerInfo && oldHandlerInfo.name === name) { | ||
// Reuse the matching oldHandlerInfo | ||
return oldHandlerInfo; | ||
} else { | ||
if (this.preTransitionState) { | ||
let preTransitionHandlerInfo = this.preTransitionState.routeInfos[i]; | ||
objectToUse = preTransitionHandlerInfo && preTransitionHandlerInfo.context; | ||
} else { | ||
// Ideally we should throw this error to provide maximal | ||
// information to the user that not enough context objects | ||
// were provided, but this proves too cumbersome in Ember | ||
// in cases where inner template helpers are evaluated | ||
// before parent helpers un-render, in which cases this | ||
// error somewhat prematurely fires. | ||
//throw new Error("Not enough context objects were provided to complete a transition to " + targetRouteName + ". Specifically, the " + name + " route needs an object that can be serialized into its dynamic URL segments [" + names.join(', ') + "]"); | ||
return oldHandlerInfo; | ||
} | ||
} | ||
return new _routeInfo.UnresolvedRouteInfoByObject(this.router, name, names, objectToUse); | ||
} | ||
createParamHandlerInfo(name, names, objects, oldHandlerInfo) { | ||
let params = {}; // Soak up all the provided string/numbers | ||
let numNames = names.length; | ||
let missingParams = []; | ||
while (numNames--) { | ||
// Only use old params if the names match with the new handler | ||
let oldParams = oldHandlerInfo && name === oldHandlerInfo.name && oldHandlerInfo.params || {}; | ||
let peek = objects[objects.length - 1]; | ||
let paramName = names[numNames]; | ||
if ((0, _utils.isParam)(peek)) { | ||
params[paramName] = '' + objects.pop(); | ||
} else { | ||
// If we're here, this means only some of the params | ||
// were string/number params, so try and use a param | ||
// value from a previous handler. | ||
if (oldParams.hasOwnProperty(paramName)) { | ||
params[paramName] = oldParams[paramName]; | ||
} else { | ||
missingParams.push(paramName); | ||
} | ||
}, { | ||
key: 'getHandlerInfoForDynamicSegment', | ||
value: function getHandlerInfoForDynamicSegment(name, names, objects, oldHandlerInfo, _targetRouteName, i) { | ||
var objectToUse = void 0; | ||
if (objects.length > 0) { | ||
// Use the objects provided for this transition. | ||
objectToUse = objects[objects.length - 1]; | ||
if ((0, _utils.isParam)(objectToUse)) { | ||
return this.createParamHandlerInfo(name, names, objects, oldHandlerInfo); | ||
} else { | ||
objects.pop(); | ||
} | ||
} else if (oldHandlerInfo && oldHandlerInfo.name === name) { | ||
// Reuse the matching oldHandlerInfo | ||
return oldHandlerInfo; | ||
} else { | ||
if (this.preTransitionState) { | ||
var preTransitionHandlerInfo = this.preTransitionState.routeInfos[i]; | ||
objectToUse = preTransitionHandlerInfo && preTransitionHandlerInfo.context; | ||
} else { | ||
// Ideally we should throw this error to provide maximal | ||
// information to the user that not enough context objects | ||
// were provided, but this proves too cumbersome in Ember | ||
// in cases where inner template helpers are evaluated | ||
// before parent helpers un-render, in which cases this | ||
// error somewhat prematurely fires. | ||
//throw new Error("Not enough context objects were provided to complete a transition to " + targetRouteName + ". Specifically, the " + name + " route needs an object that can be serialized into its dynamic URL segments [" + names.join(', ') + "]"); | ||
return oldHandlerInfo; | ||
} | ||
} | ||
return new _routeInfo.UnresolvedRouteInfoByObject(this.router, name, names, objectToUse); | ||
} | ||
}, { | ||
key: 'createParamHandlerInfo', | ||
value: function createParamHandlerInfo(name, names, objects, oldHandlerInfo) { | ||
var params = {}; | ||
// Soak up all the provided string/numbers | ||
var numNames = names.length; | ||
var missingParams = []; | ||
while (numNames--) { | ||
// Only use old params if the names match with the new handler | ||
var oldParams = oldHandlerInfo && name === oldHandlerInfo.name && oldHandlerInfo.params || {}; | ||
var peek = objects[objects.length - 1]; | ||
var paramName = names[numNames]; | ||
if ((0, _utils.isParam)(peek)) { | ||
params[paramName] = '' + objects.pop(); | ||
} else { | ||
// If we're here, this means only some of the params | ||
// were string/number params, so try and use a param | ||
// value from a previous handler. | ||
if (oldParams.hasOwnProperty(paramName)) { | ||
params[paramName] = oldParams[paramName]; | ||
} else { | ||
missingParams.push(paramName); | ||
} | ||
} | ||
} | ||
if (missingParams.length > 0) { | ||
throw new Error(`You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route ${name}.` + ` Missing params: ${missingParams}`); | ||
} | ||
return new _routeInfo.UnresolvedRouteInfoByParam(this.router, name, names, params); | ||
} | ||
}]); | ||
} | ||
} | ||
return NamedTransitionIntent; | ||
}(_transitionIntent.TransitionIntent); | ||
//# sourceMappingURL=named-transition-intent.js.map | ||
if (missingParams.length > 0) { | ||
throw new Error(`You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route ${name}.` + ` Missing params: ${missingParams}`); | ||
} | ||
return new _routeInfo.UnresolvedRouteInfoByParam(this.router, name, names, params); | ||
} | ||
} | ||
exports.default = NamedTransitionIntent; |
@@ -1,99 +0,86 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.default = void 0; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _routeInfo = require("../route-info"); | ||
var _routeInfo = require('../route-info'); | ||
var _transitionIntent = require("../transition-intent"); | ||
var _transitionIntent = require('../transition-intent'); | ||
var _transitionState = _interopRequireDefault(require("../transition-state")); | ||
var _transitionState = require('../transition-state'); | ||
var _unrecognizedUrlError = _interopRequireDefault(require("../unrecognized-url-error")); | ||
var _transitionState2 = _interopRequireDefault(_transitionState); | ||
var _utils = require("../utils"); | ||
var _unrecognizedUrlError = require('../unrecognized-url-error'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _unrecognizedUrlError2 = _interopRequireDefault(_unrecognizedUrlError); | ||
class URLTransitionIntent extends _transitionIntent.TransitionIntent { | ||
constructor(router, url, data) { | ||
super(router, data); | ||
this.url = url; | ||
this.preTransitionState = undefined; | ||
} | ||
var _utils = require('../utils'); | ||
applyToState(oldState) { | ||
let newState = new _transitionState.default(); | ||
let results = this.router.recognizer.recognize(this.url), | ||
i, | ||
len; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
if (!results) { | ||
throw new _unrecognizedUrlError.default(this.url); | ||
} | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
let statesDiffer = false; | ||
let _url = this.url; // Checks if a handler is accessible by URL. If it is not, an error is thrown. | ||
// For the case where the handler is loaded asynchronously, the error will be | ||
// thrown once it is loaded. | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function checkHandlerAccessibility(handler) { | ||
if (handler && handler.inaccessibleByURL) { | ||
throw new _unrecognizedUrlError.default(_url); | ||
} | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
return handler; | ||
} | ||
var URLTransitionIntent = function (_TransitionIntent) { | ||
_inherits(URLTransitionIntent, _TransitionIntent); | ||
for (i = 0, len = results.length; i < len; ++i) { | ||
let result = results[i]; | ||
let name = result.handler; | ||
let paramNames = []; | ||
function URLTransitionIntent(router, url, data) { | ||
_classCallCheck(this, URLTransitionIntent); | ||
if (this.router.recognizer.hasRoute(name)) { | ||
paramNames = this.router.recognizer.handlersFor(name)[i].names; | ||
} | ||
var _this = _possibleConstructorReturn(this, (URLTransitionIntent.__proto__ || Object.getPrototypeOf(URLTransitionIntent)).call(this, router, data)); | ||
let newRouteInfo = new _routeInfo.UnresolvedRouteInfoByParam(this.router, name, paramNames, result.params); | ||
let route = newRouteInfo.route; | ||
_this.url = url; | ||
_this.preTransitionState = undefined; | ||
return _this; | ||
if (route) { | ||
checkHandlerAccessibility(route); | ||
} else { | ||
// If the hanlder is being loaded asynchronously, check if we can | ||
// access it after it has resolved | ||
newRouteInfo.routePromise = newRouteInfo.routePromise.then(checkHandlerAccessibility); | ||
} | ||
let oldRouteInfo = oldState.routeInfos[i]; | ||
if (statesDiffer || newRouteInfo.shouldSupercede(oldRouteInfo)) { | ||
statesDiffer = true; | ||
newState.routeInfos[i] = newRouteInfo; | ||
} else { | ||
newState.routeInfos[i] = oldRouteInfo; | ||
} | ||
} | ||
_createClass(URLTransitionIntent, [{ | ||
key: 'applyToState', | ||
value: function applyToState(oldState) { | ||
var newState = new _transitionState2.default(); | ||
var results = this.router.recognizer.recognize(this.url), | ||
i = void 0, | ||
len = void 0; | ||
if (!results) { | ||
throw new _unrecognizedUrlError2.default(this.url); | ||
} | ||
var statesDiffer = false; | ||
var _url = this.url; | ||
// Checks if a handler is accessible by URL. If it is not, an error is thrown. | ||
// For the case where the handler is loaded asynchronously, the error will be | ||
// thrown once it is loaded. | ||
function checkHandlerAccessibility(handler) { | ||
if (handler && handler.inaccessibleByURL) { | ||
throw new _unrecognizedUrlError2.default(_url); | ||
} | ||
return handler; | ||
} | ||
for (i = 0, len = results.length; i < len; ++i) { | ||
var result = results[i]; | ||
var name = result.handler; | ||
var paramNames = []; | ||
if (this.router.recognizer.hasRoute(name)) { | ||
paramNames = this.router.recognizer.handlersFor(name)[i].names; | ||
} | ||
var newRouteInfo = new _routeInfo.UnresolvedRouteInfoByParam(this.router, name, paramNames, result.params); | ||
var route = newRouteInfo.route; | ||
if (route) { | ||
checkHandlerAccessibility(route); | ||
} else { | ||
// If the hanlder is being loaded asynchronously, check if we can | ||
// access it after it has resolved | ||
newRouteInfo.routePromise = newRouteInfo.routePromise.then(checkHandlerAccessibility); | ||
} | ||
var oldRouteInfo = oldState.routeInfos[i]; | ||
if (statesDiffer || newRouteInfo.shouldSupercede(oldRouteInfo)) { | ||
statesDiffer = true; | ||
newState.routeInfos[i] = newRouteInfo; | ||
} else { | ||
newState.routeInfos[i] = oldRouteInfo; | ||
} | ||
} | ||
(0, _utils.merge)(newState.queryParams, results.queryParams); | ||
return newState; | ||
} | ||
}]); | ||
(0, _utils.merge)(newState.queryParams, results.queryParams); | ||
return newState; | ||
} | ||
return URLTransitionIntent; | ||
}(_transitionIntent.TransitionIntent); | ||
//# sourceMappingURL=url-transition-intent.js.map | ||
} | ||
exports.default = URLTransitionIntent; |
@@ -1,111 +0,109 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.TransitionError = undefined; | ||
exports.TransitionError = exports.default = void 0; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _rsvp = require("rsvp"); | ||
var _rsvp = require('rsvp'); | ||
var _utils = require("./utils"); | ||
var _utils = require('./utils'); | ||
class TransitionState { | ||
constructor() { | ||
this.routeInfos = []; | ||
this.queryParams = {}; | ||
this.params = {}; | ||
} | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
promiseLabel(label) { | ||
let targetName = ''; | ||
(0, _utils.forEach)(this.routeInfos, function (routeInfo) { | ||
if (targetName !== '') { | ||
targetName += '.'; | ||
} | ||
var TransitionState = function () { | ||
function TransitionState() { | ||
_classCallCheck(this, TransitionState); | ||
targetName += routeInfo.name; | ||
return true; | ||
}); | ||
return (0, _utils.promiseLabel)("'" + targetName + "': " + label); | ||
} | ||
this.routeInfos = []; | ||
this.queryParams = {}; | ||
this.params = {}; | ||
resolve(shouldContinue, transition) { | ||
// First, calculate params for this state. This is useful | ||
// information to provide to the various route hooks. | ||
let params = this.params; | ||
(0, _utils.forEach)(this.routeInfos, routeInfo => { | ||
params[routeInfo.name] = routeInfo.params || {}; | ||
return true; | ||
}); | ||
transition.resolveIndex = 0; | ||
let currentState = this; | ||
let wasAborted = false; // The prelude RSVP.resolve() asyncs us into the promise land. | ||
return _rsvp.Promise.resolve(null, this.promiseLabel('Start transition')).then(resolveOneRouteInfo, null, this.promiseLabel('Resolve route')).catch(handleError, this.promiseLabel('Handle error')); | ||
function innerShouldContinue() { | ||
return _rsvp.Promise.resolve(shouldContinue(), currentState.promiseLabel('Check if should continue')).catch(function (reason) { | ||
// We distinguish between errors that occurred | ||
// during resolution (e.g. before"Model/model/afterModel), | ||
// and aborts due to a rejecting promise from shouldContinue(). | ||
wasAborted = true; | ||
return _rsvp.Promise.reject(reason); | ||
}, currentState.promiseLabel('Handle abort')); | ||
} | ||
_createClass(TransitionState, [{ | ||
key: 'promiseLabel', | ||
value: function promiseLabel(label) { | ||
var targetName = ''; | ||
(0, _utils.forEach)(this.routeInfos, function (routeInfo) { | ||
if (targetName !== '') { | ||
targetName += '.'; | ||
} | ||
targetName += routeInfo.name; | ||
return true; | ||
}); | ||
return (0, _utils.promiseLabel)("'" + targetName + "': " + label); | ||
} | ||
}, { | ||
key: 'resolve', | ||
value: function resolve(shouldContinue, transition) { | ||
// First, calculate params for this state. This is useful | ||
// information to provide to the various route hooks. | ||
var params = this.params; | ||
(0, _utils.forEach)(this.routeInfos, function (routeInfo) { | ||
params[routeInfo.name] = routeInfo.params || {}; | ||
return true; | ||
}); | ||
transition.resolveIndex = 0; | ||
var currentState = this; | ||
var wasAborted = false; | ||
// The prelude RSVP.resolve() asyncs us into the promise land. | ||
return _rsvp.Promise.resolve(null, this.promiseLabel('Start transition')).then(resolveOneRouteInfo, null, this.promiseLabel('Resolve route')).catch(handleError, this.promiseLabel('Handle error')); | ||
function innerShouldContinue() { | ||
return _rsvp.Promise.resolve(shouldContinue(), currentState.promiseLabel('Check if should continue')).catch(function (reason) { | ||
// We distinguish between errors that occurred | ||
// during resolution (e.g. before"Model/model/afterModel), | ||
// and aborts due to a rejecting promise from shouldContinue(). | ||
wasAborted = true; | ||
return _rsvp.Promise.reject(reason); | ||
}, currentState.promiseLabel('Handle abort')); | ||
} | ||
function handleError(error) { | ||
// This is the only possible | ||
// reject value of TransitionState#resolve | ||
var routeInfos = currentState.routeInfos; | ||
var errorHandlerIndex = transition.resolveIndex >= routeInfos.length ? routeInfos.length - 1 : transition.resolveIndex; | ||
return _rsvp.Promise.reject(new TransitionError(error, currentState.routeInfos[errorHandlerIndex].route, wasAborted, currentState)); | ||
} | ||
function proceed(resolvedRouteInfo) { | ||
var wasAlreadyResolved = currentState.routeInfos[transition.resolveIndex].isResolved; | ||
// Swap the previously unresolved routeInfo with | ||
// the resolved routeInfo | ||
currentState.routeInfos[transition.resolveIndex++] = resolvedRouteInfo; | ||
if (!wasAlreadyResolved) { | ||
// Call the redirect hook. The reason we call it here | ||
// vs. afterModel is so that redirects into child | ||
// routes don't re-run the model hooks for this | ||
// already-resolved route. | ||
var route = resolvedRouteInfo.route; | ||
function handleError(error) { | ||
// This is the only possible | ||
// reject value of TransitionState#resolve | ||
let routeInfos = currentState.routeInfos; | ||
let errorHandlerIndex = transition.resolveIndex >= routeInfos.length ? routeInfos.length - 1 : transition.resolveIndex; | ||
return _rsvp.Promise.reject(new TransitionError(error, currentState.routeInfos[errorHandlerIndex].route, wasAborted, currentState)); | ||
} | ||
if (route !== undefined) { | ||
if (route.redirect) { | ||
route.redirect(resolvedRouteInfo.context, transition); | ||
} | ||
} | ||
} | ||
// Proceed after ensuring that the redirect hook | ||
// didn't abort this transition by transitioning elsewhere. | ||
return innerShouldContinue().then(resolveOneRouteInfo, null, currentState.promiseLabel('Resolve route')); | ||
} | ||
function resolveOneRouteInfo() { | ||
if (transition.resolveIndex === currentState.routeInfos.length) { | ||
// This is is the only possible | ||
// fulfill value of TransitionState#resolve | ||
return currentState; | ||
} | ||
var routeInfo = currentState.routeInfos[transition.resolveIndex]; | ||
return routeInfo.resolve(innerShouldContinue, transition).then(proceed, null, currentState.promiseLabel('Proceed')); | ||
} | ||
function proceed(resolvedRouteInfo) { | ||
let wasAlreadyResolved = currentState.routeInfos[transition.resolveIndex].isResolved; // Swap the previously unresolved routeInfo with | ||
// the resolved routeInfo | ||
currentState.routeInfos[transition.resolveIndex++] = resolvedRouteInfo; | ||
if (!wasAlreadyResolved) { | ||
// Call the redirect hook. The reason we call it here | ||
// vs. afterModel is so that redirects into child | ||
// routes don't re-run the model hooks for this | ||
// already-resolved route. | ||
let { | ||
route | ||
} = resolvedRouteInfo; | ||
if (route !== undefined) { | ||
if (route.redirect) { | ||
route.redirect(resolvedRouteInfo.context, transition); | ||
} | ||
} | ||
}]); | ||
} // Proceed after ensuring that the redirect hook | ||
// didn't abort this transition by transitioning elsewhere. | ||
return TransitionState; | ||
}(); | ||
return innerShouldContinue().then(resolveOneRouteInfo, null, currentState.promiseLabel('Resolve route')); | ||
} | ||
function resolveOneRouteInfo() { | ||
if (transition.resolveIndex === currentState.routeInfos.length) { | ||
// This is is the only possible | ||
// fulfill value of TransitionState#resolve | ||
return currentState; | ||
} | ||
let routeInfo = currentState.routeInfos[transition.resolveIndex]; | ||
return routeInfo.resolve(innerShouldContinue, transition).then(proceed, null, currentState.promiseLabel('Proceed')); | ||
} | ||
} | ||
} | ||
exports.default = TransitionState; | ||
var TransitionError = exports.TransitionError = function TransitionError(error, route, wasAborted, state) { | ||
_classCallCheck(this, TransitionError); | ||
class TransitionError { | ||
constructor(error, route, wasAborted, state) { | ||
this.error = error; | ||
@@ -115,3 +113,6 @@ this.route = route; | ||
this.state = state; | ||
}; | ||
//# sourceMappingURL=transition-state.js.map | ||
} | ||
} | ||
exports.TransitionError = TransitionError; |
@@ -208,3 +208,3 @@ import { Promise } from 'rsvp'; | ||
export declare function logAbort(transition: Transition<any>): ITransitionAbortedError; | ||
export declare function isTransition(obj: Dict<unknown> | undefined): obj is typeof Transition; | ||
export declare function isTransition(obj: unknown): obj is typeof Transition; | ||
export declare function prepareResult(obj: Dict<unknown> | undefined): Dict<unknown> | null | undefined; |
@@ -1,29 +0,24 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.QUERY_PARAMS_SYMBOL = exports.PARAMS_SYMBOL = exports.STATE_SYMBOL = undefined; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
exports.logAbort = logAbort; | ||
exports.isTransition = isTransition; | ||
exports.prepareResult = prepareResult; | ||
exports.default = exports.QUERY_PARAMS_SYMBOL = exports.PARAMS_SYMBOL = exports.STATE_SYMBOL = void 0; | ||
var _rsvp = require('rsvp'); | ||
var _rsvp = require("rsvp"); | ||
var _transitionAbortedError = require('./transition-aborted-error'); | ||
var _transitionAbortedError = _interopRequireDefault(require("./transition-aborted-error")); | ||
var _transitionAbortedError2 = _interopRequireDefault(_transitionAbortedError); | ||
var _utils = require("./utils"); | ||
var _utils = require('./utils'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var STATE_SYMBOL = exports.STATE_SYMBOL = `__STATE__-2619860001345920-3322w3`; | ||
var PARAMS_SYMBOL = exports.PARAMS_SYMBOL = `__PARAMS__-261986232992830203-23323`; | ||
var QUERY_PARAMS_SYMBOL = exports.QUERY_PARAMS_SYMBOL = `__QPS__-2619863929824844-32323`; | ||
const STATE_SYMBOL = `__STATE__-2619860001345920-3322w3`; | ||
exports.STATE_SYMBOL = STATE_SYMBOL; | ||
const PARAMS_SYMBOL = `__PARAMS__-261986232992830203-23323`; | ||
exports.PARAMS_SYMBOL = PARAMS_SYMBOL; | ||
const QUERY_PARAMS_SYMBOL = `__QPS__-2619863929824844-32323`; | ||
/** | ||
@@ -45,329 +40,308 @@ A Transition is a thennable (a promise-like object) that represents | ||
var Transition = function () { | ||
function Transition(router, intent, state) { | ||
var _this = this; | ||
exports.QUERY_PARAMS_SYMBOL = QUERY_PARAMS_SYMBOL; | ||
var error = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined; | ||
var previousTransition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : undefined; | ||
class Transition { | ||
constructor(router, intent, state, error = undefined, previousTransition = undefined) { | ||
this.from = null; | ||
this.to = undefined; | ||
this.isAborted = false; | ||
this.isActive = true; | ||
this.urlMethod = 'update'; | ||
this.resolveIndex = 0; | ||
this.queryParamsOnly = false; | ||
this.isTransition = true; | ||
this.isCausedByAbortingTransition = false; | ||
this.isCausedByInitialTransition = false; | ||
this.isCausedByAbortingReplaceTransition = false; | ||
this._visibleQueryParams = {}; | ||
this[STATE_SYMBOL] = state || router.state; | ||
this.intent = intent; | ||
this.router = router; | ||
this.data = intent && intent.data || {}; | ||
this.resolvedModels = {}; | ||
this[QUERY_PARAMS_SYMBOL] = {}; | ||
this.promise = undefined; | ||
this.error = undefined; | ||
this[PARAMS_SYMBOL] = {}; | ||
this.routeInfos = []; | ||
this.targetName = undefined; | ||
this.pivotHandler = undefined; | ||
this.sequence = -1; | ||
_classCallCheck(this, Transition); | ||
if (error) { | ||
this.promise = _rsvp.Promise.reject(error); | ||
this.error = error; | ||
return; | ||
} // if you're doing multiple redirects, need the new transition to know if it | ||
// is actually part of the first transition or not. Any further redirects | ||
// in the initial transition also need to know if they are part of the | ||
// initial transition | ||
this.from = null; | ||
this.to = undefined; | ||
this.isAborted = false; | ||
this.isActive = true; | ||
this.urlMethod = 'update'; | ||
this.resolveIndex = 0; | ||
this.queryParamsOnly = false; | ||
this.isTransition = true; | ||
this.isCausedByAbortingTransition = false; | ||
this.isCausedByInitialTransition = false; | ||
this.isCausedByAbortingReplaceTransition = false; | ||
this._visibleQueryParams = {}; | ||
this[STATE_SYMBOL] = state || router.state; | ||
this.intent = intent; | ||
this.router = router; | ||
this.data = intent && intent.data || {}; | ||
this.resolvedModels = {}; | ||
this[QUERY_PARAMS_SYMBOL] = {}; | ||
this.promise = undefined; | ||
this.error = undefined; | ||
this[PARAMS_SYMBOL] = {}; | ||
this.routeInfos = []; | ||
this.targetName = undefined; | ||
this.pivotHandler = undefined; | ||
this.sequence = -1; | ||
if (error) { | ||
this.promise = _rsvp.Promise.reject(error); | ||
this.error = error; | ||
return; | ||
this.isCausedByAbortingTransition = !!previousTransition; | ||
this.isCausedByInitialTransition = !!previousTransition && (previousTransition.isCausedByInitialTransition || previousTransition.sequence === 0); // Every transition in the chain is a replace | ||
this.isCausedByAbortingReplaceTransition = !!previousTransition && previousTransition.urlMethod === 'replace' && (!previousTransition.isCausedByAbortingTransition || previousTransition.isCausedByAbortingReplaceTransition); | ||
if (state) { | ||
this[PARAMS_SYMBOL] = state.params; | ||
this[QUERY_PARAMS_SYMBOL] = state.queryParams; | ||
this.routeInfos = state.routeInfos; | ||
let len = state.routeInfos.length; | ||
if (len) { | ||
this.targetName = state.routeInfos[len - 1].name; | ||
} | ||
for (let i = 0; i < len; ++i) { | ||
let handlerInfo = state.routeInfos[i]; // TODO: this all seems hacky | ||
if (!handlerInfo.isResolved) { | ||
break; | ||
} | ||
// if you're doing multiple redirects, need the new transition to know if it | ||
// is actually part of the first transition or not. Any further redirects | ||
// in the initial transition also need to know if they are part of the | ||
// initial transition | ||
this.isCausedByAbortingTransition = !!previousTransition; | ||
this.isCausedByInitialTransition = !!previousTransition && (previousTransition.isCausedByInitialTransition || previousTransition.sequence === 0); | ||
// Every transition in the chain is a replace | ||
this.isCausedByAbortingReplaceTransition = !!previousTransition && previousTransition.urlMethod === 'replace' && (!previousTransition.isCausedByAbortingTransition || previousTransition.isCausedByAbortingReplaceTransition); | ||
if (state) { | ||
this[PARAMS_SYMBOL] = state.params; | ||
this[QUERY_PARAMS_SYMBOL] = state.queryParams; | ||
this.routeInfos = state.routeInfos; | ||
var len = state.routeInfos.length; | ||
if (len) { | ||
this.targetName = state.routeInfos[len - 1].name; | ||
} | ||
for (var i = 0; i < len; ++i) { | ||
var handlerInfo = state.routeInfos[i]; | ||
// TODO: this all seems hacky | ||
if (!handlerInfo.isResolved) { | ||
break; | ||
} | ||
this.pivotHandler = handlerInfo.route; | ||
} | ||
this.sequence = router.currentSequence++; | ||
this.promise = state.resolve(function () { | ||
if (_this.isAborted) { | ||
return _rsvp.Promise.reject(false, (0, _utils.promiseLabel)('Transition aborted - reject')); | ||
} | ||
return _rsvp.Promise.resolve(true); | ||
}, this).catch(function (result) { | ||
return _rsvp.Promise.reject(_this.router.transitionDidError(result, _this)); | ||
}, (0, _utils.promiseLabel)('Handle Abort')); | ||
} else { | ||
this.promise = _rsvp.Promise.resolve(this[STATE_SYMBOL]); | ||
this[PARAMS_SYMBOL] = {}; | ||
this.pivotHandler = handlerInfo.route; | ||
} | ||
this.sequence = router.currentSequence++; | ||
this.promise = state.resolve(() => { | ||
if (this.isAborted) { | ||
return _rsvp.Promise.reject(false, (0, _utils.promiseLabel)('Transition aborted - reject')); | ||
} | ||
return _rsvp.Promise.resolve(true); | ||
}, this).catch(result => { | ||
return _rsvp.Promise.reject(this.router.transitionDidError(result, this)); | ||
}, (0, _utils.promiseLabel)('Handle Abort')); | ||
} else { | ||
this.promise = _rsvp.Promise.resolve(this[STATE_SYMBOL]); | ||
this[PARAMS_SYMBOL] = {}; | ||
} | ||
/** | ||
The Transition's internal promise. Calling `.then` on this property | ||
is that same as calling `.then` on the Transition object itself, but | ||
this property is exposed for when you want to pass around a | ||
Transition's promise, but not the Transition object itself, since | ||
Transition object can be externally `abort`ed, while the promise | ||
cannot. | ||
@property promise | ||
@type {Object} | ||
@public | ||
*/ | ||
/** | ||
Custom state can be stored on a Transition's `data` object. | ||
This can be useful for decorating a Transition within an earlier | ||
hook and shared with a later hook. Properties set on `data` will | ||
be copied to new transitions generated by calling `retry` on this | ||
transition. | ||
@property data | ||
@type {Object} | ||
@public | ||
*/ | ||
/** | ||
A standard promise hook that resolves if the transition | ||
succeeds and rejects if it fails/redirects/aborts. | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
but not the Transition itself. | ||
@method then | ||
@param {Function} onFulfilled | ||
@param {Function} onRejected | ||
@param {String} label optional string for labeling the promise. | ||
Useful for tooling. | ||
@return {Promise} | ||
@public | ||
*/ | ||
} | ||
/** | ||
The Transition's internal promise. Calling `.then` on this property | ||
is that same as calling `.then` on the Transition object itself, but | ||
this property is exposed for when you want to pass around a | ||
Transition's promise, but not the Transition object itself, since | ||
Transition object can be externally `abort`ed, while the promise | ||
cannot. | ||
@property promise | ||
@type {Object} | ||
@public | ||
*/ | ||
/** | ||
Custom state can be stored on a Transition's `data` object. | ||
This can be useful for decorating a Transition within an earlier | ||
hook and shared with a later hook. Properties set on `data` will | ||
be copied to new transitions generated by calling `retry` on this | ||
transition. | ||
@property data | ||
@type {Object} | ||
@public | ||
*/ | ||
_createClass(Transition, [{ | ||
key: 'then', | ||
value: function then(onFulfilled, onRejected, label) { | ||
return this.promise.then(onFulfilled, onRejected, label); | ||
} | ||
/** | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
but not the Transition itself. | ||
@method catch | ||
@param {Function} onRejection | ||
@param {String} label optional string for labeling the promise. | ||
Useful for tooling. | ||
@return {Promise} | ||
@public | ||
*/ | ||
/** | ||
A standard promise hook that resolves if the transition | ||
succeeds and rejects if it fails/redirects/aborts. | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
but not the Transition itself. | ||
@method then | ||
@param {Function} onFulfilled | ||
@param {Function} onRejected | ||
@param {String} label optional string for labeling the promise. | ||
Useful for tooling. | ||
@return {Promise} | ||
@public | ||
*/ | ||
}, { | ||
key: 'catch', | ||
value: function _catch(onRejection, label) { | ||
return this.promise.catch(onRejection, label); | ||
} | ||
/** | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
but not the Transition itself. | ||
@method finally | ||
@param {Function} callback | ||
@param {String} label optional string for labeling the promise. | ||
Useful for tooling. | ||
@return {Promise} | ||
@public | ||
*/ | ||
}, { | ||
key: 'finally', | ||
value: function _finally(callback, label) { | ||
return this.promise.finally(callback, label); | ||
} | ||
/** | ||
Aborts the Transition. Note you can also implicitly abort a transition | ||
by initiating another transition while a previous one is underway. | ||
@method abort | ||
@return {Transition} this transition | ||
@public | ||
*/ | ||
then(onFulfilled, onRejected, label) { | ||
return this.promise.then(onFulfilled, onRejected, label); | ||
} | ||
/** | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
but not the Transition itself. | ||
@method catch | ||
@param {Function} onRejection | ||
@param {String} label optional string for labeling the promise. | ||
Useful for tooling. | ||
@return {Promise} | ||
@public | ||
*/ | ||
}, { | ||
key: 'abort', | ||
value: function abort() { | ||
this.rollback(); | ||
var transition = new Transition(this.router, undefined, undefined, undefined); | ||
transition.to = this.from; | ||
transition.from = this.from; | ||
transition.isAborted = true; | ||
this.router.routeWillChange(transition); | ||
this.router.routeDidChange(transition); | ||
return this; | ||
} | ||
}, { | ||
key: 'rollback', | ||
value: function rollback() { | ||
if (!this.isAborted) { | ||
(0, _utils.log)(this.router, this.sequence, this.targetName + ': transition was aborted'); | ||
if (this.intent !== undefined && this.intent !== null) { | ||
this.intent.preTransitionState = this.router.state; | ||
} | ||
this.isAborted = true; | ||
this.isActive = false; | ||
this.router.activeTransition = undefined; | ||
} | ||
} | ||
}, { | ||
key: 'redirect', | ||
value: function redirect(newTransition) { | ||
this.rollback(); | ||
this.router.routeWillChange(newTransition); | ||
} | ||
/** | ||
Retries a previously-aborted transition (making sure to abort the | ||
transition if it's still active). Returns a new transition that | ||
represents the new attempt to transition. | ||
@method retry | ||
@return {Transition} new transition | ||
@public | ||
*/ | ||
}, { | ||
key: 'retry', | ||
value: function retry() { | ||
// TODO: add tests for merged state retry()s | ||
this.abort(); | ||
var newTransition = this.router.transitionByIntent(this.intent, false); | ||
// inheriting a `null` urlMethod is not valid | ||
// the urlMethod is only set to `null` when | ||
// the transition is initiated *after* the url | ||
// has been updated (i.e. `router.handleURL`) | ||
// | ||
// in that scenario, the url method cannot be | ||
// inherited for a new transition because then | ||
// the url would not update even though it should | ||
if (this.urlMethod !== null) { | ||
newTransition.method(this.urlMethod); | ||
} | ||
return newTransition; | ||
} | ||
/** | ||
Sets the URL-changing method to be employed at the end of a | ||
successful transition. By default, a new Transition will just | ||
use `updateURL`, but passing 'replace' to this method will | ||
cause the URL to update using 'replaceWith' instead. Omitting | ||
a parameter will disable the URL change, allowing for transitions | ||
that don't update the URL at completion (this is also used for | ||
handleURL, since the URL has already changed before the | ||
transition took place). | ||
@method method | ||
@param {String} method the type of URL-changing method to use | ||
at the end of a transition. Accepted values are 'replace', | ||
falsy values, or any other non-falsy value (which is | ||
interpreted as an updateURL transition). | ||
@return {Transition} this transition | ||
@public | ||
*/ | ||
catch(onRejection, label) { | ||
return this.promise.catch(onRejection, label); | ||
} | ||
/** | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
but not the Transition itself. | ||
@method finally | ||
@param {Function} callback | ||
@param {String} label optional string for labeling the promise. | ||
Useful for tooling. | ||
@return {Promise} | ||
@public | ||
*/ | ||
}, { | ||
key: 'method', | ||
value: function method(_method) { | ||
this.urlMethod = _method; | ||
return this; | ||
} | ||
// Alias 'trigger' as 'send' | ||
}, { | ||
key: 'send', | ||
value: function send() { | ||
var ignoreFailure = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; | ||
var _name = arguments[1]; | ||
var err = arguments[2]; | ||
var transition = arguments[3]; | ||
var handler = arguments[4]; | ||
finally(callback, label) { | ||
return this.promise.finally(callback, label); | ||
} | ||
/** | ||
Aborts the Transition. Note you can also implicitly abort a transition | ||
by initiating another transition while a previous one is underway. | ||
@method abort | ||
@return {Transition} this transition | ||
@public | ||
*/ | ||
this.trigger(ignoreFailure, _name, err, transition, handler); | ||
} | ||
/** | ||
Fires an event on the current list of resolved/resolving | ||
handlers within this transition. Useful for firing events | ||
on route hierarchies that haven't fully been entered yet. | ||
Note: This method is also aliased as `send` | ||
@method trigger | ||
@param {Boolean} [ignoreFailure=false] a boolean specifying whether unhandled events throw an error | ||
@param {String} name the name of the event to fire | ||
@public | ||
*/ | ||
}, { | ||
key: 'trigger', | ||
value: function trigger() { | ||
var ignoreFailure = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; | ||
var name = arguments[1]; | ||
abort() { | ||
this.rollback(); | ||
let transition = new Transition(this.router, undefined, undefined, undefined); | ||
transition.to = this.from; | ||
transition.from = this.from; | ||
transition.isAborted = true; | ||
this.router.routeWillChange(transition); | ||
this.router.routeDidChange(transition); | ||
return this; | ||
} | ||
// TODO: Deprecate the current signature | ||
if (typeof ignoreFailure === 'string') { | ||
name = ignoreFailure; | ||
ignoreFailure = false; | ||
} | ||
rollback() { | ||
if (!this.isAborted) { | ||
(0, _utils.log)(this.router, this.sequence, this.targetName + ': transition was aborted'); | ||
for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { | ||
args[_key - 2] = arguments[_key]; | ||
} | ||
if (this.intent !== undefined && this.intent !== null) { | ||
this.intent.preTransitionState = this.router.state; | ||
} | ||
this.router.triggerEvent(this[STATE_SYMBOL].routeInfos.slice(0, this.resolveIndex + 1), ignoreFailure, name, args); | ||
} | ||
/** | ||
Transitions are aborted and their promises rejected | ||
when redirects occur; this method returns a promise | ||
that will follow any redirects that occur and fulfill | ||
with the value fulfilled by any redirecting transitions | ||
that occur. | ||
@method followRedirects | ||
@return {Promise} a promise that fulfills with the same | ||
value that the final redirecting transition fulfills with | ||
@public | ||
*/ | ||
this.isAborted = true; | ||
this.isActive = false; | ||
this.router.activeTransition = undefined; | ||
} | ||
} | ||
}, { | ||
key: 'followRedirects', | ||
value: function followRedirects() { | ||
var router = this.router; | ||
return this.promise.catch(function (reason) { | ||
if (router.activeTransition) { | ||
return router.activeTransition.followRedirects(); | ||
} | ||
return _rsvp.Promise.reject(reason); | ||
}); | ||
} | ||
}, { | ||
key: 'toString', | ||
value: function toString() { | ||
return 'Transition (sequence ' + this.sequence + ')'; | ||
} | ||
/** | ||
@private | ||
*/ | ||
redirect(newTransition) { | ||
this.rollback(); | ||
this.router.routeWillChange(newTransition); | ||
} | ||
/** | ||
Retries a previously-aborted transition (making sure to abort the | ||
transition if it's still active). Returns a new transition that | ||
represents the new attempt to transition. | ||
@method retry | ||
@return {Transition} new transition | ||
@public | ||
*/ | ||
}, { | ||
key: 'log', | ||
value: function log(message) { | ||
(0, _utils.log)(this.router, this.sequence, message); | ||
} | ||
}]); | ||
return Transition; | ||
}(); | ||
retry() { | ||
// TODO: add tests for merged state retry()s | ||
this.abort(); | ||
let newTransition = this.router.transitionByIntent(this.intent, false); // inheriting a `null` urlMethod is not valid | ||
// the urlMethod is only set to `null` when | ||
// the transition is initiated *after* the url | ||
// has been updated (i.e. `router.handleURL`) | ||
// | ||
// in that scenario, the url method cannot be | ||
// inherited for a new transition because then | ||
// the url would not update even though it should | ||
if (this.urlMethod !== null) { | ||
newTransition.method(this.urlMethod); | ||
} | ||
return newTransition; | ||
} | ||
/** | ||
Sets the URL-changing method to be employed at the end of a | ||
successful transition. By default, a new Transition will just | ||
use `updateURL`, but passing 'replace' to this method will | ||
cause the URL to update using 'replaceWith' instead. Omitting | ||
a parameter will disable the URL change, allowing for transitions | ||
that don't update the URL at completion (this is also used for | ||
handleURL, since the URL has already changed before the | ||
transition took place). | ||
@method method | ||
@param {String} method the type of URL-changing method to use | ||
at the end of a transition. Accepted values are 'replace', | ||
falsy values, or any other non-falsy value (which is | ||
interpreted as an updateURL transition). | ||
@return {Transition} this transition | ||
@public | ||
*/ | ||
method(method) { | ||
this.urlMethod = method; | ||
return this; | ||
} // Alias 'trigger' as 'send' | ||
send(ignoreFailure = false, _name, err, transition, handler) { | ||
this.trigger(ignoreFailure, _name, err, transition, handler); | ||
} | ||
/** | ||
Fires an event on the current list of resolved/resolving | ||
handlers within this transition. Useful for firing events | ||
on route hierarchies that haven't fully been entered yet. | ||
Note: This method is also aliased as `send` | ||
@method trigger | ||
@param {Boolean} [ignoreFailure=false] a boolean specifying whether unhandled events throw an error | ||
@param {String} name the name of the event to fire | ||
@public | ||
*/ | ||
trigger(ignoreFailure = false, name, ...args) { | ||
// TODO: Deprecate the current signature | ||
if (typeof ignoreFailure === 'string') { | ||
name = ignoreFailure; | ||
ignoreFailure = false; | ||
} | ||
this.router.triggerEvent(this[STATE_SYMBOL].routeInfos.slice(0, this.resolveIndex + 1), ignoreFailure, name, args); | ||
} | ||
/** | ||
Transitions are aborted and their promises rejected | ||
when redirects occur; this method returns a promise | ||
that will follow any redirects that occur and fulfill | ||
with the value fulfilled by any redirecting transitions | ||
that occur. | ||
@method followRedirects | ||
@return {Promise} a promise that fulfills with the same | ||
value that the final redirecting transition fulfills with | ||
@public | ||
*/ | ||
followRedirects() { | ||
let router = this.router; | ||
return this.promise.catch(function (reason) { | ||
if (router.activeTransition) { | ||
return router.activeTransition.followRedirects(); | ||
} | ||
return _rsvp.Promise.reject(reason); | ||
}); | ||
} | ||
toString() { | ||
return 'Transition (sequence ' + this.sequence + ')'; | ||
} | ||
/** | ||
@private | ||
*/ | ||
log(message) { | ||
(0, _utils.log)(this.router, this.sequence, message); | ||
} | ||
} | ||
/** | ||
@@ -381,15 +355,18 @@ @private | ||
exports.default = Transition; | ||
function logAbort(transition) { | ||
(0, _utils.log)(transition.router, transition.sequence, 'detected abort.'); | ||
return new _transitionAbortedError2.default(); | ||
(0, _utils.log)(transition.router, transition.sequence, 'detected abort.'); | ||
return new _transitionAbortedError.default(); | ||
} | ||
function isTransition(obj) { | ||
return typeof obj === 'object' && obj instanceof Transition && obj.isTransition; | ||
return typeof obj === 'object' && obj instanceof Transition && obj.isTransition; | ||
} | ||
function prepareResult(obj) { | ||
if (isTransition(obj)) { | ||
return null; | ||
} | ||
return obj; | ||
} | ||
//# sourceMappingURL=transition.js.map | ||
if (isTransition(obj)) { | ||
return null; | ||
} | ||
return obj; | ||
} |
@@ -1,22 +0,28 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
var UnrecognizedURLError = function () { | ||
UnrecognizedURLError.prototype = Object.create(Error.prototype); | ||
UnrecognizedURLError.prototype.constructor = UnrecognizedURLError; | ||
function UnrecognizedURLError(message) { | ||
var error = Error.call(this, message); | ||
this.name = 'UnrecognizedURLError'; | ||
this.message = message || 'UnrecognizedURL'; | ||
if (Error.captureStackTrace) { | ||
Error.captureStackTrace(this, UnrecognizedURLError); | ||
} else { | ||
this.stack = error.stack; | ||
} | ||
exports.default = void 0; | ||
const UnrecognizedURLError = function () { | ||
UnrecognizedURLError.prototype = Object.create(Error.prototype); | ||
UnrecognizedURLError.prototype.constructor = UnrecognizedURLError; | ||
function UnrecognizedURLError(message) { | ||
let error = Error.call(this, message); | ||
this.name = 'UnrecognizedURLError'; | ||
this.message = message || 'UnrecognizedURL'; | ||
if (Error.captureStackTrace) { | ||
Error.captureStackTrace(this, UnrecognizedURLError); | ||
} else { | ||
this.stack = error.stack; | ||
} | ||
return UnrecognizedURLError; | ||
} | ||
return UnrecognizedURLError; | ||
}(); | ||
exports.default = UnrecognizedURLError; | ||
//# sourceMappingURL=unrecognized-url-error.js.map | ||
var _default = UnrecognizedURLError; | ||
exports.default = _default; |
@@ -9,3 +9,3 @@ import { Promise } from 'rsvp'; | ||
export declare function isPromise<T>(p: any): p is Promise<T>; | ||
export declare function merge(hash: Dict<unknown>, other: Dict<unknown>): void; | ||
export declare function merge(hash: Dict<unknown>, other?: Dict<unknown>): void; | ||
/** | ||
@@ -16,3 +16,3 @@ @private | ||
**/ | ||
export declare function extractQueryParams(array: unknown[]): any[]; | ||
export declare function extractQueryParams<T>(array: T[]): [T[], Dict<unknown> | null]; | ||
/** | ||
@@ -28,3 +28,3 @@ @private | ||
export declare function log(router: Router<any>, ...args: (string | number)[]): void; | ||
export declare function isParam(object: Dict<unknown>): boolean; | ||
export declare function isParam(object: any): object is string | number; | ||
export declare function forEach<T>(array: T[], callback: (item: T) => boolean): void; | ||
@@ -31,0 +31,0 @@ export interface ChangeList { |
@@ -1,5 +0,5 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
@@ -15,16 +15,20 @@ exports.isPromise = isPromise; | ||
exports.promiseLabel = promiseLabel; | ||
var slice = exports.slice = Array.prototype.slice; | ||
var hasOwnProperty = Object.prototype.hasOwnProperty; | ||
exports.slice = void 0; | ||
const slice = Array.prototype.slice; | ||
exports.slice = slice; | ||
const hasOwnProperty = Object.prototype.hasOwnProperty; | ||
/** | ||
Determines if an object is Promise by checking if it is "thenable". | ||
**/ | ||
function isPromise(p) { | ||
return p !== null && typeof p === 'object' && typeof p.then === 'function'; | ||
return p !== null && typeof p === 'object' && typeof p.then === 'function'; | ||
} | ||
function merge(hash, other) { | ||
for (var prop in other) { | ||
if (hasOwnProperty.call(other, prop)) { | ||
hash[prop] = other[prop]; | ||
} | ||
for (let prop in other) { | ||
if (hasOwnProperty.call(other, prop)) { | ||
hash[prop] = other[prop]; | ||
} | ||
} | ||
} | ||
@@ -36,18 +40,24 @@ /** | ||
**/ | ||
function extractQueryParams(array) { | ||
var len = array && array.length, | ||
head = void 0, | ||
queryParams = void 0; | ||
if (len && len > 0) { | ||
var obj = array[len - 1]; | ||
if (isQueryParams(obj)) { | ||
queryParams = obj.queryParams; | ||
head = slice.call(array, 0, len - 1); | ||
return [head, queryParams]; | ||
} | ||
let len = array && array.length, | ||
head, | ||
queryParams; | ||
if (len && len > 0) { | ||
let obj = array[len - 1]; | ||
if (isQueryParams(obj)) { | ||
queryParams = obj.queryParams; | ||
head = slice.call(array, 0, len - 1); | ||
return [head, queryParams]; | ||
} | ||
return [array, null]; | ||
} | ||
return [array, null]; | ||
} | ||
function isQueryParams(obj) { | ||
return obj && hasOwnProperty.call(obj, 'queryParams'); | ||
return obj && hasOwnProperty.call(obj, 'queryParams'); | ||
} | ||
@@ -59,13 +69,16 @@ /** | ||
**/ | ||
function coerceQueryParamsToString(queryParams) { | ||
for (var key in queryParams) { | ||
var val = queryParams[key]; | ||
if (typeof val === 'number') { | ||
queryParams[key] = '' + val; | ||
} else if (Array.isArray(val)) { | ||
for (var i = 0, l = val.length; i < l; i++) { | ||
val[i] = '' + val[i]; | ||
} | ||
} | ||
for (let key in queryParams) { | ||
let val = queryParams[key]; | ||
if (typeof val === 'number') { | ||
queryParams[key] = '' + val; | ||
} else if (Array.isArray(val)) { | ||
for (let i = 0, l = val.length; i < l; i++) { | ||
val[i] = '' + val[i]; | ||
} | ||
} | ||
} | ||
} | ||
@@ -75,81 +88,82 @@ /** | ||
*/ | ||
function log(router) { | ||
if (!router.log) { | ||
return; | ||
} | ||
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
args[_key - 1] = arguments[_key]; | ||
} | ||
if (args.length === 2) { | ||
var sequence = args[0], | ||
msg = args[1]; | ||
function log(router, ...args) { | ||
if (!router.log) { | ||
return; | ||
} | ||
router.log('Transition #' + sequence + ': ' + msg); | ||
} else { | ||
var _msg = args[0]; | ||
if (args.length === 2) { | ||
let [sequence, msg] = args; | ||
router.log('Transition #' + sequence + ': ' + msg); | ||
} else { | ||
let [msg] = args; | ||
router.log(msg); | ||
} | ||
} | ||
router.log(_msg); | ||
} | ||
} | ||
function isParam(object) { | ||
return typeof object === 'string' || object instanceof String || typeof object === 'number' || object instanceof Number; | ||
return typeof object === 'string' || object instanceof String || typeof object === 'number' || object instanceof Number; | ||
} | ||
function forEach(array, callback) { | ||
for (var i = 0, l = array.length; i < l && callback(array[i]) !== false; i++) { | ||
// empty intentionally | ||
} | ||
for (let i = 0, l = array.length; i < l && callback(array[i]) !== false; i++) {// empty intentionally | ||
} | ||
} | ||
function getChangelist(oldObject, newObject) { | ||
var key = void 0; | ||
var results = { | ||
all: {}, | ||
changed: {}, | ||
removed: {} | ||
}; | ||
merge(results.all, newObject); | ||
var didChange = false; | ||
coerceQueryParamsToString(oldObject); | ||
coerceQueryParamsToString(newObject); | ||
// Calculate removals | ||
for (key in oldObject) { | ||
if (hasOwnProperty.call(oldObject, key)) { | ||
if (!hasOwnProperty.call(newObject, key)) { | ||
didChange = true; | ||
results.removed[key] = oldObject[key]; | ||
} | ||
} | ||
let key; | ||
let results = { | ||
all: {}, | ||
changed: {}, | ||
removed: {} | ||
}; | ||
merge(results.all, newObject); | ||
let didChange = false; | ||
coerceQueryParamsToString(oldObject); | ||
coerceQueryParamsToString(newObject); // Calculate removals | ||
for (key in oldObject) { | ||
if (hasOwnProperty.call(oldObject, key)) { | ||
if (!hasOwnProperty.call(newObject, key)) { | ||
didChange = true; | ||
results.removed[key] = oldObject[key]; | ||
} | ||
} | ||
// Calculate changes | ||
for (key in newObject) { | ||
if (hasOwnProperty.call(newObject, key)) { | ||
var oldElement = oldObject[key]; | ||
var newElement = newObject[key]; | ||
if (isArray(oldElement) && isArray(newElement)) { | ||
if (oldElement.length !== newElement.length) { | ||
results.changed[key] = newObject[key]; | ||
didChange = true; | ||
} else { | ||
for (var i = 0, l = oldElement.length; i < l; i++) { | ||
if (oldElement[i] !== newElement[i]) { | ||
results.changed[key] = newObject[key]; | ||
didChange = true; | ||
} | ||
} | ||
} | ||
} else if (oldObject[key] !== newObject[key]) { | ||
results.changed[key] = newObject[key]; | ||
didChange = true; | ||
} // Calculate changes | ||
for (key in newObject) { | ||
if (hasOwnProperty.call(newObject, key)) { | ||
let oldElement = oldObject[key]; | ||
let newElement = newObject[key]; | ||
if (isArray(oldElement) && isArray(newElement)) { | ||
if (oldElement.length !== newElement.length) { | ||
results.changed[key] = newObject[key]; | ||
didChange = true; | ||
} else { | ||
for (let i = 0, l = oldElement.length; i < l; i++) { | ||
if (oldElement[i] !== newElement[i]) { | ||
results.changed[key] = newObject[key]; | ||
didChange = true; | ||
} | ||
} | ||
} | ||
} else if (oldObject[key] !== newObject[key]) { | ||
results.changed[key] = newObject[key]; | ||
didChange = true; | ||
} | ||
} | ||
return didChange ? results : undefined; | ||
} | ||
return didChange ? results : undefined; | ||
} | ||
function isArray(obj) { | ||
return Array.isArray(obj); | ||
return Array.isArray(obj); | ||
} | ||
function promiseLabel(label) { | ||
return 'Router: ' + label; | ||
} | ||
//# sourceMappingURL=utils.js.map | ||
return 'Router: ' + label; | ||
} |
@@ -16,6 +16,6 @@ import { Promise } from 'rsvp'; | ||
deserialize?(params: Dict<unknown>, transition: Transition): Dict<unknown>; | ||
serialize?(model: {}, params: string[]): {} | undefined; | ||
serialize?(model: {}, params: string[]): Dict<unknown> | undefined; | ||
beforeModel?(transition: Transition): Promise<any> | any; | ||
afterModel?(resolvedModel: any, transition: Transition): Promise<any> | any; | ||
setup?(context: Dict<unknown>, transition: Transition): void; | ||
setup?(context: Dict<unknown> | PromiseLike<Dict<unknown> | null | undefined>, transition: Transition): void; | ||
enter?(transition: Transition): void; | ||
@@ -52,12 +52,14 @@ exit?(transition?: Transition): void; | ||
queryParams?: Dict<unknown>; | ||
context?: Dict<unknown>; | ||
context?: Dict<unknown> | PromiseLike<Dict<unknown> | null | undefined> | null; | ||
isResolved: boolean; | ||
constructor(router: Router<T>, name: string, paramNames: string[], route?: T); | ||
getModel(_transition: InternalTransition<T>): Promise<Dict<unknown> | undefined>; | ||
serialize(_context?: Dict<unknown>): Dict<unknown>; | ||
getModel(_transition: InternalTransition<T>): Promise<Dict<unknown> | null | undefined>; | ||
serialize(_context?: Dict<unknown>): Dict<unknown> | undefined; | ||
resolve(shouldContinue: Continuation, transition: InternalTransition<T>): Promise<ResolvedRouteInfo<T>>; | ||
becomeResolved(transition: InternalTransition<T> | null, resolvedContext: Dict<unknown>): ResolvedRouteInfo<T>; | ||
shouldSupercede(routeInfo?: InternalRouteInfo<T>): boolean; | ||
route: T | undefined; | ||
routePromise: Promise<T>; | ||
get route(): T | undefined; | ||
set route(route: T | undefined); | ||
get routePromise(): Promise<T>; | ||
set routePromise(routePromise: Promise<T>); | ||
protected log(transition: InternalTransition<T>, message: string): void; | ||
@@ -80,8 +82,8 @@ private updateRoute; | ||
constructor(router: Router<T>, name: string, paramNames: string[], params: Dict<unknown>, route?: T); | ||
getModel(transition: InternalTransition<T>): Promise<Dict<unknown> | undefined>; | ||
getModel(transition: InternalTransition<T>): Promise<Dict<unknown> | null | undefined>; | ||
} | ||
export declare class UnresolvedRouteInfoByObject<T extends Route> extends InternalRouteInfo<T> { | ||
serializer?: SerializerFunc; | ||
constructor(router: Router<T>, name: string, paramNames: string[], context: Dict<unknown>); | ||
getModel(transition: InternalTransition<T>): Promise<Dict<unknown> | undefined>; | ||
constructor(router: Router<T>, name: string, paramNames: string[], context: Dict<unknown> | PromiseLike<Dict<unknown>>); | ||
getModel(transition: InternalTransition<T>): Promise<Dict<unknown> | null | undefined>; | ||
/** | ||
@@ -96,4 +98,4 @@ @private | ||
*/ | ||
serialize(model?: IModel): any; | ||
serialize(model?: IModel): Dict<unknown> | undefined; | ||
} | ||
export {}; |
@@ -20,3 +20,3 @@ import { Promise } from 'rsvp'; | ||
if (predicate.length === 3) { | ||
arr = routeInfos.map(info => ROUTE_INFOS.get(info)); | ||
arr = routeInfos.map((info) => ROUTE_INFOS.get(info)); | ||
} | ||
@@ -125,5 +125,5 @@ for (let i = 0; routeInfos.length > i; i++) { | ||
.then(() => this.getModel(transition)) | ||
.then(resolvedModel => this.checkForAbort(shouldContinue, resolvedModel)) | ||
.then(resolvedModel => this.runAfterModelHook(transition, resolvedModel)) | ||
.then(resolvedModel => this.becomeResolved(transition, resolvedModel)); | ||
.then((resolvedModel) => this.checkForAbort(shouldContinue, resolvedModel)) | ||
.then((resolvedModel) => this.runAfterModelHook(transition, resolvedModel)) | ||
.then((resolvedModel) => this.becomeResolved(transition, resolvedModel)); | ||
} | ||
@@ -250,3 +250,3 @@ becomeResolved(transition, resolvedContext) { | ||
if (isPromise(route)) { | ||
this.routePromise = this.routePromise.then(r => { | ||
this.routePromise = this.routePromise.then((r) => { | ||
return this.updateRoute(r); | ||
@@ -292,3 +292,3 @@ }); | ||
let route = this.route; | ||
let result = undefined; | ||
let result; | ||
if (route.deserialize) { | ||
@@ -295,0 +295,0 @@ result = route.deserialize(fullParams, transition); |
@@ -10,3 +10,3 @@ import RouteRecognizer, { MatchCallback } from 'route-recognizer'; | ||
export interface SerializerFunc { | ||
(model: {}, params: string[]): unknown; | ||
(model: {}, params: string[]): Dict<unknown>; | ||
} | ||
@@ -228,5 +228,5 @@ export interface ParsedHandler { | ||
*/ | ||
generate(routeName: string, ...args: any[]): string; | ||
generate(routeName: string, ...args: unknown[]): string; | ||
applyIntent(routeName: string, contexts: Dict<unknown>[]): TransitionState<T>; | ||
isActiveIntent(routeName: string, contexts: any[], queryParams?: Dict<unknown>, _state?: TransitionState<T>): boolean; | ||
isActiveIntent(routeName: string, contexts: unknown[], queryParams?: Dict<unknown> | null, _state?: TransitionState<T>): boolean; | ||
isActive(routeName: string, ...args: unknown[]): boolean; | ||
@@ -233,0 +233,0 @@ trigger(name: string, ...args: any[]): void; |
@@ -9,11 +9,11 @@ import { Dict } from '../core'; | ||
pivotHandler?: Route; | ||
contexts: Dict<unknown>[]; | ||
contexts: unknown[]; | ||
queryParams: Dict<unknown>; | ||
preTransitionState?: TransitionState<T>; | ||
constructor(router: Router<T>, name: string, pivotHandler: Route | undefined, contexts?: Dict<unknown>[], queryParams?: Dict<unknown>, data?: {}); | ||
constructor(router: Router<T>, name: string, pivotHandler: Route | undefined, contexts?: unknown[], queryParams?: Dict<unknown>, data?: {}); | ||
applyToState(oldState: TransitionState<T>, isIntermediate: boolean): TransitionState<T>; | ||
applyToHandlers(oldState: TransitionState<T>, parsedHandlers: ParsedHandler[], targetRouteName: string, isIntermediate: boolean, checkingIfActive: boolean): TransitionState<T>; | ||
invalidateChildren(handlerInfos: InternalRouteInfo<T>[], invalidateIndex: number): void; | ||
getHandlerInfoForDynamicSegment(name: string, names: string[], objects: Dict<unknown>[], oldHandlerInfo: InternalRouteInfo<T>, _targetRouteName: string, i: number): InternalRouteInfo<T> | UnresolvedRouteInfoByObject<T>; | ||
createParamHandlerInfo(name: string, names: string[], objects: Dict<unknown>[], oldHandlerInfo: InternalRouteInfo<T>): UnresolvedRouteInfoByParam<T>; | ||
getHandlerInfoForDynamicSegment(name: string, names: string[], objects: unknown[], oldHandlerInfo: InternalRouteInfo<T>, _targetRouteName: string, i: number): InternalRouteInfo<T> | UnresolvedRouteInfoByObject<T>; | ||
createParamHandlerInfo(name: string, names: string[], objects: unknown[], oldHandlerInfo: InternalRouteInfo<T>): UnresolvedRouteInfoByParam<T>; | ||
} |
@@ -24,3 +24,3 @@ import { Promise } from 'rsvp'; | ||
let params = this.params; | ||
forEach(this.routeInfos, routeInfo => { | ||
forEach(this.routeInfos, (routeInfo) => { | ||
params[routeInfo.name] = routeInfo.params || {}; | ||
@@ -27,0 +27,0 @@ return true; |
@@ -208,3 +208,3 @@ import { Promise } from 'rsvp'; | ||
export declare function logAbort(transition: Transition<any>): ITransitionAbortedError; | ||
export declare function isTransition(obj: Dict<unknown> | undefined): obj is typeof Transition; | ||
export declare function isTransition(obj: unknown): obj is typeof Transition; | ||
export declare function prepareResult(obj: Dict<unknown> | undefined): Dict<unknown> | null | undefined; |
@@ -65,5 +65,5 @@ import { Promise } from 'rsvp'; | ||
!!previousTransition && | ||
(previousTransition.urlMethod === 'replace' && | ||
(!previousTransition.isCausedByAbortingTransition || | ||
previousTransition.isCausedByAbortingReplaceTransition)); | ||
previousTransition.urlMethod === 'replace' && | ||
(!previousTransition.isCausedByAbortingTransition || | ||
previousTransition.isCausedByAbortingReplaceTransition); | ||
if (state) { | ||
@@ -70,0 +70,0 @@ this[PARAMS_SYMBOL] = state.params; |
@@ -9,3 +9,3 @@ import { Promise } from 'rsvp'; | ||
export declare function isPromise<T>(p: any): p is Promise<T>; | ||
export declare function merge(hash: Dict<unknown>, other: Dict<unknown>): void; | ||
export declare function merge(hash: Dict<unknown>, other?: Dict<unknown>): void; | ||
/** | ||
@@ -16,3 +16,3 @@ @private | ||
**/ | ||
export declare function extractQueryParams(array: unknown[]): any[]; | ||
export declare function extractQueryParams<T>(array: T[]): [T[], Dict<unknown> | null]; | ||
/** | ||
@@ -28,3 +28,3 @@ @private | ||
export declare function log(router: Router<any>, ...args: (string | number)[]): void; | ||
export declare function isParam(object: Dict<unknown>): boolean; | ||
export declare function isParam(object: any): object is string | number; | ||
export declare function forEach<T>(array: T[], callback: (item: T) => boolean): void; | ||
@@ -31,0 +31,0 @@ export interface ChangeList { |
{ | ||
"name": "router_js", | ||
"version": "6.2.6", | ||
"version": "7.0.0", | ||
"description": "A lightweight JavaScript library is built on top of route-recognizer and rsvp.js to provide an API for handling routes", | ||
@@ -13,2 +13,6 @@ "keywords": [ | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/tildeio/router.js.git" | ||
}, | ||
"license": "MIT", | ||
@@ -18,46 +22,69 @@ "author": "Tilde, Inc.", | ||
"module": "dist/modules/index.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/tildeio/router.js.git" | ||
}, | ||
"files": [ | ||
"dist/cjs", | ||
"dist/modules" | ||
], | ||
"scripts": { | ||
"prepublish": "ember build", | ||
"lint": "npm-run-all lint:*", | ||
"lint:ts": "eslint --cache .", | ||
"lint:types": "tsc -p tsconfig.json --noEmit", | ||
"prepare": "ember build", | ||
"problems": "tsc -p tsconfig.json --noEmit", | ||
"pretest": "tslint -c tslint.json --project tsconfig.json", | ||
"start": "ember server", | ||
"test": "ember test" | ||
}, | ||
"files": [ | ||
"dist/cjs", | ||
"dist/modules" | ||
], | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"@babel/plugin-transform-modules-amd": "^7.10.5", | ||
"@babel/plugin-transform-modules-commonjs": "^7.10.4", | ||
"@types/node": "^12.7.5", | ||
"@types/qunit": "^2.9.0", | ||
"babel-preset-env": "^1.7.0", | ||
"@types/qunit": "^2.9.1", | ||
"@typescript-eslint/eslint-plugin": "^3.7.0", | ||
"@typescript-eslint/parser": "^3.7.0", | ||
"backburner.js": "^2.6.0", | ||
"broccoli-babel-transpiler": "^6.1.2", | ||
"broccoli-concat": "^3.7.4", | ||
"broccoli-funnel": "^2.0.2", | ||
"broccoli-merge-trees": "^3.0.2", | ||
"broccoli-typescript-compiler": "~4.0.1", | ||
"ember-cli": "~3.9.0", | ||
"broccoli-babel-transpiler": "^7.6.0", | ||
"broccoli-concat": "^4.2.4", | ||
"broccoli-funnel": "^3.0.3", | ||
"broccoli-merge-trees": "^4.2.0", | ||
"broccoli-typescript-compiler": "^6.0.0", | ||
"ember-cli": "~3.19.0", | ||
"ensure-posix-path": "^1.1.1", | ||
"eslint": "^7.5.0", | ||
"eslint-config-prettier": "^6.11.0", | ||
"eslint-plugin-prettier": "^3.1.4", | ||
"loader.js": "^4.7.0", | ||
"prettier": "1.18.2", | ||
"qunit": "^2.9.2", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "2.0.5", | ||
"qunit": "^2.10.1", | ||
"release-it": "^13.6.5", | ||
"release-it-lerna-changelog": "^2.3.0", | ||
"route-recognizer": "^0.3.4", | ||
"rsvp": "^4.8.5", | ||
"tslint": "^5.20.0", | ||
"tslint-config-prettier": "^1.18.0", | ||
"tslint-plugin-prettier": "^2.0.1" | ||
"rsvp": "^4.8.5" | ||
}, | ||
"peerDependencies": { | ||
"route-recognizer": "^0.3.4", | ||
"rsvp": "^4.8.1" | ||
"rsvp": "^4.8.5" | ||
}, | ||
"engines": { | ||
"node": "^4.5 || 6.* || >= 8.*" | ||
"node": ">= 10" | ||
}, | ||
"namespace": "Router" | ||
"publishConfig": { | ||
"registry": "https://registry.npmjs.org" | ||
}, | ||
"namespace": "Router", | ||
"release-it": { | ||
"plugins": { | ||
"release-it-lerna-changelog": { | ||
"infile": "CHANGELOG.md", | ||
"launchEditor": true | ||
} | ||
}, | ||
"git": { | ||
"tagName": "v${version}" | ||
}, | ||
"github": { | ||
"release": true, | ||
"tokenRef": "GITHUB_AUTH" | ||
} | ||
} | ||
} |
# router.js | ||
[![Build Status](https://travis-ci.org/tildeio/router.js.svg?branch=master)](https://travis-ci.org/tildeio/router.js) | ||
[![CI](https://github.com/tildeio/router.js/workflows/CI/badge.svg)](https://github.com/tildeio/router.js/actions?query=workflow%3ACI) | ||
@@ -5,0 +5,0 @@ `router.js` is a lightweight JavaScript library |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
76
351488
25
5166