ngx-foresight
Version:
<p align="center"> <img src="https://akshykhade.github.io/ngx-foresight/logo.svg" width="305px"> </p> <br/> <p align="center"> <a href="https://www.npmjs.com/package/ngx-foresight"> <img src="https://img.shields.io/npm/v/ngx-foresight.svg?style=fo
216 lines (208 loc) • 8.31 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, inject, Directive, Input } from '@angular/core';
import * as i1 from '@angular/router';
import { PRIMARY_OUTLET, Router, RouterPreloader } from '@angular/router';
import { ForesightManager } from 'js.foresight';
import { EMPTY } from 'rxjs';
// Using a global registry so we can keep it populated across lazy-loaded
// modules with different parent injectors which create instance of the registry.
const globalRegistry = [];
class PrefetchRegistry {
router;
trees = globalRegistry;
constructor(router) {
this.router = router;
}
add(tree) {
this.trees.push(tree);
}
shouldPrefetch(url) {
const tree = this.router.parseUrl(url);
return this.trees.some(containsTree.bind(null, tree));
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PrefetchRegistry, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PrefetchRegistry, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PrefetchRegistry, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: i1.Router }] });
function containsQueryParams(container, containee) {
// TODO: This does not handle array params correctly.
return (Object.keys(containee).length <= Object.keys(container).length &&
Object.keys(containee).every((key) => containee[key] === container[key]));
}
function containsTree(containee, container) {
return (containsQueryParams(container.queryParams, containee.queryParams) &&
containsSegmentGroup(container.root, containee.root, containee.root.segments));
}
function containsSegmentGroup(container, containee, containeePaths) {
if (container.segments.length > containeePaths.length) {
const current = container.segments.slice(0, containeePaths.length);
if (!equalPath(current, containeePaths))
return false;
if (containee.hasChildren())
return false;
return true;
}
else if (container.segments.length === containeePaths.length) {
if (!equalPath(container.segments, containeePaths))
return false;
if (!containee.hasChildren())
return true;
for (const c in containee.children) {
if (!container.children[c])
break;
if (containsSegmentGroup(container.children[c], containee.children[c], containee.children[c].segments))
return true;
}
return false;
}
else {
const current = containeePaths.slice(0, container.segments.length);
const next = containeePaths.slice(container.segments.length);
if (!equalPath(container.segments, current))
return false;
if (!container.children[PRIMARY_OUTLET])
return false;
return containsSegmentGroup(container.children[PRIMARY_OUTLET], containee, next);
}
}
function equalPath(as, bs) {
if (as.length !== bs.length)
return false;
return as.every((a, i) => a.path === bs[i].path ||
a.path.startsWith(':') ||
bs[i].path.startsWith(':'));
}
class ForesightjsDirective {
elementRef;
router = inject(Router);
registry = inject(PrefetchRegistry);
preloader = inject(RouterPreloader);
routerLink = '';
href = '';
name = undefined;
unregisterRef = () => { };
constructor(elementRef) {
this.elementRef = elementRef;
}
ngOnInit() {
const { unregister } = ForesightManager.instance.register({
element: this.elementRef.nativeElement,
name: this.name,
callback: () => {
if (!this.routerLink && !this.href) {
return;
}
const tree = this.router.parseUrl(this.routerLink || this.href);
this.registry.add(tree);
this.preloader.preload().subscribe(() => void 0);
},
});
this.unregisterRef = unregister;
}
ngOnDestroy() {
this.unregisterRef();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ForesightjsDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: ForesightjsDirective, isStandalone: true, selector: "[foresightjs],[registerForesight]", inputs: { routerLink: "routerLink", href: "href", name: ["registerForesight", "name"] }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ForesightjsDirective, decorators: [{
type: Directive,
args: [{
selector: '[foresightjs],[registerForesight]',
standalone: true,
}]
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { routerLink: [{
type: Input
}], href: [{
type: Input
}], name: [{
type: Input,
args: ['registerForesight']
}] } });
const findPath = (config, route) => {
config = config.slice();
const parent = new Map();
const visited = new Set();
while (config.length) {
const el = config.shift();
if (!el) {
continue;
}
visited.add(el);
if (el === route)
break;
let children = el.children || [];
const current = el._loadedRoutes || [];
for (const route of current) {
if (route && route.children) {
children = children.concat(route.children);
}
}
children.forEach((r) => {
if (visited.has(r))
return;
parent.set(r, el);
config.push(r);
});
}
let path = '';
let current = route;
while (current) {
if (isPrimaryRoute(current)) {
path = `/${current.path}${path}`;
}
else {
path = `/(${current.outlet}:${current.path}${path})`;
}
current = parent.get(current);
}
// For routes with empty paths (the resulted string will look like `///section/sub-section`)
return path.replace(/[\/]+/, '/');
};
function isPrimaryRoute(route) {
return route.outlet === PRIMARY_OUTLET || !route.outlet;
}
class ForesightjsStrategy {
registry;
router;
loading = new Set();
constructor(registry, router) {
this.registry = registry;
this.router = router;
}
preload(route, load) {
if (this.loading.has(route)) {
// Don't preload the same route twice
return EMPTY;
}
// Prevent from preloading
if (route.data && route.data['preload'] === false) {
return EMPTY;
}
const fullPath = findPath(this.router.config, route);
if (this.registry.shouldPrefetch(fullPath)) {
this.loading.add(route);
return load();
}
return EMPTY;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ForesightjsStrategy, deps: [{ token: PrefetchRegistry }, { token: i1.Router }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ForesightjsStrategy, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ForesightjsStrategy, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: () => [{ type: PrefetchRegistry }, { type: i1.Router }] });
/*
* Public API Surface of ngx-foresight
*/
/**
* Generated bundle index. Do not edit.
*/
export { ForesightjsDirective, ForesightjsStrategy };
//# sourceMappingURL=ngx-foresight.mjs.map