| 
									
										
										
										
											2020-06-01 20:51:36 +00:00
										 |  |  | import * as plugins from './smartrouter.plugins'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-15 18:51:17 +00:00
										 |  |  | const routeLog = (message) => { | 
					
						
							| 
									
										
										
										
											2020-06-01 20:51:36 +00:00
										 |  |  |   console.log(`%c[Router]%c ${message}`, 'color: rgb(255, 105, 100);', 'color: inherit'); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export interface IRouterOptions { | 
					
						
							|  |  |  |   debug?: boolean; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-15 18:51:17 +00:00
										 |  |  | export type THandlerFunction = <T extends object>(routeArg: IRouteInfo) => Promise<any>; | 
					
						
							|  |  |  | export interface IRouteInfo { | 
					
						
							|  |  |  |   path: string; | 
					
						
							| 
									
										
										
										
											2020-11-30 10:14:22 +00:00
										 |  |  |   index: number; | 
					
						
							|  |  |  |   params: { [key: string]: string }; | 
					
						
							| 
									
										
										
										
											2021-09-08 21:46:21 +02:00
										 |  |  |   queryParams: { [key: string]: string }; | 
					
						
							| 
									
										
										
										
											2020-07-15 18:51:17 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-01 20:51:36 +00:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Router | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export class SmartRouter { | 
					
						
							|  |  |  |   public options: IRouterOptions = { | 
					
						
							| 
									
										
										
										
											2020-07-15 18:51:17 +00:00
										 |  |  |     debug: false, | 
					
						
							| 
									
										
										
										
											2020-06-01 20:51:36 +00:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * the routes we are handling | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2020-06-03 14:08:08 +00:00
										 |  |  |   public routes: Array<{ | 
					
						
							|  |  |  |     matchFunction: plugins.pathToRegExp.MatchFunction; | 
					
						
							| 
									
										
										
										
											2020-07-15 18:51:17 +00:00
										 |  |  |     handler: THandlerFunction; | 
					
						
							| 
									
										
										
										
											2020-06-03 14:08:08 +00:00
										 |  |  |   }> = []; | 
					
						
							| 
									
										
										
										
											2020-06-01 20:51:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Creates an instance of Router. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   constructor(optionsArg: IRouterOptions) { | 
					
						
							|  |  |  |     // lets set the router options
 | 
					
						
							|  |  |  |     this.options = { | 
					
						
							|  |  |  |       ...this.options, | 
					
						
							| 
									
										
										
										
											2020-07-15 18:51:17 +00:00
										 |  |  |       ...optionsArg, | 
					
						
							| 
									
										
										
										
											2020-06-01 20:51:36 +00:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // lets subscribe to route changes
 | 
					
						
							| 
									
										
										
										
											2020-07-15 18:51:17 +00:00
										 |  |  |     window.addEventListener('popstate', (popStateEventArg) => { | 
					
						
							| 
									
										
										
										
											2020-06-01 20:51:36 +00:00
										 |  |  |       popStateEventArg.preventDefault(); | 
					
						
							|  |  |  |       this._handleRouteState(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     window.addEventListener('DOMContentLoaded', () => { | 
					
						
							|  |  |  |       this._handleRouteState(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Push route state to history stack | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   public async pushUrl(url: string = '/', state: any = {}) { | 
					
						
							|  |  |  |     if (url !== window.location.pathname) { | 
					
						
							|  |  |  |       window.history.pushState(state, window.document.title, url); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       window.history.replaceState(state, window.document.title, url); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     await this._handleRouteState(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Attach route with handler | 
					
						
							|  |  |  |    * @param {string|RegExp} routeArg | 
					
						
							|  |  |  |    * @param {function} handlerArg | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2020-07-15 18:51:17 +00:00
										 |  |  |   public on(routeArg: string, handlerArg: THandlerFunction) { | 
					
						
							| 
									
										
										
										
											2020-06-01 20:51:36 +00:00
										 |  |  |     this.routes.push({ | 
					
						
							|  |  |  |       matchFunction: plugins.pathToRegExp.match(routeArg), | 
					
						
							| 
									
										
										
										
											2020-07-15 18:51:17 +00:00
										 |  |  |       handler: handlerArg, | 
					
						
							| 
									
										
										
										
											2020-06-01 20:51:36 +00:00
										 |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Apply routes handler to current route | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   async _handleRouteState() { | 
					
						
							|  |  |  |     const currentLocation = window.location.pathname; | 
					
						
							| 
									
										
										
										
											2021-09-08 21:46:21 +02:00
										 |  |  |     const urlSearchParams = new URLSearchParams(window.location.search); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // lets find all wanted routes.
 | 
					
						
							| 
									
										
										
										
											2020-11-30 01:38:21 +00:00
										 |  |  |     const wantedRoutes = this.routes.filter((routeArg) => { | 
					
						
							| 
									
										
										
										
											2020-06-01 20:51:36 +00:00
										 |  |  |       return !!routeArg.matchFunction(currentLocation); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 01:38:21 +00:00
										 |  |  |     for (const wantedRoute of wantedRoutes) { | 
					
						
							| 
									
										
										
										
											2020-06-01 20:51:36 +00:00
										 |  |  |       const routeResult = wantedRoute.matchFunction(currentLocation); | 
					
						
							| 
									
										
										
										
											2021-09-08 21:46:21 +02:00
										 |  |  |       wantedRoute.handler({ | 
					
						
							|  |  |  |         ...(routeResult.valueOf() as Object), | 
					
						
							|  |  |  |         queryParams: Object.fromEntries(urlSearchParams.entries()), | 
					
						
							|  |  |  |       } as IRouteInfo); // not waiting here
 | 
					
						
							| 
									
										
										
										
											2020-06-01 20:51:36 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |