UNPKG

ngx-route-manager

Version:
204 lines (192 loc) 6.38 kB
import * as i0 from '@angular/core'; import { signal, InjectionToken, APP_INITIALIZER, NgModule, computed } from '@angular/core'; import { NavigationEnd, Router, ActivatedRoute } from '@angular/router'; import { filter, of, map } from 'rxjs'; const internalSignalRoute = signal(undefined); // Factory function to initialize the service function listenForRouteChange(router, route) { return () => { internalSignalRoute.set(route); const subscription = router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => { // Traverse to the most deeply activated route let route = router.routerState.root; while (route.firstChild) { route = route.firstChild; } internalSignalRoute.set(route); }); return () => subscription.unsubscribe(); }; } const NGX_ROUTE_MANAGER_CONFIG = new InjectionToken('NGX_ROUTE_MANAGER_CONFIG'); class NgxRouteManagerModule { static forRoot(config) { return { ngModule: NgxRouteManagerModule, providers: [ { provide: NGX_ROUTE_MANAGER_CONFIG, useValue: config }, { provide: APP_INITIALIZER, useFactory: listenForRouteChange, deps: [Router, ActivatedRoute], multi: true } ] }; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: NgxRouteManagerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.5", ngImport: i0, type: NgxRouteManagerModule }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: NgxRouteManagerModule }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: NgxRouteManagerModule, decorators: [{ type: NgModule, args: [{}] }] }); // type ExtractParams<T extends string> = // T extends `${infer _Start}:${infer Param}/${infer Rest}` ? // Param | ExtractParams<Rest> : // T extends `${infer _Start}:${infer Param}` ? // Param : // string; function createUrlFunction(template) { return ((args) => { if (args === undefined && template.includes(':')) { throw new Error('Arguments are required for this template'); } if (args !== undefined && !template.includes(':')) { throw new Error('This template does not accept any arguments'); } return template.replace(/:([a-zA-Z]+)/g, (_, key) => { return args?.[key] ?? ''; }); }); } class NgxParam { /** * Name of the param */ _name = ''; get name() { return this._name; } /** * Returns the current snapshoot of the value in the url route */ snapshotValue = computed(() => { if (!internalSignalRoute()) { return ''; } else { return internalSignalRoute()?.snapshot.paramMap.get(this.name) || ''; } }); /** * Listens for change on param in the route */ listenForValue = computed(() => { if (!internalSignalRoute()) { console.log(internalSignalRoute()); return of(''); } else { return internalSignalRoute()?.paramMap .pipe(filter(paramMap => paramMap.has(this.name)), map(paramMap => paramMap.get(this.name) || '')); } }); constructor(name) { this._name = name; } } function urlToNgxParam(route) { const segments = route.split('/'); const params = {}; segments.forEach(segment => { if (segment.startsWith(':')) { const param = segment.slice(1); if (!/^[A-Za-z]+$/.test(param)) { throw new Error(`${param} must contain only alphabets in ${route}`); } params[param] = new NgxParam(param); } }); return params; } class NgxRoute { /** * The url path */ path = ''; /** * Function to generate the url, requiring the right params */ fn = {}; /** * Stores all the params as */ _params = {}; /** * Stores all the segments as */ _segments = {}; constructor(path, fn, params, segments) { this.path = path; this.fn = fn; this._params = params; this._segments = segments; } /** * All params store as an object */ get params() { return this._params; } /** * All segments store as an object */ get segments() { return this._segments; } } /** * Extracts static segments from a URL pattern and returns them as a typed object * Types are automatically inferred from the URL pattern * @param url - The URL pattern to parse * @returns Object with extracted segments with automatic type inference */ function urlToSegments(url) { // Remove leading and trailing slashes const cleanUrl = url.replace(/^\/+|\/+$/g, ''); // Split the URL into segments const segments = cleanUrl.split('/'); // Initialize result object const result = {}; // Process each segment segments.forEach(segment => { // Skip dynamic segments (those starting with ':') if (segment.startsWith(':') || segment.trim().length == 0) { return; } if (!/^[a-zA-Z][a-zA-Z0-9-_]*$/.test(segment)) { throw new Error(`Segment '${segment}' must start with a letter and contain only letters, numbers, hyphens, or underscores in ${url}`); } // Add valid segments to result object result[segment] = segment; }); return result; } function generateNgxRoute(urlPattern) { const pattern = urlPattern ? urlPattern : ''; const ngxRoute = new NgxRoute(pattern, createUrlFunction(pattern), urlToNgxParam(pattern), urlToSegments(pattern)); return ngxRoute; } /* * Public API Surface of ngx-route-manager */ /** * Generated bundle index. Do not edit. */ export { NgxRouteManagerModule, generateNgxRoute }; //# sourceMappingURL=ngx-route-manager.mjs.map