packages/router/src/configuration.ts
import { DI, IContainer, IRegistry } from '@aurelia/kernel';
import { AppTask } from '@aurelia/runtime-html';
import { ViewportCustomElement } from './resources/viewport';
import { ViewportScopeCustomElement } from './resources/viewport-scope';
import { LoadCustomAttribute } from './resources/load';
import { HrefCustomAttribute } from './resources/href';
import { ConsideredActiveCustomAttribute } from './resources/considered-active';
import { IRouter, Router } from './router';
import { IRouterOptions, RouterOptions } from './router-options';
import { BeforeNavigationHookFunction, IRoutingHookOptions, RoutingHook, RoutingHookFunction, RoutingHookIdentity, TransformFromUrlHookFunction, TransformTitleHookFunction, TransformToUrlHookFunction } from './routing-hook';
export const IRouterConfiguration = /*@__PURE__*/DI.createInterface<IRouterConfiguration>('IRouterConfiguration', x => x.singleton(RouterConfiguration));
export interface IRouterConfiguration extends RouterConfiguration { }
export const RouterRegistration = IRouter as unknown as IRegistry;
/**
* Default runtime/environment-agnostic implementations for the following interfaces:
* - `IRouter`
*/
export const DefaultComponents = [
RouterRegistration,
];
export {
ViewportCustomElement,
ViewportScopeCustomElement,
LoadCustomAttribute,
HrefCustomAttribute,
ConsideredActiveCustomAttribute,
};
export const ViewportCustomElementRegistration = ViewportCustomElement as unknown as IRegistry;
export const ViewportScopeCustomElementRegistration = ViewportScopeCustomElement as unknown as IRegistry;
export const LoadCustomAttributeRegistration = LoadCustomAttribute as unknown as IRegistry;
export const HrefCustomAttributeRegistration = HrefCustomAttribute as unknown as IRegistry;
export const ConsideredActiveCustomAttributeRegistration = ConsideredActiveCustomAttribute as unknown as IRegistry;
/**
* Default router resources:
* - Custom Elements: `au-viewport`, `au-nav`
* - Custom Attributes: `goto`, `load`, `href`
*/
export const DefaultResources: IRegistry[] = [
ViewportCustomElement as unknown as IRegistry,
ViewportScopeCustomElement as unknown as IRegistry,
LoadCustomAttribute as unknown as IRegistry,
HrefCustomAttribute as unknown as IRegistry,
ConsideredActiveCustomAttribute as unknown as IRegistry,
];
/**
* A DI configuration object containing router resource registrations
* and the router options API.
*/
export class RouterConfiguration {
// ONLY used during registration to support .customize. Transfered to
// instance property after that.
private static options = RouterOptions.create();
private static configurationCall: ((router: IRouter) => void) = (router: IRouter) => {
router.start();
};
/**
* The router options.
*/
public options!: RouterOptions;
/**
* Register this configuration in a provided container and
* register app tasks for starting and stopping the router.
*
* @param container - The container to register in
*/
public static register(container: IContainer): IContainer {
const _this = container.get(IRouterConfiguration);
// Transfer options (that's possibly modified through .customize)
_this.options = RouterConfiguration.options;
_this.options.setRouterConfiguration(_this);
// Reset defaults
RouterConfiguration.options = RouterOptions.create();
return container.register(
...DefaultComponents,
...DefaultResources,
AppTask.activating(IRouter, RouterConfiguration.configurationCall),
AppTask.activated(IRouter, (router: IRouter) => router.initialLoad() as Promise<void>),
AppTask.deactivated(IRouter, (router: IRouter) => router.stop()),
);
}
/**
* Make it possible to specify options to Router activation.
*
* @param config - Either a config object that's passed to router's
* start or a config function that's called instead of router's start.
*/
public static customize(config?: IRouterOptions | ((router: IRouter) => void)): RouterConfiguration {
if (config === undefined) {
RouterConfiguration.options = RouterOptions.create();
RouterConfiguration.configurationCall = (router: IRouter) => {
router.start();
};
} else if (config instanceof Function) {
RouterConfiguration.configurationCall = config;
} else {
RouterConfiguration.options = RouterOptions.create();
RouterConfiguration.options.apply(config);
}
return RouterConfiguration as unknown as RouterConfiguration;
}
/**
* Create a new container with this configuration applied to it.
*/
public static createContainer(): IContainer {
return this.register(DI.createContainer());
}
/**
* Get the router configuration for a context.
*
* @param context - The context to get the configuration for
*/
public static for(context: IRouter | IContainer): RouterConfiguration {
if (context instanceof Router) {
return context.configuration;
}
return context.get(IRouterConfiguration);
}
/**
* Apply router options.
*
* @param options - The options to apply
* @param firstResetDefaults - Whether the default router options should
* be set before applying the specified options
*/
public apply(options: IRouterOptions, firstResetDefaults: boolean = false): void {
if (firstResetDefaults) {
this.options = RouterOptions.create();
}
this.options.apply(options);
}
/**
* Add a routing hook.
*
* @param hookFunction - The hook callback function
* @param options - Options specifyinig hook type and filters
*/
public addHook(beforeNavigationHookFunction: BeforeNavigationHookFunction, options?: IRoutingHookOptions): RoutingHookIdentity;
public addHook(transformFromUrlHookFunction: TransformFromUrlHookFunction, options?: IRoutingHookOptions): RoutingHookIdentity;
public addHook(transformToUrlHookFunction: TransformToUrlHookFunction, options?: IRoutingHookOptions): RoutingHookIdentity;
public addHook(transformTitleHookFunction: TransformTitleHookFunction, options?: IRoutingHookOptions): RoutingHookIdentity;
public addHook(hookFunction: RoutingHookFunction, options?: IRoutingHookOptions): RoutingHookIdentity;
public addHook(hookFunction: RoutingHookFunction, options?: IRoutingHookOptions): RoutingHookIdentity {
return RoutingHook.add(hookFunction, options);
}
/**
* Remove a routing hook.
*
* @param id - The id of the hook to remove (returned from the addHook call)
*/
public removeHook(id: RoutingHookIdentity): void {
return RoutingHook.remove(id);
}
/**
* Remove all routing hooks.
*/
public removeAllHooks(): void {
return RoutingHook.removeAll();
}
// TODO: This goes in here
// public addRoutes(routes: IRoute[], context?: ICustomElementViewModel | Element): IRoute[] {
// // TODO: This should add to the context instead
// // TODO: Add routes without context to rootScope content (which needs to be created)?
// return [];
// // const viewport = (context !== void 0 ? this.closestViewport(context) : this.rootScope) || this.rootScope as Viewport;
// // return viewport.addRoutes(routes);
// }
// public removeRoutes(routes: IRoute[] | string[], context?: ICustomElementViewModel | Element): void {
// // TODO: This should remove from the context instead
// // const viewport = (context !== void 0 ? this.closestViewport(context) : this.rootScope) || this.rootScope as Viewport;
// // return viewport.removeRoutes(routes);
// }
}