From c83aeed0869425d2e2f412c20df9b7d6badc8d85 Mon Sep 17 00:00:00 2001 From: Peter Wagenet Date: Thu, 27 Jan 2022 18:01:56 -0800 Subject: [PATCH 1/6] Overhaul types to include more detail --- lib/router/index.ts | 2 +- lib/router/route-info.ts | 210 ++++++++++-------- lib/router/router.ts | 180 ++++++++------- lib/router/transition-intent.ts | 10 +- .../named-transition-intent.ts | 61 +++-- .../url-transition-intent.ts | 12 +- lib/router/transition-state.ts | 47 ++-- lib/router/transition.ts | 41 ++-- lib/router/utils.ts | 23 +- package.json | 3 + tests/query_params_test.ts | 4 +- tests/route_info_test.ts | 2 +- tests/router_test.ts | 61 ++--- tests/test_helpers.ts | 32 +-- tests/transition-aborted-error_test.ts | 2 +- tests/transition_intent_test.ts | 4 +- tests/transition_state_test.ts | 4 +- yarn.lock | 8 +- 18 files changed, 401 insertions(+), 305 deletions(-) diff --git a/lib/router/index.ts b/lib/router/index.ts index 3c5110c9..ef8ed09e 100644 --- a/lib/router/index.ts +++ b/lib/router/index.ts @@ -8,4 +8,4 @@ export { QUERY_PARAMS_SYMBOL, } from './transition'; export { default as TransitionState, TransitionError } from './transition-state'; -export { default as InternalRouteInfo, RouteInfo, Route } from './route-info'; +export { default as InternalRouteInfo, IModel, ModelFor, RouteInfo, Route } from './route-info'; diff --git a/lib/router/route-info.ts b/lib/router/route-info.ts index ecb4ed40..66997594 100644 --- a/lib/router/route-info.ts +++ b/lib/router/route-info.ts @@ -11,33 +11,29 @@ import InternalTransition, { import { isParam, isPromise, merge } from './utils'; import { throwIfAborted } from './transition-aborted-error'; -interface IModel { +export type IModel = {} & { id?: string | number; -} +}; + +export type ModelFor = T extends Route ? V : never; -export interface Route { +export interface Route { inaccessibleByURL?: boolean; routeName: string; _internalName: string; - context: unknown; + context: T | undefined; events?: Dict; - model?( - params: Dict, - transition: Transition - ): Promise | null | undefined> | undefined | Dict; - deserialize?(params: Dict, transition: Transition): Dict; - serialize?(model: {}, params: string[]): Dict | undefined; - beforeModel?(transition: Transition): Promise | any; - afterModel?(resolvedModel: any, transition: Transition): Promise | any; - setup?( - context: Dict | PromiseLike | null | undefined>, - transition: Transition - ): void; + model?(params: Dict, transition: Transition): PromiseLike | undefined | T; + deserialize?(params: Dict, transition: Transition): T | PromiseLike | undefined; + serialize?(model: T | undefined, params: string[]): Dict | undefined; + beforeModel?(transition: Transition): PromiseLike | any; + afterModel?(resolvedModel: T | undefined, transition: Transition): PromiseLike | any; + setup?(context: T | undefined, transition: Transition): void; enter?(transition: Transition): void; exit?(transition?: Transition): void; _internalReset?(wasReset: boolean, transition?: Transition): void; contextDidChange?(): void; - redirect?(context: Dict, transition: Transition): void; + redirect?(context: T | undefined, transition: Transition): void; buildRouteInfoMetadata?(): unknown; } @@ -46,7 +42,7 @@ export interface RouteInfo { readonly parent: RouteInfo | RouteInfoWithAttributes | null; readonly child: RouteInfo | RouteInfoWithAttributes | null; readonly localName: string; - readonly params: Dict; + readonly params: Dict | undefined; readonly paramNames: string[]; readonly queryParams: Dict; readonly metadata: unknown; @@ -60,20 +56,24 @@ export interface RouteInfoWithAttributes extends RouteInfo { attributes: any; } -let ROUTE_INFOS = new WeakMap, RouteInfo | RouteInfoWithAttributes>(); +type RouteInfosKey = InternalRouteInfo>; + +let ROUTE_INFOS = new WeakMap(); -export function toReadOnlyRouteInfo( - routeInfos: InternalRouteInfo[], +export function toReadOnlyRouteInfo>( + routeInfos: InternalRouteInfo[], queryParams: Dict = {}, includeAttributes = false ): RouteInfoWithAttributes[] | RouteInfo[] { return routeInfos.map((info, i) => { let { name, params, paramNames, context, route } = info; - if (ROUTE_INFOS.has(info) && includeAttributes) { - let routeInfo = ROUTE_INFOS.get(info)!; + // SAFETY: This should be safe since it is just for use as a key + let key = (info as unknown) as RouteInfosKey; + if (ROUTE_INFOS.has(key) && includeAttributes) { + let routeInfo = ROUTE_INFOS.get(key)!; routeInfo = attachMetadata(route!, routeInfo); let routeInfoWithAttribute = createRouteInfoWithAttributes(routeInfo, context); - ROUTE_INFOS.set(info, routeInfoWithAttribute); + ROUTE_INFOS.set(key, routeInfoWithAttribute); return routeInfoWithAttribute as RouteInfoWithAttributes; } let routeInfo: RouteInfo = { @@ -85,11 +85,15 @@ export function toReadOnlyRouteInfo( let arr: RouteInfo[] = []; if (predicate.length === 3) { - arr = routeInfos.map((info) => ROUTE_INFOS.get(info)!); + arr = routeInfos.map( + // SAFETY: This should be safe since it is just for use as a key + (info) => ROUTE_INFOS.get((info as unknown) as RouteInfosKey)! + ); } for (let i = 0; routeInfos.length > i; i++) { - publicInfo = ROUTE_INFOS.get(routeInfos[i])!; + // SAFETY: This should be safe since it is just for use as a key + publicInfo = ROUTE_INFOS.get((routeInfos[i] as unknown) as RouteInfosKey)!; if (predicate.call(thisArg, publicInfo, i, arr)) { return publicInfo; } @@ -117,7 +121,8 @@ export function toReadOnlyRouteInfo( return null; } - return ROUTE_INFOS.get(parent)!; + // SAFETY: This should be safe since it is just for use as a key + return ROUTE_INFOS.get((parent as unknown) as RouteInfosKey)!; }, get child() { @@ -127,7 +132,8 @@ export function toReadOnlyRouteInfo( return null; } - return ROUTE_INFOS.get(child)!; + // SAFETY: This should be safe since it is just for use as a key + return ROUTE_INFOS.get((child as unknown) as RouteInfosKey)!; }, get localName() { @@ -148,7 +154,8 @@ export function toReadOnlyRouteInfo( routeInfo = createRouteInfoWithAttributes(routeInfo, context); } - ROUTE_INFOS.set(info, routeInfo); + // SAFETY: This should be safe since it is just for use as a key + ROUTE_INFOS.set((info as unknown) as RouteInfosKey, routeInfo); return routeInfo; }); @@ -193,18 +200,18 @@ function attachMetadata(route: Route, routeInfo: RouteInfo) { return Object.assign(routeInfo, metadata); } -export default class InternalRouteInfo { - private _routePromise?: Promise = undefined; - private _route?: Option = null; - protected router: Router; +export default class InternalRouteInfo> { + private _routePromise?: Promise = undefined; + private _route?: Option = null; + protected router: Router; paramNames: string[]; name: string; - params: Dict = {}; + params: Dict | undefined = {}; queryParams?: Dict; - context?: Dict | PromiseLike | null | undefined> | null; + context?: ModelFor | PromiseLike>; isResolved = false; - constructor(router: Router, name: string, paramNames: string[], route?: T) { + constructor(router: Router, name: string, paramNames: string[], route?: R) { this.name = name; this.paramNames = paramNames; this.router = router; @@ -213,15 +220,15 @@ export default class InternalRouteInfo { } } - getModel(_transition: InternalTransition) { + getModel(_transition: InternalTransition) { return Promise.resolve(this.context); } - serialize(_context?: Dict): Dict | undefined { + serialize(_context?: ModelFor | null): Dict | undefined { return this.params || {}; } - resolve(transition: InternalTransition): Promise> { + resolve(transition: InternalTransition): Promise> { return Promise.resolve(this.routePromise) .then((route: Route) => { throwIfAborted(transition); @@ -239,10 +246,10 @@ export default class InternalRouteInfo { } becomeResolved( - transition: InternalTransition | null, - resolvedContext: Dict - ): ResolvedRouteInfo { - let params = this.serialize(resolvedContext) as Dict; + transition: InternalTransition | null, + resolvedContext: ModelFor | undefined + ): ResolvedRouteInfo { + let params = this.serialize(resolvedContext); if (transition) { this.stashResolvedModel(transition, resolvedContext); @@ -256,8 +263,10 @@ export default class InternalRouteInfo { if ('context' in this || !contextsMatch) { context = resolvedContext; } - let cached = ROUTE_INFOS.get(this); - let resolved = new ResolvedRouteInfo( + + // SAFETY: Since this is just for lookup, it should be safe + let cached = ROUTE_INFOS.get((this as unknown) as InternalRouteInfo>); + let resolved = new ResolvedRouteInfo( this.router, this.name, this.paramNames, @@ -267,13 +276,14 @@ export default class InternalRouteInfo { ); if (cached !== undefined) { - ROUTE_INFOS.set(resolved, cached); + // SAFETY: This is potentially a bit risker, but for what we're doing, it should be ok. + ROUTE_INFOS.set((this as unknown) as InternalRouteInfo>, cached); } return resolved; } - shouldSupersede(routeInfo?: InternalRouteInfo) { + shouldSupersede(routeInfo?: InternalRouteInfo) { // Prefer this newer routeInfo over `other` if: // 1) The other one doesn't exist // 2) The names don't match @@ -292,7 +302,7 @@ export default class InternalRouteInfo { ); } - get route(): T | undefined { + get route(): R | undefined { // _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) { @@ -302,11 +312,11 @@ export default class InternalRouteInfo { return this.fetchRoute(); } - set route(route: T | undefined) { + set route(route: R | undefined) { this._route = route; } - get routePromise(): Promise { + get routePromise(): Promise { if (this._routePromise) { return this._routePromise; } @@ -316,22 +326,22 @@ export default class InternalRouteInfo { return this._routePromise!; } - set routePromise(routePromise: Promise) { + set routePromise(routePromise: Promise) { this._routePromise = routePromise; } - protected log(transition: InternalTransition, message: string) { + protected log(transition: InternalTransition, message: string) { if (transition.log) { transition.log(this.name + ': ' + message); } } - private updateRoute(route: T) { + private updateRoute(route: R) { route._internalName = this.name; return (this.route = route); } - private runBeforeModelHook(transition: InternalTransition) { + private runBeforeModelHook(transition: InternalTransition) { if (transition.trigger) { transition.trigger(true, 'willResolveModel', transition, this.route); } @@ -351,9 +361,9 @@ export default class InternalRouteInfo { } private runAfterModelHook( - transition: InternalTransition, - resolvedModel?: Dict | null - ): Promise> { + transition: InternalTransition, + resolvedModel?: ModelFor | null + ): Promise> { // Stash the resolved model on the payload. // This makes it possible for users to swap out // the resolved model in afterModel. @@ -373,12 +383,17 @@ export default class InternalRouteInfo { // 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]!; + // SAFTEY: We expect this to be of type T, though typing it as such is challenging. + return (transition.resolvedModels[name]! as unknown) as ModelFor; }); } - private stashResolvedModel(transition: InternalTransition, resolvedModel: Dict) { + private stashResolvedModel( + transition: InternalTransition, + resolvedModel: ModelFor | undefined + ) { transition.resolvedModels = transition.resolvedModels || {}; + // SAFETY: It's unfortunate that we have to do this cast. It should be safe though. transition.resolvedModels[this.name] = resolvedModel; } @@ -387,7 +402,7 @@ export default class InternalRouteInfo { return this._processRoute(route); } - private _processRoute(route: T | Promise) { + private _processRoute(route: R | Promise) { // Setup a routePromise so that we can wait for asynchronously loaded routes this.routePromise = Promise.resolve(route); @@ -407,15 +422,16 @@ export default class InternalRouteInfo { } } -export class ResolvedRouteInfo extends InternalRouteInfo { +export class ResolvedRouteInfo> extends InternalRouteInfo { isResolved: boolean; + context: ModelFor | undefined; constructor( - router: Router, + router: Router, name: string, paramNames: string[], - params: Dict, - route: T, - context?: Dict + params: Dict | undefined, + route: R, + context?: ModelFor ) { super(router, name, paramNames, route); this.params = params; @@ -423,29 +439,31 @@ export class ResolvedRouteInfo extends InternalRouteInfo { this.context = context; } - resolve(transition: InternalTransition): Promise> { + resolve(transition: InternalTransition): Promise { // A ResolvedRouteInfo just resolved with itself. if (transition && transition.resolvedModels) { - transition.resolvedModels[this.name] = this.context as Dict; + transition.resolvedModels[this.name] = this.context; } return Promise.resolve(this); } } -export class UnresolvedRouteInfoByParam extends InternalRouteInfo { +export class UnresolvedRouteInfoByParam> extends InternalRouteInfo { params: Dict = {}; constructor( - router: Router, + router: Router, name: string, paramNames: string[], - params: Dict, - route?: T + params: Dict | undefined, + route?: R ) { super(router, name, paramNames, route); - this.params = params; + if (params) { + this.params = params; + } } - getModel(transition: InternalTransition) { + getModel(transition: InternalTransition): Promise | undefined> { let fullParams = this.params; if (transition && transition[QUERY_PARAMS_SYMBOL]) { fullParams = {}; @@ -455,12 +473,19 @@ export class UnresolvedRouteInfoByParam extends InternalRouteIn let route = this.route!; - let result: Dict | undefined | Promise | null | undefined>; + let result: ModelFor | PromiseLike> | undefined; + // FIXME: Review these casts if (route.deserialize) { - result = route.deserialize(fullParams, transition); + result = route.deserialize(fullParams, transition) as + | ModelFor + | PromiseLike> + | undefined; } else if (route.model) { - result = route.model(fullParams, transition); + result = route.model(fullParams, transition) as + | ModelFor + | PromiseLike> + | undefined; } if (result && isTransition(result)) { @@ -471,20 +496,20 @@ export class UnresolvedRouteInfoByParam extends InternalRouteIn } } -export class UnresolvedRouteInfoByObject extends InternalRouteInfo { - serializer?: SerializerFunc; +export class UnresolvedRouteInfoByObject> extends InternalRouteInfo { + serializer?: SerializerFunc>; constructor( - router: Router, + router: Router, name: string, paramNames: string[], - context: Dict | PromiseLike> + context: ModelFor | PromiseLike> | undefined ) { super(router, name, paramNames); this.context = context; this.serializer = this.router.getSerializer(name); } - getModel(transition: InternalTransition) { + getModel(transition: InternalTransition) { if (this.router.log !== undefined) { this.router.log(this.name + ': resolving provided model'); } @@ -500,11 +525,13 @@ export class UnresolvedRouteInfoByObject extends InternalRouteI @param {Object} model the model to be serialized for this route */ - serialize(model?: IModel) { + serialize(model?: ModelFor): Dict | undefined { let { paramNames, context } = this; if (!model) { - model = context as IModel; + // SAFETY: By the time we serialize, we expect to be resolved. + // This may not be an entirely safe assumption though no tests fail. + model = context as ModelFor; } let object: Dict = {}; @@ -530,7 +557,8 @@ export class UnresolvedRouteInfoByObject extends InternalRouteI let name = paramNames[0]; if (/_id$/.test(name)) { - object[name] = model.id; + // SAFETY: Model is supposed to extend IModel already + object[name] = (model as IModel).id; } else { object[name] = model; } @@ -538,15 +566,15 @@ export class UnresolvedRouteInfoByObject extends InternalRouteI } } -function paramsMatch(a: Dict, b: Dict) { - if (!a !== !b) { - // Only one is null. - return false; +function paramsMatch(a: Dict | undefined, b: Dict | undefined) { + if (a === b) { + // Both are identical, may both be undefined + return true; } - if (!a) { - // Both must be null. - return true; + if (!a || !b) { + // Only one is undefined, already checked they aren't identical + return false; } // Note: this assumes that both params have the same diff --git a/lib/router/router.ts b/lib/router/router.ts index ee08c185..a67ce4ed 100644 --- a/lib/router/router.ts +++ b/lib/router/router.ts @@ -1,7 +1,9 @@ -import RouteRecognizer, { MatchCallback, Params } from 'route-recognizer'; +import RouteRecognizer, { MatchCallback, Params, QueryParams } from 'route-recognizer'; import { Promise } from 'rsvp'; import { Dict, Maybe, Option } from './core'; import InternalRouteInfo, { + IModel, + ModelFor, Route, RouteInfo, RouteInfoWithAttributes, @@ -27,10 +29,11 @@ import { log, merge, promiseLabel, + QueryParamsContainer, } from './utils'; -export interface SerializerFunc { - (model: {}, params: string[]): Dict; +export interface SerializerFunc { + (model: T, params: string[]): Dict; } export interface ParsedHandler { @@ -38,13 +41,13 @@ export interface ParsedHandler { names: string[]; } -export default abstract class Router { +export default abstract class Router> { private _lastQueryParams = {}; log?: (message: string) => void; - state?: TransitionState = undefined; - oldState: Maybe> = undefined; - activeTransition?: InternalTransition = undefined; - currentRouteInfos?: InternalRouteInfo[] = undefined; + state?: TransitionState = undefined; + oldState: Maybe> = undefined; + activeTransition?: InternalTransition = undefined; + currentRouteInfos?: InternalRouteInfo[] = undefined; _changedQueryParams?: Dict = undefined; currentSequence = 0; recognizer: RouteRecognizer; @@ -55,18 +58,18 @@ export default abstract class Router { this.reset(); } - abstract getRoute(name: string): T | Promise; - abstract getSerializer(name: string): SerializerFunc | undefined; + abstract getRoute(name: string): R | Promise; + abstract getSerializer(name: string): SerializerFunc> | undefined; abstract updateURL(url: string): void; abstract replaceURL(url: string): void; abstract willTransition( - oldRouteInfos: InternalRouteInfo[], - newRouteInfos: InternalRouteInfo[], + oldRouteInfos: InternalRouteInfo[], + newRouteInfos: InternalRouteInfo[], transition: Transition ): void; - abstract didTransition(routeInfos: InternalRouteInfo[]): void; + abstract didTransition(routeInfos: InternalRouteInfo[]): void; abstract triggerEvent( - routeInfos: InternalRouteInfo[], + routeInfos: InternalRouteInfo[], ignoreFailure: boolean, name: string, args: unknown[] @@ -103,8 +106,8 @@ export default abstract class Router { queryParamsTransition( changelist: ChangeList, wasTransitioning: boolean, - oldState: TransitionState, - newState: TransitionState + oldState: TransitionState, + newState: TransitionState ): OpaqueTransition { this.fireQueryParamDidChange(newState, changelist); @@ -136,7 +139,7 @@ export default abstract class Router { this.routeWillChange(newTransition); newTransition.promise = newTransition.promise!.then( - (result: TransitionState | Route | Error | undefined) => { + (result: TransitionState | Route | Error | undefined) => { if (!newTransition.isAborted) { this._updateURL(newTransition, oldState); this.didTransition(this.currentRouteInfos!); @@ -153,7 +156,7 @@ export default abstract class Router { } } - transitionByIntent(intent: TransitionIntent, isIntermediate: boolean): InternalTransition { + transitionByIntent(intent: TransitionIntent, isIntermediate: boolean): InternalTransition { try { return this.getTransitionByIntent(intent, isIntermediate); } catch (e) { @@ -162,7 +165,7 @@ export default abstract class Router { } recognize(url: string): Option { - let intent = new URLTransitionIntent(this, url); + let intent = new URLTransitionIntent(this, url); let newState = this.generateNewState(intent); if (newState === null) { @@ -174,7 +177,7 @@ export default abstract class Router { } recognizeAndLoad(url: string): Promise { - let intent = new URLTransitionIntent(this, url); + let intent = new URLTransitionIntent(this, url); let newState = this.generateNewState(intent); if (newState === null) { @@ -192,7 +195,7 @@ export default abstract class Router { }); } - private generateNewState(intent: TransitionIntent): Option> { + private generateNewState(intent: TransitionIntent): Option> { try { return intent.applyToState(this.state!, false); } catch (e) { @@ -201,12 +204,12 @@ export default abstract class Router { } private getTransitionByIntent( - intent: TransitionIntent, + intent: TransitionIntent, isIntermediate: boolean - ): InternalTransition { + ): InternalTransition { let wasTransitioning = !!this.activeTransition; let oldState = wasTransitioning ? this.activeTransition![STATE_SYMBOL] : this.state; - let newTransition: InternalTransition; + let newTransition: InternalTransition; let newState = intent.applyToState(oldState!, isIntermediate); let queryParamChangelist = getChangelist(oldState!.queryParams, newState.queryParams); @@ -221,7 +224,8 @@ export default abstract class Router { newState ); newTransition.queryParamsOnly = true; - return newTransition; + // SAFETY: The returned OpaqueTransition should actually be this. + return newTransition as InternalTransition; } // No-op. No need to create a new transition. @@ -264,7 +268,7 @@ export default abstract class Router { // For our purposes, swap out the promise to resolve // after the transition has been finalized. newTransition.promise = newTransition.promise!.then( - (result: TransitionState) => { + (result: TransitionState) => { return this.finalizeTransition(newTransition, result); }, null, @@ -293,14 +297,18 @@ export default abstract class Router { */ private doTransition( name?: string, - modelsArray: Dict[] = [], + modelsArray: [...ModelFor[]] | [...ModelFor[], { queryParams: QueryParams }] = [], isIntermediate = false - ): InternalTransition { + ): InternalTransition { let lastArg = modelsArray[modelsArray.length - 1]; let queryParams: Dict = {}; if (lastArg !== undefined && lastArg.hasOwnProperty('queryParams')) { - queryParams = modelsArray.pop()!.queryParams as Dict; + // We just checked this. + // TODO: Use an assertion? + queryParams = (modelsArray.pop() as { queryParams: QueryParams }).queryParams as Dict< + unknown + >; } let intent; @@ -310,7 +318,7 @@ export default abstract class Router { // A query param update is really just a transition // into the route you're already on. let { routeInfos } = this.state!; - intent = new NamedTransitionIntent( + intent = new NamedTransitionIntent( this, routeInfos[routeInfos.length - 1].name, undefined, @@ -319,10 +327,17 @@ export default abstract class Router { ); } else if (name.charAt(0) === '/') { log(this, 'Attempting URL transition to ' + name); - intent = new URLTransitionIntent(this, name); + intent = new URLTransitionIntent(this, name); } else { log(this, 'Attempting transition to ' + name); - intent = new NamedTransitionIntent(this, name, undefined, modelsArray, queryParams); + intent = new NamedTransitionIntent( + this, + name, + undefined, + // SAFETY: We know this to be the case since we removed the last item if it was QPs + modelsArray as ModelFor[], + queryParams + ); } return this.transitionByIntent(intent, isIntermediate); @@ -335,9 +350,9 @@ export default abstract class Router { to update the router's array of `currentRouteInfos`. */ private finalizeTransition( - transition: InternalTransition, - newState: TransitionState - ): T | Promise { + transition: InternalTransition, + newState: TransitionState + ): R | Promise { try { log( transition.router, @@ -423,7 +438,7 @@ export default abstract class Router { @param {Router} transition @param {TransitionState} newState */ - private setupContexts(newState: TransitionState, transition?: InternalTransition) { + private setupContexts(newState: TransitionState, transition?: InternalTransition) { let partition = this.partitionRoutes(this.state!, newState); let i, l, route; @@ -486,7 +501,7 @@ export default abstract class Router { Fires queryParamsDidChange event */ - private fireQueryParamDidChange(newState: TransitionState, queryParamChangelist: ChangeList) { + private fireQueryParamDidChange(newState: TransitionState, queryParamChangelist: ChangeList) { // If queryParams changed trigger event if (queryParamChangelist) { // This is a little hacky but we need some way of storing @@ -509,15 +524,15 @@ export default abstract class Router { that may happen in enter/setup. */ private routeEnteredOrUpdated( - currentRouteInfos: InternalRouteInfo[], - routeInfo: InternalRouteInfo, + currentRouteInfos: InternalRouteInfo[], + routeInfo: InternalRouteInfo, enter: boolean, - transition?: InternalTransition + transition?: InternalTransition ) { let route = routeInfo.route, context = routeInfo.context; - function _routeEnteredOrUpdated(route: T) { + function _routeEnteredOrUpdated(route: R) { if (enter) { if (route.enter !== undefined) { route.enter(transition!); @@ -526,7 +541,7 @@ export default abstract class Router { throwIfAborted(transition); - route.context = context; + route.context = context as Awaited; if (route.contextDidChange !== undefined) { route.contextDidChange(); @@ -593,11 +608,11 @@ export default abstract class Router { @return {Partition} */ - private partitionRoutes(oldState: TransitionState, newState: TransitionState) { + private partitionRoutes(oldState: TransitionState, newState: TransitionState) { let oldRouteInfos = oldState.routeInfos; let newRouteInfos = newState.routeInfos; - let routes: RoutePartition = { + let routes: RoutePartition = { updatedContext: [], exited: [], entered: [], @@ -641,7 +656,7 @@ export default abstract class Router { return routes; } - private _updateURL(transition: OpaqueTransition, state: TransitionState) { + private _updateURL(transition: OpaqueTransition, state: TransitionState) { let urlMethod: string | null = transition.urlMethod; if (!urlMethod) { @@ -705,7 +720,7 @@ export default abstract class Router { } private finalizeQueryParamChange( - resolvedHandlers: InternalRouteInfo[], + resolvedHandlers: InternalRouteInfo[], newQueryParams: Dict, transition: OpaqueTransition ) { @@ -750,14 +765,14 @@ export default abstract class Router { return finalQueryParams; } - private toReadOnlyInfos(newTransition: OpaqueTransition, newState: TransitionState) { + private toReadOnlyInfos(newTransition: OpaqueTransition, newState: TransitionState) { let oldRouteInfos = this.state!.routeInfos; this.fromInfos(newTransition, oldRouteInfos); this.toInfos(newTransition, newState.routeInfos); this._lastQueryParams = newState.queryParams; } - private fromInfos(newTransition: OpaqueTransition, oldRouteInfos: InternalRouteInfo[]) { + private fromInfos(newTransition: OpaqueTransition, oldRouteInfos: InternalRouteInfo[]) { if (newTransition !== undefined && oldRouteInfos.length > 0) { let fromInfos = toReadOnlyRouteInfo( oldRouteInfos, @@ -770,7 +785,7 @@ export default abstract class Router { public toInfos( newTransition: OpaqueTransition, - newRouteInfos: InternalRouteInfo[], + newRouteInfos: InternalRouteInfo[], includeAttributes = false ) { if (newTransition !== undefined && newRouteInfos.length > 0) { @@ -784,8 +799,8 @@ export default abstract class Router { } private notifyExistingHandlers( - newState: TransitionState, - newTransition: InternalTransition + newState: TransitionState, + newTransition: InternalTransition ) { let oldRouteInfos = this.state!.routeInfos, changing = [], @@ -820,7 +835,7 @@ export default abstract class Router { */ reset() { if (this.state) { - forEach>(this.state.routeInfos.slice().reverse(), function (routeInfo) { + forEach>(this.state.routeInfos.slice().reverse(), function (routeInfo) { let route = routeInfo.route; if (route !== undefined) { if (route.exit !== undefined) { @@ -879,7 +894,7 @@ export default abstract class Router { return this.doTransition(name, args, true); } - refresh(pivotRoute?: T) { + refresh(pivotRoute?: R) { let previousTransition = this.activeTransition; let state = previousTransition ? previousTransition[STATE_SYMBOL] : this.state; let routeInfos = state!.routeInfos; @@ -930,7 +945,7 @@ export default abstract class Router { @return {String} a URL */ - generate(routeName: string, ...args: unknown[]) { + generate(routeName: string, ...args: ModelFor[]) { let partitionedArgs = extractQueryParams(args), suppliedParams = partitionedArgs[0], queryParams = partitionedArgs[1]; @@ -951,7 +966,7 @@ export default abstract class Router { return this.recognizer.generate(routeName, params); } - applyIntent(routeName: string, contexts: Dict[]): TransitionState { + applyIntent(routeName: string, contexts: ModelFor[]): TransitionState { let intent = new NamedTransitionIntent(this, routeName, undefined, contexts); let state = (this.activeTransition && this.activeTransition[STATE_SYMBOL]) || this.state!; @@ -961,9 +976,9 @@ export default abstract class Router { isActiveIntent( routeName: string, - contexts: unknown[], + contexts: ModelFor[], queryParams?: Dict | null, - _state?: TransitionState + _state?: TransitionState ) { let state = _state || this.state!, targetRouteInfos = state.routeInfos, @@ -990,7 +1005,7 @@ export default abstract class Router { return false; } - let testState = new TransitionState(); + let testState = new TransitionState(); testState.routeInfos = targetRouteInfos.slice(0, index + 1); recognizerHandlers = recognizerHandlers.slice(0, index + 1); @@ -1017,9 +1032,9 @@ export default abstract class Router { return routesEqual && !getChangelist(activeQPsOnNewHandler, queryParams); } - isActive(routeName: string, ...args: unknown[]) { - let partitionedArgs = extractQueryParams(args); - return this.isActiveIntent(routeName, partitionedArgs[0], partitionedArgs[1]); + isActive(routeName: string, ...args: ModelFor[] | [...ModelFor[], QueryParamsContainer]) { + let [contexts, queryParams] = extractQueryParams(args); + return this.isActiveIntent(routeName, contexts, queryParams); } trigger(name: string, ...args: any[]) { @@ -1027,25 +1042,28 @@ export default abstract class Router { } } -function routeInfosEqual( - routeInfos: InternalRouteInfo[], - otherRouteInfos: InternalRouteInfo[] -) { +function routeInfosEqual< + T1 extends IModel, + R1 extends Route, + T2 extends IModel, + R2 extends Route +>(routeInfos: InternalRouteInfo[], otherRouteInfos: InternalRouteInfo[]) { if (routeInfos.length !== otherRouteInfos.length) { return false; } for (let i = 0, len = routeInfos.length; i < len; ++i) { - if (routeInfos[i] !== otherRouteInfos[i]) { + // SAFETY: Just casting for comparison + if (routeInfos[i] !== ((otherRouteInfos[i] as unknown) as InternalRouteInfo)) { return false; } } return true; } -function routeInfosSameExceptQueryParams( - routeInfos: InternalRouteInfo[], - otherRouteInfos: InternalRouteInfo[] +function routeInfosSameExceptQueryParams, R2 extends Route<{}>>( + routeInfos: InternalRouteInfo[], + otherRouteInfos: InternalRouteInfo[] ) { if (routeInfos.length !== otherRouteInfos.length) { return false; @@ -1063,13 +1081,17 @@ function routeInfosSameExceptQueryParams( return true; } -function paramsEqual(params: Dict, otherParams: Dict) { - if (!params && !otherParams) { +function paramsEqual(params: Dict | undefined, otherParams: Dict | undefined) { + if (params === otherParams) { + // Both identical or both undefined return true; - } else if ((!params && !!otherParams) || (!!params && !otherParams)) { - // one is falsy but other is not; + } + + if (!params || !otherParams) { + // One is falsy but other is not return false; } + let keys = Object.keys(params); let otherKeys = Object.keys(otherParams); @@ -1088,10 +1110,10 @@ function paramsEqual(params: Dict, otherParams: Dict) { return true; } -export interface RoutePartition { - updatedContext: InternalRouteInfo[]; - exited: InternalRouteInfo[]; - entered: InternalRouteInfo[]; - unchanged: InternalRouteInfo[]; - reset: InternalRouteInfo[]; +export interface RoutePartition> { + updatedContext: InternalRouteInfo[]; + exited: InternalRouteInfo[]; + entered: InternalRouteInfo[]; + unchanged: InternalRouteInfo[]; + reset: InternalRouteInfo[]; } diff --git a/lib/router/transition-intent.ts b/lib/router/transition-intent.ts index 8578d7fb..b6e4354d 100644 --- a/lib/router/transition-intent.ts +++ b/lib/router/transition-intent.ts @@ -4,13 +4,13 @@ import TransitionState from './transition-state'; export type OpaqueIntent = TransitionIntent; -export abstract class TransitionIntent { +export abstract class TransitionIntent> { data: {}; - router: Router; - constructor(router: Router, data: {} = {}) { + router: Router; + constructor(router: Router, data: {} = {}) { this.router = router; this.data = data; } - preTransitionState?: TransitionState; - abstract applyToState(oldState: TransitionState, isIntermediate: boolean): TransitionState; + preTransitionState?: TransitionState; + abstract applyToState(oldState: TransitionState, isIntermediate: boolean): TransitionState; } diff --git a/lib/router/transition-intent/named-transition-intent.ts b/lib/router/transition-intent/named-transition-intent.ts index b6567c9a..ab38e14e 100644 --- a/lib/router/transition-intent/named-transition-intent.ts +++ b/lib/router/transition-intent/named-transition-intent.ts @@ -1,5 +1,7 @@ import { Dict } from '../core'; import InternalRouteInfo, { + ModelFor, + ResolvedRouteInfo, Route, UnresolvedRouteInfoByObject, UnresolvedRouteInfoByParam, @@ -9,18 +11,18 @@ import { TransitionIntent } from '../transition-intent'; import TransitionState from '../transition-state'; import { extractQueryParams, isParam, merge } from '../utils'; -export default class NamedTransitionIntent extends TransitionIntent { +export default class NamedTransitionIntent> extends TransitionIntent { name: string; pivotHandler?: Route; - contexts: unknown[]; + contexts: ModelFor[]; queryParams: Dict; - preTransitionState?: TransitionState = undefined; + preTransitionState?: TransitionState = undefined; constructor( - router: Router, + router: Router, name: string, pivotHandler: Route | undefined, - contexts: unknown[] = [], + contexts: ModelFor[] = [], queryParams: Dict = {}, data?: {} ) { @@ -31,7 +33,7 @@ export default class NamedTransitionIntent extends TransitionIn this.queryParams = queryParams; } - applyToState(oldState: TransitionState, isIntermediate: boolean): TransitionState { + applyToState(oldState: TransitionState, isIntermediate: boolean): TransitionState { // TODO: WTF fix me let partitionedArgs = extractQueryParams([this.name].concat(this.contexts as any)), pureArgs = partitionedArgs[0], @@ -43,14 +45,14 @@ export default class NamedTransitionIntent extends TransitionIn } applyToHandlers( - oldState: TransitionState, + oldState: TransitionState, parsedHandlers: ParsedHandler[], targetRouteName: string, isIntermediate: boolean, checkingIfActive: boolean ) { let i, len; - let newState = new TransitionState(); + let newState = new TransitionState(); let objects = this.contexts.slice(0); let invalidateIndex = parsedHandlers.length; @@ -70,7 +72,11 @@ export default class NamedTransitionIntent extends TransitionIn let name = result.handler; let oldHandlerInfo = oldState.routeInfos[i]; - let newHandlerInfo = null; + let newHandlerInfo: + | InternalRouteInfo + | UnresolvedRouteInfoByObject + | ResolvedRouteInfo + | null = null; if (result.names.length > 0) { if (i >= invalidateIndex) { @@ -99,7 +105,8 @@ export default class NamedTransitionIntent extends TransitionIn // ignore mismatches between old and new context. newHandlerInfo = newHandlerInfo.becomeResolved( null, - newHandlerInfo.context as Dict + // SAFETY: This seems to imply that it would be resolved, but it's unclear if that's actually the case. + newHandlerInfo.context as Awaited ); let oldContext = oldHandlerInfo && oldHandlerInfo.context; if ( @@ -112,17 +119,25 @@ export default class NamedTransitionIntent extends TransitionIn // handler provide a `serialize` method newHandlerInfo.params = oldHandlerInfo && oldHandlerInfo.params; } - newHandlerInfo.context = oldContext; + newHandlerInfo.context = oldContext as Awaited; } - let handlerToUse = oldHandlerInfo; + let handlerToUse: + | InternalRouteInfo + | UnresolvedRouteInfoByObject + | ResolvedRouteInfo = oldHandlerInfo; + if (i >= invalidateIndex || newHandlerInfo.shouldSupersede(oldHandlerInfo)) { invalidateIndex = Math.min(i, invalidateIndex); handlerToUse = newHandlerInfo; } if (isIntermediate && !checkingIfActive) { - handlerToUse = handlerToUse.becomeResolved(null, handlerToUse.context as Dict); + handlerToUse = handlerToUse.becomeResolved( + null, + // SAFETY: This seems to imply that it would be resolved, but it's unclear if that's actually the case. + handlerToUse.context as ModelFor + ); } newState.routeInfos.unshift(handlerToUse); @@ -147,7 +162,7 @@ export default class NamedTransitionIntent extends TransitionIn return newState; } - invalidateChildren(handlerInfos: InternalRouteInfo[], invalidateIndex: number) { + invalidateChildren(handlerInfos: InternalRouteInfo[], invalidateIndex: number) { for (let i = invalidateIndex, l = handlerInfos.length; i < l; ++i) { let handlerInfo = handlerInfos[i]; if (handlerInfo.isResolved) { @@ -166,12 +181,12 @@ export default class NamedTransitionIntent extends TransitionIn getHandlerInfoForDynamicSegment( name: string, names: string[], - objects: unknown[], - oldHandlerInfo: InternalRouteInfo, + objects: ModelFor[], + oldHandlerInfo: InternalRouteInfo, _targetRouteName: string, i: number - ) { - let objectToUse: unknown; + ): UnresolvedRouteInfoByObject { + let objectToUse: ModelFor | PromiseLike> | undefined; if (objects.length > 0) { // Use the objects provided for this transition. objectToUse = objects[objects.length - 1]; @@ -185,8 +200,10 @@ export default class NamedTransitionIntent extends TransitionIn return oldHandlerInfo; } else { if (this.preTransitionState) { - let preTransitionHandlerInfo = this.preTransitionState.routeInfos[i]; - objectToUse = preTransitionHandlerInfo && preTransitionHandlerInfo.context!; + let preTransitionHandlerInfo = this.preTransitionState.routeInfos[i] as + | ResolvedRouteInfo + | undefined; + objectToUse = preTransitionHandlerInfo?.context; } else { // Ideally we should throw this error to provide maximal // information to the user that not enough context objects @@ -199,14 +216,14 @@ export default class NamedTransitionIntent extends TransitionIn } } - return new UnresolvedRouteInfoByObject(this.router, name, names, objectToUse as Dict); + return new UnresolvedRouteInfoByObject(this.router, name, names, objectToUse); } createParamHandlerInfo( name: string, names: string[], objects: unknown[], - oldHandlerInfo: InternalRouteInfo + oldHandlerInfo: InternalRouteInfo ) { let params: Dict = {}; diff --git a/lib/router/transition-intent/url-transition-intent.ts b/lib/router/transition-intent/url-transition-intent.ts index 2d8c4b5e..9bc4b05e 100644 --- a/lib/router/transition-intent/url-transition-intent.ts +++ b/lib/router/transition-intent/url-transition-intent.ts @@ -5,17 +5,17 @@ import TransitionState from '../transition-state'; import UnrecognizedURLError from '../unrecognized-url-error'; import { merge } from '../utils'; -export default class URLTransitionIntent extends TransitionIntent { - preTransitionState?: TransitionState; +export default class URLTransitionIntent> extends TransitionIntent { + preTransitionState?: TransitionState; url: string; - constructor(router: Router, url: string, data?: {}) { + constructor(router: Router, url: string, data?: {}) { super(router, data); this.url = url; this.preTransitionState = undefined; } - applyToState(oldState: TransitionState) { - let newState = new TransitionState(); + applyToState(oldState: TransitionState) { + let newState = new TransitionState(); let results = this.router.recognizer.recognize(this.url), i, len; @@ -30,7 +30,7 @@ export default class URLTransitionIntent extends TransitionInte // 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: T) { + function checkHandlerAccessibility(handler: R) { if (handler && handler.inaccessibleByURL) { throw new UnrecognizedURLError(_url); } diff --git a/lib/router/transition-state.ts b/lib/router/transition-state.ts index 31abfb79..903f4804 100644 --- a/lib/router/transition-state.ts +++ b/lib/router/transition-state.ts @@ -9,9 +9,9 @@ interface IParams { [key: string]: unknown; } -function handleError( - currentState: TransitionState, - transition: Transition, +function handleError>( + currentState: TransitionState, + transition: Transition, error: Error ): never { // This is the only possible @@ -30,9 +30,9 @@ function handleError( ); } -function resolveOneRouteInfo( - currentState: TransitionState, - transition: Transition +function resolveOneRouteInfo>( + currentState: TransitionState, + transition: Transition ): void | Promise { if (transition.resolveIndex === currentState.routeInfos.length) { // This is is the only possible @@ -42,15 +42,17 @@ function resolveOneRouteInfo( let routeInfo = currentState.routeInfos[transition.resolveIndex]; - return routeInfo - .resolve(transition) - .then(proceed.bind(null, currentState, transition), null, currentState.promiseLabel('Proceed')); + let callback = proceed.bind(null, currentState, transition) as ( + resolvedRouteInfo: ResolvedRouteInfo + ) => void | Promise; + + return routeInfo.resolve(transition).then(callback, null, currentState.promiseLabel('Proceed')); } -function proceed( - currentState: TransitionState, - transition: Transition, - resolvedRouteInfo: ResolvedRouteInfo +function proceed>( + currentState: TransitionState, + transition: Transition, + resolvedRouteInfo: ResolvedRouteInfo ): void | Promise { let wasAlreadyResolved = currentState.routeInfos[transition.resolveIndex].isResolved; @@ -66,7 +68,7 @@ function proceed( let { route } = resolvedRouteInfo; if (route !== undefined) { if (route.redirect) { - route.redirect(resolvedRouteInfo.context as Dict, transition); + route.redirect(resolvedRouteInfo.context, transition); } } } @@ -78,8 +80,8 @@ function proceed( return resolveOneRouteInfo(currentState, transition); } -export default class TransitionState { - routeInfos: InternalRouteInfo[] = []; +export default class TransitionState> { + routeInfos: InternalRouteInfo[] = []; queryParams: Dict = {}; params: IParams = {}; @@ -95,7 +97,7 @@ export default class TransitionState { return promiseLabel("'" + targetName + "': " + label); } - resolve(transition: Transition): Promise> { + resolve(transition: Transition): Promise> { // First, calculate params for this state. This is useful // information to provide to the various route hooks. let params = this.params; @@ -106,14 +108,13 @@ export default class TransitionState { transition.resolveIndex = 0; + let callback = resolveOneRouteInfo.bind(null, this, transition); + let errorHandler = handleError.bind(null, this, transition); + // The prelude RSVP.resolve() async moves us into the promise land. return Promise.resolve(null, this.promiseLabel('Start transition')) - .then( - resolveOneRouteInfo.bind(null, this, transition), - null, - this.promiseLabel('Resolve route') - ) - .catch(handleError.bind(null, this, transition), this.promiseLabel('Handle error')) + .then(callback, null, this.promiseLabel('Resolve route')) + .catch(errorHandler, this.promiseLabel('Handle error')) .then(() => this); } } diff --git a/lib/router/transition.ts b/lib/router/transition.ts index 03525896..37891e4b 100644 --- a/lib/router/transition.ts +++ b/lib/router/transition.ts @@ -1,6 +1,11 @@ import { Promise } from 'rsvp'; import { Dict, Maybe, Option } from './core'; -import InternalRouteInfo, { Route, RouteInfo, RouteInfoWithAttributes } from './route-info'; +import InternalRouteInfo, { + ModelFor, + Route, + RouteInfo, + RouteInfoWithAttributes, +} from './route-info'; import Router from './router'; import { TransitionAbortedError, buildTransitionAborted } from './transition-aborted-error'; import { OpaqueIntent } from './transition-intent'; @@ -39,21 +44,21 @@ export const QUERY_PARAMS_SYMBOL = `__QPS__-2619863929824844-32323`; @param {Object} error @private */ -export default class Transition implements Partial> { - [STATE_SYMBOL]: TransitionState; +export default class Transition> implements Partial> { + [STATE_SYMBOL]: TransitionState; from: Maybe = null; to?: RouteInfo | RouteInfoWithAttributes = undefined; - router: Router; + router: Router; data: Dict; intent: Maybe; - resolvedModels: Dict>; + resolvedModels: Dict | undefined>; [QUERY_PARAMS_SYMBOL]: Dict; promise?: Promise; // Todo: Fix this shit its actually TransitionState | IHandler | undefined | Error - error: Maybe; + error: Maybe; [PARAMS_SYMBOL]: Dict; - routeInfos: InternalRouteInfo[]; + routeInfos: InternalRouteInfo[]; targetName: Maybe; - pivotHandler: Maybe; + pivotHandler: Maybe<{}>; sequence: number; isAborted = false; isActive = true; @@ -94,14 +99,14 @@ export default class Transition implements Partial> @property debugPreviousTransition @type {Transition | undefined} */ - declare debugPreviousTransition: Maybe>; + declare debugPreviousTransition: Maybe>; constructor( - router: Router, + router: Router, intent: Maybe, - state: TransitionState | undefined, - error: Maybe = undefined, - previousTransition: Maybe> = undefined + state: TransitionState | undefined, + error: Maybe = undefined, + previousTransition: Maybe> = undefined ) { this[STATE_SYMBOL] = state! || router.state!; this.intent = intent; @@ -222,8 +227,8 @@ export default class Transition implements Partial> @return {Promise} @public */ - then( - onFulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, + then( + onFulfilled?: ((value: R) => TResult1 | PromiseLike) | undefined | null, onRejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, label?: string ): Promise { @@ -303,7 +308,7 @@ export default class Transition implements Partial> } } - redirect(newTransition: Transition) { + redirect(newTransition: Transition) { this.rollback(); this.router.routeWillChange(newTransition); } @@ -367,7 +372,7 @@ export default class Transition implements Partial> ignoreFailure = false, _name: string, err?: Error, - transition?: Transition, + transition?: Transition, handler?: Route ) { this.trigger(ignoreFailure, _name, err, transition, handler); @@ -413,7 +418,7 @@ export default class Transition implements Partial> value that the final redirecting transition fulfills with @public */ - followRedirects(): Promise { + followRedirects(): Promise { let router = this.router; return this.promise!.catch(function (reason) { if (router.activeTransition) { diff --git a/lib/router/utils.ts b/lib/router/utils.ts index eae8f50f..0e754ef1 100644 --- a/lib/router/utils.ts +++ b/lib/router/utils.ts @@ -1,3 +1,4 @@ +import { QueryParams } from 'route-recognizer'; import { Promise } from 'rsvp'; import { Dict } from './core'; import Router from './router'; @@ -25,25 +26,37 @@ export function merge(hash: Dict, other?: Dict) { Extracts query params from the end of an array **/ -export function extractQueryParams(array: T[]): [T[], Dict | null] { +export function extractQueryParams( + array: T[] | [...T[], QueryParamsContainer] +): [T[], QueryParams | null] { let len = array && array.length, head, queryParams; if (len && len > 0) { let obj = array[len - 1]; - if (isQueryParams(obj)) { + if (isQueryParamsContainer(obj)) { queryParams = obj.queryParams; head = slice.call(array, 0, len - 1); return [head, queryParams]; } } - return [array, null]; + // SAFETY: We confirmed that the last item isn't a QP container + return [array as T[], null]; } -function isQueryParams(obj: unknown): obj is { queryParams: Dict } { - return obj && hasOwnProperty.call(obj, 'queryParams'); +export type QueryParamsContainer = { queryParams: QueryParams }; + +// TODO: Actually check that Dict is QueryParams +function isQueryParamsContainer(obj: unknown): obj is QueryParamsContainer { + if (obj && typeof obj === 'object') { + let cast = obj as QueryParamsContainer; + return ( + 'queryParams' in cast && Object.keys(cast.queryParams).every((k) => typeof k === 'string') + ); + } + return false; } /** diff --git a/package.json b/package.json index ba4ef60f..ddfab0f4 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,9 @@ "route-recognizer": "^0.3.4", "rsvp": "^4.8.5" }, + "resolutions": { + "typescript": "^4.5.5" + }, "peerDependencies": { "route-recognizer": "^0.3.4", "rsvp": "^4.8.5" diff --git a/tests/query_params_test.ts b/tests/query_params_test.ts index c80b5ba3..80860c64 100644 --- a/tests/query_params_test.ts +++ b/tests/query_params_test.ts @@ -13,7 +13,7 @@ import { trigger, } from './test_helpers'; -let router: Router, handlers: Dict, expectedUrl: Maybe; +let router: Router>, handlers: Dict, expectedUrl: Maybe; let scenarios = [ { name: 'Sync Get Handler', @@ -52,7 +52,7 @@ scenarios.forEach(function (scenario) { didTransition() {} willTransition() {} triggerEvent( - handlerInfos: RouteInfo[], + handlerInfos: RouteInfo>[], ignoreFailure: boolean, name: string, args: any[] diff --git a/tests/route_info_test.ts b/tests/route_info_test.ts index 3d32e3d9..7fee992f 100644 --- a/tests/route_info_test.ts +++ b/tests/route_info_test.ts @@ -142,7 +142,7 @@ test('UnresolvedRouteInfoByParam gets its model hook called', async function (as test('UnresolvedRouteInfoByObject does NOT get its model hook called', async function (assert) { assert.expect(1); - class TestRouteInfo extends UnresolvedRouteInfoByObject { + class TestRouteInfo extends UnresolvedRouteInfoByObject> { __routeHandler?: Route; get route(): Route { if (this.__routeHandler) { diff --git a/tests/router_test.ts b/tests/router_test.ts index fe9a17b7..f06af611 100644 --- a/tests/router_test.ts +++ b/tests/router_test.ts @@ -2,6 +2,7 @@ import { MatchCallback } from 'route-recognizer'; import Router, { Route, Transition } from 'router'; import { Dict, Maybe } from 'router/core'; import RouteInfo, { + IModel, RouteInfo as PublicRouteInfo, RouteInfoWithAttributes, } from 'router/route-info'; @@ -25,7 +26,7 @@ import { trigger, } from './test_helpers'; -let router: Router; +let router: Router>; let url: string | undefined; let routes: Dict; @@ -33,7 +34,7 @@ function isPresent(maybe: Maybe): maybe is PublicRouteInfo { return maybe !== undefined && maybe !== null; } -let serializers: Dict, expectedUrl: Maybe; +let serializers: Dict>>, expectedUrl: Maybe; let scenarios = [ { name: 'Sync Get Handler', @@ -104,7 +105,7 @@ scenarios.forEach(function (scenario) { this.updateURL(name); } triggerEvent( - handlerInfos: RouteInfo[], + handlerInfos: RouteInfo>[], ignoreFailure: boolean, name: string, args: any[] @@ -157,7 +158,7 @@ scenarios.forEach(function (scenario) { }); }); - function routePath(infos: RouteInfo[]) { + function routePath(infos: RouteInfo>[]) { let path = []; for (let i = 0, l = infos.length; i < l; i++) { @@ -1770,8 +1771,10 @@ scenarios.forEach(function (scenario) { }); test("when transitioning to a new parent and child state, the parent's context should be available to the child's model", function (assert) { + type Post = IModel; + assert.expect(1); - let contexts: Dict[] = []; + let contexts: Array = []; map(assert, function (match) { match('/').to('index'); @@ -1781,16 +1784,16 @@ scenarios.forEach(function (scenario) { }); routes = { - post: createHandler('post', { + post: createHandler('post', { model: function () { return contexts; }, }), - postDetails: createHandler('postDetails', { + postDetails: createHandler('postDetails', { name: 'postDetails', - afterModel: function (_model: Dict, transition: Transition) { - contexts.push(transition.resolvedModels.post!); + afterModel: function (_model: Post, transition: Transition) { + contexts.push(transition.resolvedModels.post as Post | undefined); }, }), }; @@ -1976,12 +1979,8 @@ scenarios.forEach(function (scenario) { 'showFilteredPosts', 'going to same route' ); - assert.equal( - transition.from && transition.from.params.filter_id, - 'amazing', - 'old params' - ); - assert.equal(transition.to && transition.to.params.filter_id, 'sad', 'new params'); + assert.equal(transition.from?.params?.filter_id, 'amazing', 'old params'); + assert.equal(transition.to?.params?.filter_id, 'sad', 'new params'); assert.equal( postIndexHandler.context, posts, @@ -2309,6 +2308,8 @@ scenarios.forEach(function (scenario) { }); test('transition.resolvedModels after redirects b/w routes', function (assert) { + type Application = { app: boolean } & IModel; + assert.expect(3); map(assert, function (match) { @@ -2321,7 +2322,7 @@ scenarios.forEach(function (scenario) { let app = { app: true }; routes = { - application: createHandler('application', { + application: createHandler('application', { model: function () { assert.ok(true, 'application#model'); return app; @@ -2331,7 +2332,7 @@ scenarios.forEach(function (scenario) { peter: createHandler('peter', { model: function (_params: Dict, transition: Transition) { assert.deepEqual( - transition.resolvedModels.application, + transition.resolvedModels.application as Application, app, 'peter: resolvedModel correctly stored in resolvedModels for parent route' ); @@ -2341,7 +2342,7 @@ scenarios.forEach(function (scenario) { wagenet: createHandler('wagenet', { model: function (_params: Dict, transition: Transition) { assert.deepEqual( - transition.resolvedModels.application, + transition.resolvedModels.application as Application | undefined, app, 'wagenet: resolvedModel correctly stored in resolvedModels for parent route' ); @@ -2353,11 +2354,13 @@ scenarios.forEach(function (scenario) { }); test('transition.resolvedModels after redirects within the same route', function (assert) { + type Admin = IModel & { admin: boolean }; + let admin = { admin: true }, redirect = true; routes = { - admin: createHandler('admin', { + admin: createHandler('admin', { model: function () { assert.ok(true, 'admin#model'); return admin; @@ -2367,7 +2370,7 @@ scenarios.forEach(function (scenario) { adminPosts: createHandler('adminPosts', { model: function (_params: Dict, transition: Transition) { assert.deepEqual( - transition.resolvedModels.admin, + transition.resolvedModels.admin as Admin | undefined, admin, 'resolvedModel correctly stored in resolvedModels for parent route' ); @@ -2616,7 +2619,7 @@ scenarios.forEach(function (scenario) { }), }; router.triggerEvent = function ( - handlerInfos: RouteInfo[], + handlerInfos: RouteInfo>[], ignoreFailure: boolean, name: string, args: any[] @@ -3008,6 +3011,7 @@ scenarios.forEach(function (scenario) { ); assert.ok(!router.isActive('adminPost'), 'The adminPost handler is inactive'); assert.ok( + // @ts-expect-error BUG: The types don't allow for `null` to be passed here. This behavior seems to be undocumented. !router.isActive('showPost', null), 'The showPost handler is inactive with a null context' ); @@ -3054,20 +3058,22 @@ scenarios.forEach(function (scenario) { }); test('calling transitionTo on a dynamic parent route causes non-dynamic child context to be updated', function (assert) { + type Project = { project_id: string } & IModel; + map(assert, function (match) { match('/project/:project_id').to('project', function (match) { match('/').to('projectIndex'); }); }); - let projectHandler = createHandler('project', { + let projectHandler = createHandler('project', { model: function (params: Dict) { delete params.queryParams; return params; }, }); - let projectIndexHandler = createHandler('projectIndex', { + let projectIndexHandler = createHandler('projectIndex', { model: function (_params: Dict, transition: Transition) { return transition.resolvedModels.project; }, @@ -4927,8 +4933,8 @@ scenarios.forEach(function (scenario) { router.getRoute = function (name) { count++; - return (scenario.getRoute.call(null, name) as Promise).then(function ( - handler: Route + return Promise.resolve(scenario.getRoute.call(null, name)).then(function ( + handler: Route<{}> ) { assert.equal(count, handlerCount); return handler; @@ -4990,13 +4996,14 @@ scenarios.forEach(function (scenario) { // When using an async getHandler serializers need to be loaded separately if (scenario.async) { serializers = { - parent: function (obj: Dict) { + parent: function (obj) { + // TODO: Review this return { one: obj.one, two: obj.two, }; }, - child: function (obj: Dict) { + child: function (obj) { return { three: obj.three, four: obj.four, diff --git a/tests/test_helpers.ts b/tests/test_helpers.ts index 2fdba80a..c54d434c 100644 --- a/tests/test_helpers.ts +++ b/tests/test_helpers.ts @@ -1,7 +1,7 @@ import Backburner from 'backburner'; import Router, { Route, Transition } from 'router'; import { Dict } from 'router/core'; -import RouteInfo, { UnresolvedRouteInfoByParam } from 'router/route-info'; +import RouteInfo, { IModel, UnresolvedRouteInfoByParam } from 'router/route-info'; import { logAbort, PublicTransition } from 'router/transition'; import { TransitionError } from 'router/transition-state'; import { UnrecognizedURLError } from 'router/unrecognized-url-error'; @@ -53,7 +53,7 @@ function assertAbort(assert: Assert) { // the backburner queue. Helpful for when you want to write // tests that avoid .then callbacks. function transitionTo( - router: Router, + router: Router>, path: string | { queryParams: Dict }, ...context: any[] ) { @@ -62,18 +62,18 @@ function transitionTo( return result; } -function transitionToWithAbort(assert: Assert, router: Router, path: string) { +function transitionToWithAbort(assert: Assert, router: Router>, path: string) { router.transitionTo(path).then(shouldNotHappen(assert), assertAbort(assert)); flushBackburner(); } -function replaceWith(router: Router, path: string) { +function replaceWith(router: Router>, path: string) { let result = router.transitionTo.apply(router, [path]).method('replace'); flushBackburner(); return result; } -function handleURL(router: Router, url: string) { +function handleURL(router: Router>, url: string) { let result = router.handleURL.apply(router, [url]); flushBackburner(); return result; @@ -88,7 +88,7 @@ function shouldNotHappen(assert: Assert, _message?: string) { }; } -export function isExiting(route: Route | string, routeInfos: RouteInfo[]) { +export function isExiting(route: Route | string, routeInfos: RouteInfo>[]) { for (let i = 0, len = routeInfos.length; i < len; ++i) { let routeInfo = routeInfos[i]; if (routeInfo.name === route || routeInfo.route === route) { @@ -126,20 +126,20 @@ export { assertAbort, }; -export function createHandler(name: string, options?: Dict): Route { - return Object.assign( - { name, routeName: name, context: undefined, names: [], handler: name, _internalName: name }, +export function createHandler(name: string, options?: Dict): Route { + return (Object.assign( + { name, routeName: name, context: {}, names: [], handler: name, _internalName: name }, options - ); + ) as unknown) as Route; } -export class TestRouter extends Router { +export class TestRouter extends Router> { didTransition() {} willTransition() {} updateURL(_url: string): void {} replaceURL(_url: string): void {} triggerEvent( - _handlerInfos: RouteInfo[], + _handlerInfos: RouteInfo>[], _ignoreFailure: boolean, _name: string, _args: any[] @@ -163,9 +163,9 @@ export class TestRouter extends Router { } } -export function createHandlerInfo(name: string, options: Dict = {}): RouteInfo { - class Stub extends RouteInfo { - constructor(name: string, router: Router, handler?: Route) { +export function createHandlerInfo(name: string, options: Dict = {}): RouteInfo> { + class Stub extends RouteInfo> { + constructor(name: string, router: Router>, handler?: Route) { super(router, name, [], handler); } getModel(_transition: Transition) { @@ -185,7 +185,7 @@ export function createHandlerInfo(name: string, options: Dict = {}): Ro } export function trigger( - handlerInfos: RouteInfo[], + handlerInfos: RouteInfo>[], ignoreFailure: boolean, name: string, ...args: any[] diff --git a/tests/transition-aborted-error_test.ts b/tests/transition-aborted-error_test.ts index 6e684265..44648488 100644 --- a/tests/transition-aborted-error_test.ts +++ b/tests/transition-aborted-error_test.ts @@ -18,7 +18,7 @@ test('correct inheritance and name', function (assert) { // it would be more correct with TransitionAbortedError, but other libraries may rely on this name assert.equal( - error.name, + (error as Error).name, 'TransitionAborted', "TransitionAbortedError has the name 'TransitionAborted'" ); diff --git a/tests/transition_intent_test.ts b/tests/transition_intent_test.ts index c362adfa..682dc814 100644 --- a/tests/transition_intent_test.ts +++ b/tests/transition_intent_test.ts @@ -38,13 +38,13 @@ scenarios.forEach(function (scenario) { } } - let router: Router; + let router: Router>; // Asserts that a handler from a handlerInfo equals an expected valued. // Returns a promise during async scenarios to wait until the handler is ready. function assertHandlerEquals( assert: Assert, - handlerInfo: InternalRouteInfo, + handlerInfo: InternalRouteInfo>, expected: Route ) { if (!scenario.async) { diff --git a/tests/transition_state_test.ts b/tests/transition_state_test.ts index a1a93fe3..b31cf9b9 100644 --- a/tests/transition_state_test.ts +++ b/tests/transition_state_test.ts @@ -45,7 +45,7 @@ test("#resolve delegates to handleInfo objects' resolve()", function (assert) { }), ]; - state.resolve({} as Transition).then(function (result: TransitionState) { + state.resolve({} as Transition).then(function (result: TransitionState>) { assert.deepEqual(result.routeInfos, resolvedHandlerInfos); }); }); @@ -104,7 +104,7 @@ test('Integration w/ HandlerInfos', function (assert) { state .resolve(transition as Transition) - .then(function (result: TransitionState) { + .then(function (result: TransitionState>) { let models = []; for (let i = 0; i < result.routeInfos.length; i++) { models.push(result.routeInfos[i].context); diff --git a/yarn.lock b/yarn.lock index 80a6e94e..addd047a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7557,10 +7557,10 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@~4.0.3: - version "4.0.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389" - integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ== +typescript@^4.5.5, typescript@~4.0.3: + version "4.5.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" + integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" From eb7f37375534d1f1cbff8031829dd11b8ef0bb9b Mon Sep 17 00:00:00 2001 From: Peter Wagenet Date: Tue, 1 Feb 2022 14:22:56 -0800 Subject: [PATCH 2/6] Update some dependencies and node version --- package.json | 19 +- yarn.lock | 507 +++++++++++++++++++++------------------------------ 2 files changed, 211 insertions(+), 315 deletions(-) diff --git a/package.json b/package.json index ddfab0f4..2dde90fe 100644 --- a/package.json +++ b/package.json @@ -40,15 +40,15 @@ "@babel/plugin-transform-modules-commonjs": "^7.12.1", "@types/node": "^14.14.6", "@types/qunit": "^2.9.6", - "@typescript-eslint/eslint-plugin": "^4.6.1", - "@typescript-eslint/parser": "^4.6.1", + "@typescript-eslint/eslint-plugin": "^5.10.2", + "@typescript-eslint/parser": "^5.10.2", "babel-plugin-debug-macros": "^0.3.3", "backburner.js": "^2.6.0", "broccoli-babel-transpiler": "^7.8.0", "broccoli-concat": "^4.2.4", "broccoli-funnel": "^3.0.3", "broccoli-merge-trees": "^4.2.0", - "broccoli-typescript-compiler": "^7.0.0", + "broccoli-typescript-compiler": "^8.0.0", "ember-cli": "~3.22.0", "ember-cli-inject-live-reload": "^2.0.2", "ensure-posix-path": "^1.1.1", @@ -62,17 +62,14 @@ "release-it": "^14.2.1", "release-it-lerna-changelog": "^3.1.0", "route-recognizer": "^0.3.4", - "rsvp": "^4.8.5" - }, - "resolutions": { - "typescript": "^4.5.5" + "rsvp": "^4.8.5", + "typescript": "~4.5.5" }, "peerDependencies": { - "route-recognizer": "^0.3.4", - "rsvp": "^4.8.5" + "route-recognizer": "^0.3.4" }, "engines": { - "node": ">= 10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "publishConfig": { "registry": "https://registry.npmjs.org" @@ -94,7 +91,7 @@ } }, "volta": { - "node": "14.15.0", + "node": "14.17.0", "yarn": "1.22.10" } } diff --git a/yarn.lock b/yarn.lock index addd047a..73220592 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,7 +9,7 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/core@^7.11.6", "@babel/core@^7.12.0": +"@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.3.4": version "7.12.3" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.3.tgz#1b436884e1e3bff6fb1328dc02b208759de92ad8" integrity sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g== @@ -31,37 +31,6 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.3.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.5.tgz#1f15e2cca8ad9a1d78a38ddba612f5e7cdbbd330" - integrity sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.10.5" - "@babel/helper-module-transforms" "^7.10.5" - "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.10.5" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.5" - "@babel/types" "^7.10.5" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.19" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/generator@^7.10.5": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.5.tgz#1b903554bc8c583ee8d25f1e8969732e6b829a69" - integrity sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig== - dependencies: - "@babel/types" "^7.10.5" - jsesc "^2.5.1" - source-map "^0.5.0" - "@babel/generator@^7.12.1", "@babel/generator@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de" @@ -87,13 +56,6 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-member-expression-to-functions@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.5.tgz#172f56e7a63e78112f3a04055f24365af702e7ee" - integrity sha512-HiqJpYD5+WopCXIAbQDG0zye5XYVvcO9w/DHp5GsaGkRUaamLj2bEtu6i8rnGGprAhHM3qidCMgp71HF4endhA== - dependencies: - "@babel/types" "^7.10.5" - "@babel/helper-member-expression-to-functions@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c" @@ -101,13 +63,6 @@ dependencies: "@babel/types" "^7.12.1" -"@babel/helper-module-imports@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" - integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== - dependencies: - "@babel/types" "^7.10.4" - "@babel/helper-module-imports@^7.12.1": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" @@ -115,19 +70,6 @@ dependencies: "@babel/types" "^7.12.5" -"@babel/helper-module-transforms@^7.10.5": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz#120c271c0b3353673fcdfd8c053db3c544a260d6" - integrity sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA== - dependencies: - "@babel/helper-module-imports" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" - "@babel/helper-simple-access" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.5" - lodash "^4.17.19" - "@babel/helper-module-transforms@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" @@ -155,16 +97,6 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-replace-supers@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" - integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.10.4" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - "@babel/helper-replace-supers@^7.12.1": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz#f009a17543bbbbce16b06206ae73b63d3fca68d9" @@ -175,14 +107,6 @@ "@babel/traverse" "^7.12.5" "@babel/types" "^7.12.5" -"@babel/helper-simple-access@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" - integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== - dependencies: - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" - "@babel/helper-simple-access@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" @@ -190,13 +114,6 @@ dependencies: "@babel/types" "^7.12.1" -"@babel/helper-split-export-declaration@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz#2c70576eaa3b5609b24cb99db2888cc3fc4251d1" - integrity sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg== - dependencies: - "@babel/types" "^7.10.4" - "@babel/helper-split-export-declaration@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" @@ -209,15 +126,6 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== -"@babel/helpers@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" - integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== - dependencies: - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - "@babel/helpers@^7.12.1": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" @@ -236,26 +144,12 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.10.4", "@babel/parser@^7.10.5": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.5.tgz#e7c6bf5a7deff957cec9f04b551e2762909d826b" - integrity sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ== - -"@babel/parser@^7.12.3", "@babel/parser@^7.12.5": +"@babel/parser@^7.10.4", "@babel/parser@^7.12.3", "@babel/parser@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.5.tgz#b4af32ddd473c0bfa643bd7ff0728b8e71b81ea0" integrity sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ== -"@babel/plugin-transform-modules-amd@^7.10.5": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" - integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== - dependencies: - "@babel/helper-module-transforms" "^7.10.5" - "@babel/helper-plugin-utils" "^7.10.4" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-amd@^7.12.1": +"@babel/plugin-transform-modules-amd@^7.10.5", "@babel/plugin-transform-modules-amd@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9" integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ== @@ -291,21 +185,6 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/traverse@^7.10.4", "@babel/traverse@^7.10.5": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.5.tgz#77ce464f5b258be265af618d8fddf0536f20b564" - integrity sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.10.5" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.10.4" - "@babel/parser" "^7.10.5" - "@babel/types" "^7.10.5" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.19" - "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.5.tgz#78a0c68c8e8a35e4cacfd31db8bb303d5606f095" @@ -321,16 +200,7 @@ globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.10.4", "@babel/types@^7.10.5": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.5.tgz#d88ae7e2fde86bfbfe851d4d81afa70a997b5d15" - integrity sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q== - dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - lodash "^4.17.19" - to-fast-properties "^2.0.0" - -"@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5": +"@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5": version "7.12.6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.6.tgz#ae0e55ef1cce1fbc881cd26f8234eb3e657edc96" integrity sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA== @@ -484,14 +354,7 @@ "@octokit/plugin-request-log" "^1.0.0" "@octokit/plugin-rest-endpoint-methods" "4.2.0" -"@octokit/types@^5.0.0", "@octokit/types@^5.0.1": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.1.0.tgz#4377a3f39edad3e60753fb5c3c310756f1ded57f" - integrity sha512-OFxUBgrEllAbdEmWp/wNmKIu5EuumKHG4sgy56vjZ8lXPgMhF05c76hmulfOdFHHYRpPj49ygOZJ8wgVsPecuA== - dependencies: - "@types/node" ">= 8" - -"@octokit/types@^5.5.0": +"@octokit/types@^5.0.0", "@octokit/types@^5.0.1", "@octokit/types@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b" integrity sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ== @@ -608,10 +471,10 @@ resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz#9140779736aa2655635ee756e2467d787cfe8a2a" integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A== -"@types/json-schema@^7.0.3": - version "7.0.5" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" - integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== +"@types/json-schema@^7.0.9": + version "7.0.9" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" + integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== "@types/keyv@*": version "3.1.1" @@ -637,12 +500,7 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/node@*", "@types/node@>= 8": - version "14.0.24" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.24.tgz#b0f86f58564fa02a28b68f8b55d4cdec42e3b9d6" - integrity sha512-btt/oNOiDWcSuI721MdL8VQGnjsKjlTMdrKyTcLCKeQp/n4AAMFJ961wMbp+09y8WuGPClDEv07RIItdXKIXAA== - -"@types/node@^14.14.6": +"@types/node@*", "@types/node@>= 8", "@types/node@^14.14.6": version "14.14.6" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.6.tgz#146d3da57b3c636cc0d1769396ce1cfa8991147f" integrity sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw== @@ -700,75 +558,85 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== -"@typescript-eslint/eslint-plugin@^4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.6.1.tgz#99d77eb7a016fd5a5e749d2c44a7e4c317eb7da3" - integrity sha512-SNZyflefTMK2JyrPfFFzzoy2asLmZvZJ6+/L5cIqg4HfKGiW2Gr1Go1OyEVqne/U4QwmoasuMwppoBHWBWF2nA== +"@typescript-eslint/eslint-plugin@^5.10.2": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.2.tgz#f8c1d59fc37bd6d9d11c97267fdfe722c4777152" + integrity sha512-4W/9lLuE+v27O/oe7hXJKjNtBLnZE8tQAFpapdxwSVHqtmIoPB1gph3+ahNwVuNL37BX7YQHyGF9Xv6XCnIX2Q== dependencies: - "@typescript-eslint/experimental-utils" "4.6.1" - "@typescript-eslint/scope-manager" "4.6.1" - debug "^4.1.1" + "@typescript-eslint/scope-manager" "5.10.2" + "@typescript-eslint/type-utils" "5.10.2" + "@typescript-eslint/utils" "5.10.2" + debug "^4.3.2" functional-red-black-tree "^1.0.1" - regexpp "^3.0.0" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/experimental-utils@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.6.1.tgz#a9c691dfd530a9570274fe68907c24c07a06c4aa" - integrity sha512-qyPqCFWlHZXkEBoV56UxHSoXW2qnTr4JrWVXOh3soBP3q0o7p4pUEMfInDwIa0dB/ypdtm7gLOS0hg0a73ijfg== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.6.1" - "@typescript-eslint/types" "4.6.1" - "@typescript-eslint/typescript-estree" "4.6.1" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - -"@typescript-eslint/parser@^4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.6.1.tgz#b801bff67b536ecc4a840ac9289ba2be57e02428" - integrity sha512-lScKRPt1wM9UwyKkGKyQDqf0bh6jm8DQ5iN37urRIXDm16GEv+HGEmum2Fc423xlk5NUOkOpfTnKZc/tqKZkDQ== - dependencies: - "@typescript-eslint/scope-manager" "4.6.1" - "@typescript-eslint/types" "4.6.1" - "@typescript-eslint/typescript-estree" "4.6.1" - debug "^4.1.1" - -"@typescript-eslint/scope-manager@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.6.1.tgz#21872b91cbf7adfc7083f17b8041149148baf992" - integrity sha512-f95+80r6VdINYscJY1KDUEDcxZ3prAWHulL4qRDfNVD0I5QAVSGqFkwHERDoLYJJWmEAkUMdQVvx7/c2Hp+Bjg== - dependencies: - "@typescript-eslint/types" "4.6.1" - "@typescript-eslint/visitor-keys" "4.6.1" - -"@typescript-eslint/types@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.6.1.tgz#d3ad7478f53f22e7339dc006ab61aac131231552" - integrity sha512-k2ZCHhJ96YZyPIsykickez+OMHkz06xppVLfJ+DY90i532/Cx2Z+HiRMH8YZQo7a4zVd/TwNBuRCdXlGK4yo8w== - -"@typescript-eslint/typescript-estree@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.6.1.tgz#6025cce724329413f57e4959b2d676fceeca246f" - integrity sha512-/J/kxiyjQQKqEr5kuKLNQ1Finpfb8gf/NpbwqFFYEBjxOsZ621r9AqwS9UDRA1Rrr/eneX/YsbPAIhU2rFLjXQ== - dependencies: - "@typescript-eslint/types" "4.6.1" - "@typescript-eslint/visitor-keys" "4.6.1" - debug "^4.1.1" - globby "^11.0.1" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" + ignore "^5.1.8" + regexpp "^3.2.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.10.2": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.10.2.tgz#b6076d27cc5499ce3f2c625f5ccde946ecb7db9a" + integrity sha512-JaNYGkaQVhP6HNF+lkdOr2cAs2wdSZBoalE22uYWq8IEv/OVH0RksSGydk+sW8cLoSeYmC+OHvRyv2i4AQ7Czg== + dependencies: + "@typescript-eslint/scope-manager" "5.10.2" + "@typescript-eslint/types" "5.10.2" + "@typescript-eslint/typescript-estree" "5.10.2" + debug "^4.3.2" + +"@typescript-eslint/scope-manager@5.10.2": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.10.2.tgz#92c0bc935ec00f3d8638cdffb3d0e70c9b879639" + integrity sha512-39Tm6f4RoZoVUWBYr3ekS75TYgpr5Y+X0xLZxXqcZNDWZdJdYbKd3q2IR4V9y5NxxiPu/jxJ8XP7EgHiEQtFnw== + dependencies: + "@typescript-eslint/types" "5.10.2" + "@typescript-eslint/visitor-keys" "5.10.2" + +"@typescript-eslint/type-utils@5.10.2": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.10.2.tgz#ad5acdf98a7d2ab030bea81f17da457519101ceb" + integrity sha512-uRKSvw/Ccs5FYEoXW04Z5VfzF2iiZcx8Fu7DGIB7RHozuP0VbKNzP1KfZkHBTM75pCpsWxIthEH1B33dmGBKHw== + dependencies: + "@typescript-eslint/utils" "5.10.2" + debug "^4.3.2" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.10.2": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.10.2.tgz#604d15d795c4601fffba6ecb4587ff9fdec68ce8" + integrity sha512-Qfp0qk/5j2Rz3p3/WhWgu4S1JtMcPgFLnmAKAW061uXxKSa7VWKZsDXVaMXh2N60CX9h6YLaBoy9PJAfCOjk3w== + +"@typescript-eslint/typescript-estree@5.10.2": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.2.tgz#810906056cd3ddcb35aa333fdbbef3713b0fe4a7" + integrity sha512-WHHw6a9vvZls6JkTgGljwCsMkv8wu8XU8WaYKeYhxhWXH/atZeiMW6uDFPLZOvzNOGmuSMvHtZKd6AuC8PrwKQ== + dependencies: + "@typescript-eslint/types" "5.10.2" + "@typescript-eslint/visitor-keys" "5.10.2" + debug "^4.3.2" + globby "^11.0.4" + is-glob "^4.0.3" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.10.2": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.10.2.tgz#1fcd37547c32c648ab11aea7173ec30060ee87a8" + integrity sha512-vuJaBeig1NnBRkf7q9tgMLREiYD7zsMrsN1DA3wcoMDvr3BTFiIpKjGiYZoKPllfEwN7spUjv7ZqD+JhbVjEPg== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.10.2" + "@typescript-eslint/types" "5.10.2" + "@typescript-eslint/typescript-estree" "5.10.2" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" -"@typescript-eslint/visitor-keys@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.6.1.tgz#6b125883402d8939df7b54528d879e88f7ba3614" - integrity sha512-owABze4toX7QXwOLT3/D5a8NecZEjEWU1srqxENTfqsY3bwVnl3YYbOh6s1rp2wQKO9RTHFGjKes08FgE7SVMw== +"@typescript-eslint/visitor-keys@5.10.2": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.2.tgz#fdbf272d8e61c045d865bd6c8b41bea73d222f3d" + integrity sha512-zHIhYGGGrFJvvyfwHk5M08C5B5K4bewkm+rrvNTKk1/S15YHR+SA/QUF8ZWscXSfEaB8Nn2puZj+iHcoxVOD/Q== dependencies: - "@typescript-eslint/types" "4.6.1" - eslint-visitor-keys "^2.0.0" + "@typescript-eslint/types" "5.10.2" + eslint-visitor-keys "^3.0.0" abbrev@1: version "1.1.1" @@ -827,17 +695,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.10.2: - version "6.12.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" - integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1199,9 +1057,9 @@ bluebird@^3.1.1, bluebird@^3.4.6: integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== blueimp-md5@^2.10.0: - version "2.16.0" - resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.16.0.tgz#9018bb805e4ee05512e0e8cbdb9305eeecbdc87c" - integrity sha512-j4nzWIqEFpLSbdhUApHRGDwfXbV8ALhqOn+FY5L6XBdKPAXU9BpGgFSbDsgqogfqPPR9R2WooseWCsfhfEC6uQ== + version "2.19.0" + resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.19.0.tgz#b53feea5498dcb53dc6ec4b823adb84b729c4af0" + integrity sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w== body-parser@1.19.0: version "1.19.0" @@ -1602,7 +1460,7 @@ broccoli-stew@^3.0.0: symlink-or-copy "^1.2.0" walk-sync "^1.1.3" -broccoli-typescript-compiler@^7.0.0: +broccoli-typescript-compiler@^8.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/broccoli-typescript-compiler/-/broccoli-typescript-compiler-7.0.0.tgz#a7792ceb8db2ddb3d57e91e429750b4ce9568626" integrity sha512-9BSZc9tVdm3SEbR7uyMQ6XqYMQWkdCvp2dPlZYnENEqbUToCIVOJuOZ24nrenR6N4eTZPnY3R99DkgyoxmRp5A== @@ -2291,14 +2149,7 @@ debug@2.6.9, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.3. dependencies: ms "2.0.0" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@~4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - -debug@4.2.0, debug@^4.0.0: +debug@4, debug@4.2.0, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== @@ -2312,6 +2163,13 @@ debug@^3.0.1, debug@^3.1.0, debug@^3.1.1: dependencies: ms "^2.1.1" +debug@^4.3.2: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + debug@~3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -2319,6 +2177,13 @@ debug@~3.1.0: dependencies: ms "2.0.0" +debug@~4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -2822,14 +2687,6 @@ eslint-plugin-prettier@^3.1.4: dependencies: prettier-linter-helpers "^1.0.0" -eslint-scope@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" - integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -2838,13 +2695,20 @@ eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^2.0.0, eslint-utils@^2.1.0: +eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" @@ -2855,6 +2719,11 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== +eslint-visitor-keys@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz#6fbb166a6798ee5991358bc2daa1ba76cc1254a1" + integrity sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ== + eslint@^7.12.1: version "7.12.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.12.1.tgz#bd9a81fa67a6cfd51656cdb88812ce49ccec5801" @@ -2929,13 +2798,6 @@ esquery@^1.2.0: dependencies: estraverse "^5.1.0" -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== - dependencies: - estraverse "^4.1.0" - esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" @@ -2943,17 +2805,12 @@ esrecurse@^4.3.0: dependencies: estraverse "^5.2.0" -estraverse@^4.1.0, estraverse@^4.1.1: +estraverse@^4.1.1: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" - integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== - -estraverse@^5.2.0: +estraverse@^5.1.0, estraverse@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== @@ -2983,7 +2840,7 @@ exec-sh@^0.3.2: resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5" integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A== -execa@4.1.0: +execa@4.1.0, execa@^4.0.2, execa@^4.0.3: version "4.1.0" resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== @@ -3011,21 +2868,6 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^4.0.2, execa@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.3.tgz#0a34dabbad6d66100bd6f2c576c8669403f317f2" - integrity sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A== - dependencies: - cross-spawn "^7.0.0" - get-stream "^5.0.0" - human-signals "^1.1.1" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.0" - onetime "^5.1.0" - signal-exit "^3.0.2" - strip-final-newline "^2.0.0" - exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -3152,6 +2994,17 @@ fast-glob@^3.0.3, fast-glob@^3.1.1: micromatch "^4.0.2" picomatch "^2.2.1" +fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -3626,6 +3479,13 @@ glob-parent@^5.0.0, glob-parent@^5.1.0: dependencies: is-glob "^4.0.1" +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + glob@^5.0.10: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" @@ -3707,7 +3567,7 @@ globby@10.0.0: merge2 "^1.2.3" slash "^3.0.0" -globby@11.0.1, globby@^11.0.1: +globby@11.0.1: version "11.0.1" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== @@ -3719,6 +3579,18 @@ globby@11.0.1, globby@^11.0.1: merge2 "^1.3.0" slash "^3.0.0" +globby@^11.0.4: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + globrex@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" @@ -4109,6 +3981,11 @@ ignore@^5.1.1, ignore@^5.1.4: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== +ignore@^5.1.8, ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + import-cwd@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-3.0.0.tgz#20845547718015126ea9b3676b7592fb8bd4cf92" @@ -4393,6 +4270,13 @@ is-glob@^4.0.0, is-glob@^4.0.1: dependencies: is-extglob "^2.1.1" +is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + is-hexadecimal@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" @@ -4999,16 +4883,11 @@ lodash.uniqby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI= -lodash@4.17.20, lodash@^4.17.20: +lodash@4.17.20, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: - version "4.17.19" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" - integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== - log-symbols@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" @@ -5214,7 +5093,7 @@ merge-trees@^2.0.0: fs-updater "^1.0.4" heimdalljs "^0.2.5" -merge2@^1.2.3, merge2@^1.3.0: +merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -5259,6 +5138,14 @@ micromatch@^4.0.2: braces "^3.0.1" picomatch "^2.0.5" +micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + mime-db@1.44.0, "mime-db@>= 1.43.0 < 2": version "1.44.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" @@ -5905,7 +5792,7 @@ parse-entities@^2.0.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" -parse-json@5.1.0: +parse-json@5.1.0, parse-json@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646" integrity sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ== @@ -5923,16 +5810,6 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" -parse-json@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" - integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - lines-and-columns "^1.1.6" - parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" @@ -6061,6 +5938,11 @@ picomatch@^2.0.5, picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +picomatch@^2.2.3: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + pidtree@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" @@ -6355,11 +6237,16 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^3.0.0, regexpp@^3.1.0: +regexpp@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== +regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + registry-auth-token@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.0.tgz#1d37dffda72bbecd0f581e4715540213a65eb7da" @@ -6701,6 +6588,13 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + send@0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -7518,10 +7412,10 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== -tsutils@^3.17.1: - version "3.17.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" - integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" @@ -7557,7 +7451,12 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@^4.5.5, typescript@~4.0.3: +typescript@~4.0.3: + version "4.0.8" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.8.tgz#5739105541db80a971fdbd0d56511d1a6f17d37f" + integrity sha512-oz1765PN+imfz1MlZzSZPtC/tqcwsCyIYA8L47EkRnRW97ztRk83SzMiWLrnChC0vqoYxSU1fcFUDA5gV/ZiPg== + +typescript@~4.5.5: version "4.5.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== From 609713dfbd1a23d5b5c48cc3b1c3c058f27c8963 Mon Sep 17 00:00:00 2001 From: Peter Wagenet Date: Tue, 1 Feb 2022 15:09:05 -0800 Subject: [PATCH 3/6] Fix CI --- .github/workflows/ci.yml | 2 +- package.json | 2 +- yarn.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f95f1aa..6bbca0a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: - node: ['10', '12', '14', '15'] + node: ['12', '14', '16', '17'] steps: - uses: actions/checkout@v1 diff --git a/package.json b/package.json index 2dde90fe..3d4f8bdb 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "broccoli-concat": "^4.2.4", "broccoli-funnel": "^3.0.3", "broccoli-merge-trees": "^4.2.0", - "broccoli-typescript-compiler": "^8.0.0", + "broccoli-typescript-compiler": "^7.0.0", "ember-cli": "~3.22.0", "ember-cli-inject-live-reload": "^2.0.2", "ensure-posix-path": "^1.1.1", diff --git a/yarn.lock b/yarn.lock index 73220592..c3bfca1b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1460,7 +1460,7 @@ broccoli-stew@^3.0.0: symlink-or-copy "^1.2.0" walk-sync "^1.1.3" -broccoli-typescript-compiler@^8.0.0: +broccoli-typescript-compiler@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/broccoli-typescript-compiler/-/broccoli-typescript-compiler-7.0.0.tgz#a7792ceb8db2ddb3d57e91e429750b4ce9568626" integrity sha512-9BSZc9tVdm3SEbR7uyMQ6XqYMQWkdCvp2dPlZYnENEqbUToCIVOJuOZ24nrenR6N4eTZPnY3R99DkgyoxmRp5A== From 814309dfe54fbdbb66fa0d1b680d792a8c93b914 Mon Sep 17 00:00:00 2001 From: Peter Wagenet Date: Tue, 1 Feb 2022 15:30:30 -0800 Subject: [PATCH 4/6] Switch to rest-params --- .eslintrc.js | 1 - tests/test_helpers.ts | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 63c9d620..492cce86 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -48,7 +48,6 @@ module.exports = { // TODO: stop disabling these rules 'prefer-const': 'off', - 'prefer-rest-params': 'off', 'no-prototype-builtins': 'off', '@typescript-eslint/ban-types': 'off', '@typescript-eslint/ban-ts-comment': 'off', diff --git a/tests/test_helpers.ts b/tests/test_helpers.ts index c54d434c..6acf0cb9 100644 --- a/tests/test_helpers.ts +++ b/tests/test_helpers.ts @@ -25,19 +25,19 @@ let test = QUnit.test; function module(name: string, options?: any) { options = options || {}; QUnit.module(name, { - beforeEach: function () { + beforeEach: function (...args: unknown[]) { configure('async', customAsync); bb.begin(); if (options.setup) { - options.setup.apply(this, arguments); + options.setup.apply(this, args); } }, - afterEach: function () { + afterEach: function (...args: unknown[]) { bb.end(); if (options.teardown) { - options.teardown.apply(this, arguments); + options.teardown.apply(this, args); } }, }); From a9b976c4e1fbb2d7915491cb2b87677ef402a398 Mon Sep 17 00:00:00 2001 From: Peter Wagenet Date: Tue, 1 Feb 2022 15:35:59 -0800 Subject: [PATCH 5/6] Remove @ts-ignore and improve test types --- .eslintrc.js | 1 - tests/route_info_test.ts | 10 ++++++---- tests/test_helpers.ts | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 492cce86..0a29af8b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -50,7 +50,6 @@ module.exports = { 'prefer-const': 'off', 'no-prototype-builtins': 'off', '@typescript-eslint/ban-types': 'off', - '@typescript-eslint/ban-ts-comment': 'off', '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', diff --git a/tests/route_info_test.ts b/tests/route_info_test.ts index 7fee992f..05b8e682 100644 --- a/tests/route_info_test.ts +++ b/tests/route_info_test.ts @@ -1,6 +1,7 @@ import { Transition } from 'router'; import { Dict } from 'router/core'; import { + IModel, ResolvedRouteInfo, Route, toReadOnlyRouteInfo, @@ -140,11 +141,13 @@ test('UnresolvedRouteInfoByParam gets its model hook called', async function (as }); test('UnresolvedRouteInfoByObject does NOT get its model hook called', async function (assert) { + type Dorkleton = { name: string } & IModel; + assert.expect(1); - class TestRouteInfo extends UnresolvedRouteInfoByObject> { - __routeHandler?: Route; - get route(): Route { + class TestRouteInfo extends UnresolvedRouteInfoByObject> { + __routeHandler?: Route; + get route(): Route { if (this.__routeHandler) { return this.__routeHandler; } @@ -164,7 +167,6 @@ test('UnresolvedRouteInfoByObject does NOT get its model hook called', async fun ); let resolvedRouteInfo = await routeInfo.resolve({} as Transition); - // @ts-ignore assert.equal(resolvedRouteInfo.context!.name, 'dorkletons'); }); diff --git a/tests/test_helpers.ts b/tests/test_helpers.ts index 6acf0cb9..6e24baf5 100644 --- a/tests/test_helpers.ts +++ b/tests/test_helpers.ts @@ -133,13 +133,13 @@ export function createHandler(name: string, options?: Dict; } -export class TestRouter extends Router> { +export class TestRouter extends Router { didTransition() {} willTransition() {} updateURL(_url: string): void {} replaceURL(_url: string): void {} triggerEvent( - _handlerInfos: RouteInfo>[], + _handlerInfos: RouteInfo[], _ignoreFailure: boolean, _name: string, _args: any[] From d11de202f2f774150e24bdcdbc48e677f00ee6f9 Mon Sep 17 00:00:00 2001 From: Peter Wagenet Date: Tue, 1 Feb 2022 15:40:10 -0800 Subject: [PATCH 6/6] Enable more eslint rules --- .eslintrc.js | 13 +++++++++---- lib/router/route-info.ts | 2 +- tests/test_helpers.ts | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 0a29af8b..ad8be3c0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -49,11 +49,16 @@ module.exports = { // TODO: stop disabling these rules 'prefer-const': 'off', 'no-prototype-builtins': 'off', - '@typescript-eslint/ban-types': 'off', - '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/ban-types': [ + 'error', + { + extendDefaults: true, + types: { + '{}': false, + }, + }, + ], '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/no-this-alias': 'off', }, }, diff --git a/lib/router/route-info.ts b/lib/router/route-info.ts index 66997594..29eeaa56 100644 --- a/lib/router/route-info.ts +++ b/lib/router/route-info.ts @@ -22,7 +22,7 @@ export interface Route { routeName: string; _internalName: string; context: T | undefined; - events?: Dict; + events?: Dict<(...args: unknown[]) => unknown>; model?(params: Dict, transition: Transition): PromiseLike | undefined | T; deserialize?(params: Dict, transition: Transition): T | PromiseLike | undefined; serialize?(model: T | undefined, params: string[]): Dict | undefined; diff --git a/tests/test_helpers.ts b/tests/test_helpers.ts index 6e24baf5..56a8c285 100644 --- a/tests/test_helpers.ts +++ b/tests/test_helpers.ts @@ -11,7 +11,7 @@ import { isTransitionAborted } from 'router/transition-aborted-error'; QUnit.config.testTimeout = 1000; let bb = new Backburner(['promises']); -function customAsync(callback: Function, promise: Promise) { +function customAsync(callback: (...args: unknown[]) => unknown, promise: Promise) { bb.defer('promises', promise, callback, promise); }