ui5-lib-guard-router 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +382 -0
- package/dist/index.d.ts +27 -0
- package/dist/resources/ui5/guard/router/.library +17 -0
- package/dist/resources/ui5/guard/router/Router-dbg.js +431 -0
- package/dist/resources/ui5/guard/router/Router-dbg.js.map +1 -0
- package/dist/resources/ui5/guard/router/Router.d.ts +28 -0
- package/dist/resources/ui5/guard/router/Router.d.ts.map +1 -0
- package/dist/resources/ui5/guard/router/Router.js +2 -0
- package/dist/resources/ui5/guard/router/Router.js.map +1 -0
- package/dist/resources/ui5/guard/router/library-dbg.js +17 -0
- package/dist/resources/ui5/guard/router/library-dbg.js.map +1 -0
- package/dist/resources/ui5/guard/router/library-preload.js +10 -0
- package/dist/resources/ui5/guard/router/library-preload.js.map +1 -0
- package/dist/resources/ui5/guard/router/library.d.ts +7 -0
- package/dist/resources/ui5/guard/router/library.d.ts.map +1 -0
- package/dist/resources/ui5/guard/router/library.js +2 -0
- package/dist/resources/ui5/guard/router/library.js.map +1 -0
- package/dist/resources/ui5/guard/router/manifest.json +33 -0
- package/dist/resources/ui5/guard/router/types-dbg.js +2 -0
- package/dist/resources/ui5/guard/router/types-dbg.js.map +1 -0
- package/dist/resources/ui5/guard/router/types.d.ts +118 -0
- package/dist/resources/ui5/guard/router/types.d.ts.map +1 -0
- package/dist/resources/ui5/guard/router/types.js +2 -0
- package/dist/resources/ui5/guard/router/types.js.map +1 -0
- package/package.json +52 -0
- package/src/.library +17 -0
- package/src/Router.ts +540 -0
- package/src/library.ts +17 -0
- package/src/manifest.json +33 -0
- package/src/types.ts +136 -0
- package/tsconfig.json +13 -0
- package/ui5.yaml +24 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//@ui5-bundle ui5/guard/router/library-preload.js
|
|
2
|
+
sap.ui.predefine("ui5/guard/router/Router", ["sap/m/routing/Router","sap/base/Log","sap/ui/core/library"],function(t,e,r){"use strict";const n=r.routing.HistoryDirection;const s="ui5.guard.router.Router";function i(t){return typeof t==="object"&&t!==null}function a(t){return t instanceof Promise}function u(t){return typeof t==="object"}function o(t,e,r){let n=t.get(e);if(!n){n=[];t.set(e,n)}n.push(r)}function h(t,e,r){const n=t.get(e);if(!n)return;const s=n.indexOf(r);if(s!==-1)n.splice(s,1);if(n.length===0)t.delete(e)}const l=t.extend("ui5.guard.router.Router",{constructor:function(...e){t.prototype.constructor.apply(this,e);this._globalGuards=[];this._enterGuards=new Map;this._leaveGuards=new Map;this._currentRoute="";this._currentHash=null;this._pendingHash=null;this._redirecting=false;this._parseGeneration=0;this._suppressNextParse=false;this._abortController=null},addGuard(t){this._globalGuards.push(t);return this},removeGuard(t){const e=this._globalGuards.indexOf(t);if(e!==-1){this._globalGuards.splice(e,1)}return this},addRouteGuard(t,r){if(u(r)){if(!r.beforeEnter&&!r.beforeLeave){e.info("addRouteGuard called with config missing both beforeEnter and beforeLeave",t,s)}if(r.beforeEnter){this.addRouteGuard(t,r.beforeEnter)}if(r.beforeLeave){this.addLeaveGuard(t,r.beforeLeave)}return this}o(this._enterGuards,t,r);return this},removeRouteGuard(t,e){if(u(e)){if(e.beforeEnter){this.removeRouteGuard(t,e.beforeEnter)}if(e.beforeLeave){this.removeLeaveGuard(t,e.beforeLeave)}return this}h(this._enterGuards,t,e);return this},addLeaveGuard(t,e){o(this._leaveGuards,t,e);return this},removeLeaveGuard(t,e){h(this._leaveGuards,t,e);return this},parse(t){if(this._suppressNextParse){this._suppressNextParse=false;return}if(this._redirecting){this._commitNavigation(t);return}if(this._currentHash!==null&&t===this._currentHash){this._pendingHash=null;++this._parseGeneration;this._abortController?.abort();this._abortController=null;return}if(this._pendingHash!==null&&t===this._pendingHash){return}const r=this.getRouteInfoByHash(t);const n=r?.name??"";this._abortController?.abort();this._abortController=null;const i=++this._parseGeneration;this._pendingHash=t;const u=this._currentRoute!==""&&this._leaveGuards.has(this._currentRoute);const o=this._globalGuards.length>0||n!==""&&this._enterGuards.has(n);if(!u&&!o){this._commitNavigation(t,n);return}this._abortController=new AbortController;const h={toRoute:n,toHash:t,toArguments:r?.arguments??{},fromRoute:this._currentRoute,fromHash:this._currentHash??"",signal:this._abortController.signal};const l=()=>{const r=this._runEnterGuards(this._globalGuards,n,h);if(a(r)){r.then(r=>{if(i!==this._parseGeneration){e.debug("Async enter guard result discarded (superseded by newer navigation)",t,s);return}if(r===true){this._commitNavigation(t,n)}else if(r===false){this._blockNavigation()}else{this._redirect(r)}}).catch(t=>{if(i!==this._parseGeneration)return;e.error(`Async enter guard for route "${n}" failed, blocking navigation`,String(t),s);this._blockNavigation()});return}if(r===true){this._commitNavigation(t,n)}else if(r===false){this._blockNavigation()}else{this._redirect(r)}};if(u){const r=this._runLeaveGuards(h);if(a(r)){r.then(r=>{if(i!==this._parseGeneration){e.debug("Async leave guard result discarded (superseded by newer navigation)",t,s);return}if(r!==true){this._blockNavigation();return}l()}).catch(t=>{if(i!==this._parseGeneration)return;e.error(`Async leave guard on route "${this._currentRoute}" failed, blocking navigation`,String(t),s);this._blockNavigation()});return}if(r!==true){this._blockNavigation();return}}l()},_runLeaveGuards(t){const r=this._leaveGuards.get(this._currentRoute);if(!r||r.length===0)return true;const n=r.slice();for(let r=0;r<n.length;r++){try{const e=n[r](t);if(a(e)){return this._continueGuardsAsync(e,n,r,t,()=>false,"Leave guard",true)}if(e!==true)return false}catch(t){e.error(`Leave guard [${r}] on route "${this._currentRoute}" threw, blocking navigation`,String(t),s);return false}}return true},_commitNavigation(e,r){this._pendingHash=null;this._currentHash=e;this._currentRoute=r??this.getRouteInfoByHash(e)?.name??"";t.prototype.parse.call(this,e)},_runEnterGuards(t,e,r){const n=this._runGuards(t,r);if(a(n)){return n.then(t=>{if(t!==true)return t;if(r.signal.aborted)return false;return this._runRouteGuards(e,r)})}if(n!==true)return n;return this._runRouteGuards(e,r)},_runRouteGuards(t,e){if(!t||!this._enterGuards.has(t))return true;return this._runGuards(this._enterGuards.get(t),e)},_runGuards(t,r){t=t.slice();for(let n=0;n<t.length;n++){try{const e=t[n](r);if(a(e)){return this._continueGuardsAsync(e,t,n,r,t=>this._validateGuardResult(t),"Enter guard",false)}if(e!==true)return this._validateGuardResult(e)}catch(t){e.error(`Enter guard [${n}] for route "${r.toRoute}" threw, blocking navigation`,String(t),s);return false}}return true},async _continueGuardsAsync(t,r,n,i,a,u,o){let h=n;try{const e=await t;if(e!==true)return a(e);for(let t=n+1;t<r.length;t++){if(i.signal.aborted)return false;h=t;const e=await r[t](i);if(e!==true)return a(e)}return true}catch(t){if(!i.signal.aborted){const r=o?i.fromRoute:i.toRoute;e.error(`${u} [${h}] on route "${r}" threw, blocking navigation`,String(t),s)}return false}},_validateGuardResult(t){if(typeof t==="string"||typeof t==="boolean"||i(t)){return t}e.warning("Guard returned invalid value, treating as block",String(t),s);return false},_redirect(t){this._pendingHash=null;this._redirecting=true;try{if(typeof t==="string"){this.navTo(t,{},{},true)}else{this.navTo(t.route,t.parameters??{},t.componentTargetInfo,true)}}finally{this._redirecting=false}},_blockNavigation(){this._pendingHash=null;this._restoreHash()},_restoreHash(){const t=this.getHashChanger();if(t){this._suppressNextParse=true;t.replaceHash(this._currentHash??"",n.Unknown);if(this._suppressNextParse){this._suppressNextParse=false}}},destroy(){this._globalGuards=[];this._enterGuards.clear();this._leaveGuards.clear();++this._parseGeneration;this._pendingHash=null;this._abortController?.abort();this._abortController=null;return t.prototype.destroy.call(this)}});return l});
|
|
3
|
+
sap.ui.predefine("ui5/guard/router/library", ["sap/ui/core/Lib","sap/ui/core/library","sap/m/library"],function(e,r,i){"use strict";const s=e.init({apiVersion:2,name:"ui5.guard.router",version:"1.0.1",dependencies:["sap.ui.core","sap.m"],types:[],interfaces:[],controls:[],elements:[],noLibraryCSS:true});return s});
|
|
4
|
+
sap.ui.require.preload({
|
|
5
|
+
"ui5/guard/router/manifest.json":'{"_version":"2.0.0","sap.app":{"id":"ui5.guard.router","type":"library","applicationVersion":{"version":"1.0.1"},"title":"UI5 Router extension with async navigation guards","description":"Extends sap.m.routing.Router with async navigation guards, running before route matching begins."},"sap.ui":{"technology":"UI5","deviceTypes":{"desktop":true,"tablet":true,"phone":true}},"sap.ui5":{"contentDensities":{"compact":true,"cozy":true},"dependencies":{"minUI5Version":"1.144.0","libs":{"sap.ui.core":{},"sap.m":{}}}}}',
|
|
6
|
+
"ui5/guard/router/types.js":function(){
|
|
7
|
+
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
//# sourceMappingURL=library-preload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"library-preload.js","sections":[{"offset":{"line":1,"column":0},"map":{"version":3,"names":["HistoryDirection","coreLibrary","routing","LOG_COMPONENT","isGuardRedirect","value","isPromise","Promise","isRouteGuardConfig","guard","addToGuardMap","map","key","guards","get","set","push","removeFromGuardMap","index","indexOf","splice","length","delete","Router","MobileRouter","extend","constructor","args","prototype","apply","this","_globalGuards","_enterGuards","Map","_leaveGuards","_currentRoute","_currentHash","_pendingHash","_redirecting","_parseGeneration","_suppressNextParse","_abortController","addGuard","removeGuard","addRouteGuard","routeName","beforeEnter","beforeLeave","Log","info","addLeaveGuard","removeRouteGuard","removeLeaveGuard","parse","newHash","_commitNavigation","abort","routeInfo","getRouteInfoByHash","toRoute","name","generation","hasLeaveGuards","has","hasEnterGuards","AbortController","context","toHash","toArguments","arguments","fromRoute","fromHash","signal","runEnterGuards","enterResult","_runEnterGuards","then","guardResult","debug","_blockNavigation","_redirect","catch","error","String","leaveResult","_runLeaveGuards","allowed","registered","slice","i","result","_continueGuardsAsync","hash","route","call","globalGuards","globalResult","_runGuards","r","aborted","_runRouteGuards","_validateGuardResult","pendingResult","currentIndex","onBlock","label","isLeaveGuard","guardIndex","warning","target","navTo","parameters","componentTargetInfo","_restoreHash","hashChanger","getHashChanger","replaceHash","Unknown","destroy","clear"],"sources":["Router.ts"],"sourcesContent":["import MobileRouter from \"sap/m/routing/Router\";\nimport Log from \"sap/base/Log\";\nimport coreLibrary from \"sap/ui/core/library\";\nimport type {\n\tGuardFn,\n\tGuardContext,\n\tGuardResult,\n\tGuardRedirect,\n\tGuardRouter,\n\tLeaveGuardFn,\n\tRouteGuardConfig,\n\tRouterInternal,\n} from \"./types\";\n\nconst HistoryDirection = coreLibrary.routing.HistoryDirection;\n\nconst LOG_COMPONENT = \"ui5.guard.router.Router\";\n\nfunction isGuardRedirect(value: GuardResult): value is GuardRedirect {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isPromise<T>(value: T | Promise<T>): value is Promise<T> {\n\treturn value instanceof Promise;\n}\n\nfunction isRouteGuardConfig(guard: GuardFn | RouteGuardConfig): guard is RouteGuardConfig {\n\treturn typeof guard === \"object\";\n}\n\nfunction addToGuardMap<T>(map: Map<string, T[]>, key: string, guard: T): void {\n\tlet guards = map.get(key);\n\tif (!guards) {\n\t\tguards = [];\n\t\tmap.set(key, guards);\n\t}\n\tguards.push(guard);\n}\n\nfunction removeFromGuardMap<T>(map: Map<string, T[]>, key: string, guard: T): void {\n\tconst guards = map.get(key);\n\tif (!guards) return;\n\tconst index = guards.indexOf(guard);\n\tif (index !== -1) guards.splice(index, 1);\n\tif (guards.length === 0) map.delete(key);\n}\n\n/**\n * Router with navigation guard support.\n *\n * Extends `sap.m.routing.Router` by overriding `parse()` to run\n * registered guard functions before any route matching, target loading,\n * or event firing occurs.\n *\n * Key assumptions (see docs/architecture.md for full rationale):\n * - `parse()` is intentionally NOT async. Sync guards execute in the\n * same tick; async guards fall back to a deferred path.\n * - `replaceHash` fires `hashChanged` synchronously (validated by test).\n * - Redirect targets bypass guards to prevent infinite loops.\n *\n * @extends sap.m.routing.Router\n */\nconst Router = MobileRouter.extend(\"ui5.guard.router.Router\", {\n\tconstructor: function (this: RouterInternal, ...args: unknown[]) {\n\t\tMobileRouter.prototype.constructor.apply(this, args);\n\t\tthis._globalGuards = [];\n\t\tthis._enterGuards = new Map<string, GuardFn[]>();\n\t\tthis._leaveGuards = new Map<string, LeaveGuardFn[]>();\n\t\tthis._currentRoute = \"\";\n\t\tthis._currentHash = null; // null = no parse processed yet\n\t\tthis._pendingHash = null;\n\t\tthis._redirecting = false;\n\t\tthis._parseGeneration = 0;\n\t\tthis._suppressNextParse = false;\n\t\tthis._abortController = null;\n\t},\n\n\t/**\n\t * Register a global guard that runs for every navigation.\n\t */\n\taddGuard(this: RouterInternal, guard: GuardFn): GuardRouter {\n\t\tthis._globalGuards.push(guard);\n\t\treturn this;\n\t},\n\n\t/**\n\t * Remove a previously registered global guard.\n\t */\n\tremoveGuard(this: RouterInternal, guard: GuardFn): GuardRouter {\n\t\tconst index = this._globalGuards.indexOf(guard);\n\t\tif (index !== -1) {\n\t\t\tthis._globalGuards.splice(index, 1);\n\t\t}\n\t\treturn this;\n\t},\n\n\t/**\n\t * Register a guard for a specific route.\n\t *\n\t * Accepts either a guard function (registered as an enter guard) or a\n\t * configuration object with `beforeEnter` and/or `beforeLeave` guards.\n\t */\n\taddRouteGuard(this: RouterInternal, routeName: string, guard: GuardFn | RouteGuardConfig): GuardRouter {\n\t\tif (isRouteGuardConfig(guard)) {\n\t\t\tif (!guard.beforeEnter && !guard.beforeLeave) {\n\t\t\t\tLog.info(\n\t\t\t\t\t\"addRouteGuard called with config missing both beforeEnter and beforeLeave\",\n\t\t\t\t\trouteName,\n\t\t\t\t\tLOG_COMPONENT,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (guard.beforeEnter) {\n\t\t\t\tthis.addRouteGuard(routeName, guard.beforeEnter);\n\t\t\t}\n\t\t\tif (guard.beforeLeave) {\n\t\t\t\tthis.addLeaveGuard(routeName, guard.beforeLeave);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\taddToGuardMap(this._enterGuards, routeName, guard);\n\t\treturn this;\n\t},\n\n\t/**\n\t * Remove a guard from a specific route.\n\t *\n\t * Accepts the same forms as `addRouteGuard`: a guard function removes\n\t * an enter guard; a configuration object removes `beforeEnter` and/or\n\t * `beforeLeave` by reference.\n\t */\n\tremoveRouteGuard(this: RouterInternal, routeName: string, guard: GuardFn | RouteGuardConfig): GuardRouter {\n\t\tif (isRouteGuardConfig(guard)) {\n\t\t\tif (guard.beforeEnter) {\n\t\t\t\tthis.removeRouteGuard(routeName, guard.beforeEnter);\n\t\t\t}\n\t\t\tif (guard.beforeLeave) {\n\t\t\t\tthis.removeLeaveGuard(routeName, guard.beforeLeave);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tremoveFromGuardMap(this._enterGuards, routeName, guard);\n\t\treturn this;\n\t},\n\n\t/**\n\t * Register a leave guard for a specific route.\n\t *\n\t * Leave guards run when navigating **away from** the route, before any\n\t * enter guards for the target route. They answer the binary question\n\t * \"can I leave?\" and return only a boolean (no redirects).\n\t */\n\taddLeaveGuard(this: RouterInternal, routeName: string, guard: LeaveGuardFn): GuardRouter {\n\t\taddToGuardMap(this._leaveGuards, routeName, guard);\n\t\treturn this;\n\t},\n\n\t/**\n\t * Remove a leave guard from a specific route.\n\t */\n\tremoveLeaveGuard(this: RouterInternal, routeName: string, guard: LeaveGuardFn): GuardRouter {\n\t\tremoveFromGuardMap(this._leaveGuards, routeName, guard);\n\t\treturn this;\n\t},\n\n\t/**\n\t * Intercept hash changes and run the guard pipeline before route matching.\n\t *\n\t * Called by the HashChanger on every `hashChanged` event. Runs leave guards\n\t * (current route), then global + route-specific enter guards (target route).\n\t * Stays synchronous when all guards return plain values; falls back to async\n\t * when a guard returns a Promise. A generation counter discards stale results\n\t * when navigations overlap.\n\t *\n\t * @override sap.ui.core.routing.Router#parse\n\t */\n\tparse(this: RouterInternal, newHash: string): void {\n\t\tif (this._suppressNextParse) {\n\t\t\tthis._suppressNextParse = false;\n\t\t\treturn;\n\t\t}\n\n\t\tif (this._redirecting) {\n\t\t\tthis._commitNavigation(newHash);\n\t\t\treturn;\n\t\t}\n\n\t\t// Same-hash dedup: also invalidates any pending async guard\n\t\tif (this._currentHash !== null && newHash === this._currentHash) {\n\t\t\tthis._pendingHash = null;\n\t\t\t++this._parseGeneration;\n\t\t\tthis._abortController?.abort();\n\t\t\tthis._abortController = null;\n\t\t\treturn;\n\t\t}\n\n\t\t// Dedup against in-flight pending navigation\n\t\tif (this._pendingHash !== null && newHash === this._pendingHash) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst routeInfo = this.getRouteInfoByHash(newHash);\n\t\tconst toRoute = routeInfo?.name ?? \"\";\n\n\t\t// Invalidate any pending async guards from a previous navigation\n\t\tthis._abortController?.abort();\n\t\tthis._abortController = null;\n\t\tconst generation = ++this._parseGeneration;\n\n\t\tthis._pendingHash = newHash;\n\n\t\t// Check if any guards apply (leave OR enter)\n\t\tconst hasLeaveGuards = this._currentRoute !== \"\" && this._leaveGuards.has(this._currentRoute);\n\t\tconst hasEnterGuards = this._globalGuards.length > 0 || (toRoute !== \"\" && this._enterGuards.has(toRoute));\n\n\t\t// No guards → fast path\n\t\tif (!hasLeaveGuards && !hasEnterGuards) {\n\t\t\tthis._commitNavigation(newHash, toRoute);\n\t\t\treturn;\n\t\t}\n\n\t\t// Only create a controller when guards will actually run\n\t\tthis._abortController = new AbortController();\n\n\t\tconst context: GuardContext = {\n\t\t\ttoRoute,\n\t\t\ttoHash: newHash,\n\t\t\ttoArguments: routeInfo?.arguments ?? {},\n\t\t\tfromRoute: this._currentRoute,\n\t\t\tfromHash: this._currentHash ?? \"\",\n\t\t\tsignal: this._abortController.signal,\n\t\t};\n\n\t\t// Run enter guards and apply result (reused after leave guards pass)\n\t\tconst runEnterGuards = (): void => {\n\t\t\tconst enterResult = this._runEnterGuards(this._globalGuards, toRoute, context);\n\n\t\t\tif (isPromise(enterResult)) {\n\t\t\t\tenterResult\n\t\t\t\t\t.then((guardResult: GuardResult) => {\n\t\t\t\t\t\tif (generation !== this._parseGeneration) {\n\t\t\t\t\t\t\tLog.debug(\n\t\t\t\t\t\t\t\t\"Async enter guard result discarded (superseded by newer navigation)\",\n\t\t\t\t\t\t\t\tnewHash,\n\t\t\t\t\t\t\t\tLOG_COMPONENT,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Apply result: true=commit, false=block, other=redirect\n\t\t\t\t\t\tif (guardResult === true) {\n\t\t\t\t\t\t\tthis._commitNavigation(newHash, toRoute);\n\t\t\t\t\t\t} else if (guardResult === false) {\n\t\t\t\t\t\t\tthis._blockNavigation();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis._redirect(guardResult);\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\t\tif (generation !== this._parseGeneration) return;\n\t\t\t\t\t\tLog.error(\n\t\t\t\t\t\t\t`Async enter guard for route \"${toRoute}\" failed, blocking navigation`,\n\t\t\t\t\t\t\tString(error),\n\t\t\t\t\t\t\tLOG_COMPONENT,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis._blockNavigation();\n\t\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Apply result: true=commit, false=block, other=redirect\n\t\t\tif (enterResult === true) {\n\t\t\t\tthis._commitNavigation(newHash, toRoute);\n\t\t\t} else if (enterResult === false) {\n\t\t\t\tthis._blockNavigation();\n\t\t\t} else {\n\t\t\t\tthis._redirect(enterResult);\n\t\t\t}\n\t\t};\n\n\t\t// Run leave guards first, then enter guards\n\t\tif (hasLeaveGuards) {\n\t\t\tconst leaveResult = this._runLeaveGuards(context);\n\n\t\t\tif (isPromise(leaveResult)) {\n\t\t\t\tleaveResult\n\t\t\t\t\t.then((allowed: boolean) => {\n\t\t\t\t\t\tif (generation !== this._parseGeneration) {\n\t\t\t\t\t\t\tLog.debug(\n\t\t\t\t\t\t\t\t\"Async leave guard result discarded (superseded by newer navigation)\",\n\t\t\t\t\t\t\t\tnewHash,\n\t\t\t\t\t\t\t\tLOG_COMPONENT,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (allowed !== true) {\n\t\t\t\t\t\t\tthis._blockNavigation();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trunEnterGuards();\n\t\t\t\t\t})\n\t\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\t\tif (generation !== this._parseGeneration) return;\n\t\t\t\t\t\tLog.error(\n\t\t\t\t\t\t\t`Async leave guard on route \"${this._currentRoute}\" failed, blocking navigation`,\n\t\t\t\t\t\t\tString(error),\n\t\t\t\t\t\t\tLOG_COMPONENT,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis._blockNavigation();\n\t\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (leaveResult !== true) {\n\t\t\t\tthis._blockNavigation();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Enter guards (leave guards passed or were absent)\n\t\trunEnterGuards();\n\t},\n\n\t/**\n\t * Run leave guards for the current route. Returns boolean (no redirects).\n\t *\n\t * The guard array is snapshot-copied before iteration so that guards\n\t * may safely add/remove themselves (e.g. one-shot guards) without\n\t * affecting the current pipeline run.\n\t */\n\t_runLeaveGuards(this: RouterInternal, context: GuardContext): boolean | Promise<boolean> {\n\t\tconst registered = this._leaveGuards.get(this._currentRoute);\n\t\tif (!registered || registered.length === 0) return true;\n\n\t\tconst guards = registered.slice();\n\t\tfor (let i = 0; i < guards.length; i++) {\n\t\t\ttry {\n\t\t\t\tconst result = guards[i](context);\n\t\t\t\tif (isPromise(result)) {\n\t\t\t\t\treturn this._continueGuardsAsync(\n\t\t\t\t\t\tresult,\n\t\t\t\t\t\tguards,\n\t\t\t\t\t\ti,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t() => false,\n\t\t\t\t\t\t\"Leave guard\",\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t) as Promise<boolean>;\n\t\t\t\t}\n\t\t\t\tif (result !== true) return false;\n\t\t\t} catch (error) {\n\t\t\t\tLog.error(\n\t\t\t\t\t`Leave guard [${i}] on route \"${this._currentRoute}\" threw, blocking navigation`,\n\t\t\t\t\tString(error),\n\t\t\t\t\tLOG_COMPONENT,\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t},\n\n\t/**\n\t * Delegate to the parent router and update internal state.\n\t *\n\t * State is updated BEFORE calling parse to ensure that if event handlers\n\t * (e.g., routeMatched) trigger nested navigation, the leave guards will\n\t * run for the correct (new) route rather than the old one.\n\t */\n\t_commitNavigation(this: RouterInternal, hash: string, route?: string): void {\n\t\tthis._pendingHash = null;\n\t\tthis._currentHash = hash;\n\t\tthis._currentRoute = route ?? this.getRouteInfoByHash(hash)?.name ?? \"\";\n\t\tMobileRouter.prototype.parse.call(this, hash);\n\t},\n\n\t/** Run global guards, then route-specific guards. Stays sync when possible. */\n\t_runEnterGuards(\n\t\tthis: RouterInternal,\n\t\tglobalGuards: GuardFn[],\n\t\ttoRoute: string,\n\t\tcontext: GuardContext,\n\t): GuardResult | Promise<GuardResult> {\n\t\tconst globalResult = this._runGuards(globalGuards, context);\n\n\t\tif (isPromise(globalResult)) {\n\t\t\treturn globalResult.then((r: GuardResult) => {\n\t\t\t\tif (r !== true) return r;\n\t\t\t\tif (context.signal.aborted) return false;\n\t\t\t\treturn this._runRouteGuards(toRoute, context);\n\t\t\t});\n\t\t}\n\t\tif (globalResult !== true) return globalResult;\n\t\treturn this._runRouteGuards(toRoute, context);\n\t},\n\n\t/** Run route-specific guards if any are registered. */\n\t_runRouteGuards(this: RouterInternal, toRoute: string, context: GuardContext): GuardResult | Promise<GuardResult> {\n\t\tif (!toRoute || !this._enterGuards.has(toRoute)) return true;\n\t\treturn this._runGuards(this._enterGuards.get(toRoute)!, context);\n\t},\n\n\t/**\n\t * Run guards sync; switch to async path if a Promise is returned.\n\t *\n\t * The guard array is snapshot-copied before iteration so that guards\n\t * may safely add/remove themselves (e.g. one-shot guards) without\n\t * affecting the current pipeline run.\n\t */\n\t_runGuards(this: RouterInternal, guards: GuardFn[], context: GuardContext): GuardResult | Promise<GuardResult> {\n\t\tguards = guards.slice();\n\t\tfor (let i = 0; i < guards.length; i++) {\n\t\t\ttry {\n\t\t\t\tconst result = guards[i](context);\n\t\t\t\tif (isPromise(result)) {\n\t\t\t\t\treturn this._continueGuardsAsync(\n\t\t\t\t\t\tresult,\n\t\t\t\t\t\tguards,\n\t\t\t\t\t\ti,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t(r) => this._validateGuardResult(r),\n\t\t\t\t\t\t\"Enter guard\",\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (result !== true) return this._validateGuardResult(result);\n\t\t\t} catch (error) {\n\t\t\t\tLog.error(\n\t\t\t\t\t`Enter guard [${i}] for route \"${context.toRoute}\" threw, blocking navigation`,\n\t\t\t\t\tString(error),\n\t\t\t\t\tLOG_COMPONENT,\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t},\n\n\t/**\n\t * Continue guard array async from the first Promise onward.\n\t *\n\t * Shared by both enter and leave guard pipelines. The `onBlock` callback\n\t * determines what to return for non-true results: leave guards always\n\t * return `false`, enter guards validate and may return redirects.\n\t *\n\t * @param isLeaveGuard - When true, error logs reference `fromRoute`; otherwise `toRoute`.\n\t */\n\tasync _continueGuardsAsync(\n\t\tthis: RouterInternal,\n\t\tpendingResult: Promise<GuardResult>,\n\t\tguards: Array<(context: GuardContext) => GuardResult | Promise<GuardResult>>,\n\t\tcurrentIndex: number,\n\t\tcontext: GuardContext,\n\t\tonBlock: (result: GuardResult) => GuardResult,\n\t\tlabel: string,\n\t\tisLeaveGuard: boolean,\n\t): Promise<GuardResult> {\n\t\tlet guardIndex = currentIndex;\n\t\ttry {\n\t\t\tconst result = await pendingResult;\n\t\t\tif (result !== true) return onBlock(result);\n\n\t\t\tfor (let i = currentIndex + 1; i < guards.length; i++) {\n\t\t\t\tif (context.signal.aborted) return false;\n\t\t\t\tguardIndex = i;\n\t\t\t\tconst r = await guards[i](context);\n\t\t\t\tif (r !== true) return onBlock(r);\n\t\t\t}\n\t\t\treturn true;\n\t\t} catch (error) {\n\t\t\tif (!context.signal.aborted) {\n\t\t\t\tconst route = isLeaveGuard ? context.fromRoute : context.toRoute;\n\t\t\t\tLog.error(\n\t\t\t\t\t`${label} [${guardIndex}] on route \"${route}\" threw, blocking navigation`,\n\t\t\t\t\tString(error),\n\t\t\t\t\tLOG_COMPONENT,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t},\n\n\t/** Validate a non-true guard result; invalid values become false. */\n\t_validateGuardResult(this: RouterInternal, result: GuardResult): GuardResult {\n\t\tif (typeof result === \"string\" || typeof result === \"boolean\" || isGuardRedirect(result)) {\n\t\t\treturn result;\n\t\t}\n\t\tLog.warning(\"Guard returned invalid value, treating as block\", String(result), LOG_COMPONENT);\n\t\treturn false;\n\t},\n\n\t/** Perform a guard redirect (string route name or GuardRedirect object). */\n\t_redirect(this: RouterInternal, target: string | GuardRedirect): void {\n\t\tthis._pendingHash = null;\n\t\tthis._redirecting = true;\n\t\ttry {\n\t\t\tif (typeof target === \"string\") {\n\t\t\t\tthis.navTo(target, {}, {}, true);\n\t\t\t} else {\n\t\t\t\tthis.navTo(target.route, target.parameters ?? {}, target.componentTargetInfo, true);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis._redirecting = false;\n\t\t}\n\t},\n\n\t/** Clear pending state and restore the previous hash. */\n\t_blockNavigation(this: RouterInternal): void {\n\t\tthis._pendingHash = null;\n\t\tthis._restoreHash();\n\t},\n\n\t/**\n\t * Restore the previous hash without creating a history entry.\n\t * Assumes replaceHash fires hashChanged synchronously (validated by test).\n\t * Note: _currentRoute intentionally stays unchanged — the blocked navigation\n\t * never committed, so the user remains on the same logical route.\n\t */\n\t_restoreHash(this: RouterInternal): void {\n\t\tconst hashChanger = this.getHashChanger();\n\t\tif (hashChanger) {\n\t\t\tthis._suppressNextParse = true;\n\t\t\thashChanger.replaceHash(this._currentHash ?? \"\", HistoryDirection.Unknown);\n\t\t\tif (this._suppressNextParse) {\n\t\t\t\t// replaceHash was a no-op (same hash) - reset to prevent leak\n\t\t\t\tthis._suppressNextParse = false;\n\t\t\t}\n\t\t}\n\t},\n\n\t/** Clean up guards on destroy. Bumps generation to discard pending async results. */\n\tdestroy(this: RouterInternal) {\n\t\tthis._globalGuards = [];\n\t\tthis._enterGuards.clear();\n\t\tthis._leaveGuards.clear();\n\t\t++this._parseGeneration;\n\t\tthis._pendingHash = null;\n\t\tthis._abortController?.abort();\n\t\tthis._abortController = null;\n\t\treturn MobileRouter.prototype.destroy.call(this);\n\t},\n});\n\nexport default Router;\n"],"mappings":"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","ignoreList":[],"sourceRoot":""}},{"offset":{"line":2,"column":0},"map":{"version":3,"names":["library","Lib","init","apiVersion","name","version","dependencies","types","interfaces","controls","elements","noLibraryCSS"],"sources":["library.ts"],"sourcesContent":["import Lib from \"sap/ui/core/Lib\";\nimport \"sap/ui/core/library\";\nimport \"sap/m/library\";\n\nconst library = Lib.init({\n\tapiVersion: 2,\n\tname: \"ui5.guard.router\",\n\tversion: \"1.0.1\",\n\tdependencies: [\"sap.ui.core\", \"sap.m\"],\n\ttypes: [],\n\tinterfaces: [],\n\tcontrols: [],\n\telements: [],\n\tnoLibraryCSS: true,\n});\n\nexport default library;\n"],"mappings":"AAAA,oIAIA,MAAMA,EAAUC,EAAIC,KAAK,CACxBC,WAAY,EACZC,KAAM,mBACNC,QAAS,QACTC,aAAc,CAAC,cAAe,SAC9BC,MAAO,GACPC,WAAY,GACZC,SAAU,GACVC,SAAU,GACVC,aAAc,OACZ,OAEYX,CAAO","ignoreList":[],"sourceRoot":""}},{"offset":{"line":3,"column":0},"map":{"version":3,"names":[],"sources":["library-preload.js?bundle-code-0"],"mappings":"AAAA;AACA","sourcesContent":["sap.ui.require.preload({\n"],"sourceRoot":""}},{"offset":{"line":6,"column":0},"map":{"version":3,"file":"types.js","names":[],"sources":[],"mappings":"","ignoreList":[],"sourceRoot":""}}]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"library.d.ts","sourceRoot":"..\\..\\..\\..\\..","sources":["src\\library.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,0BAA0B,CAAC;IAE1C,OAAO,qBAAqB,CAAC;IAC7B,OAAO,eAAe,CAAC;IAEvB,MAAM,OAAO,KAUX,CAAC;IAEH,eAAe,OAAO,CAAC;CAEtB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
sap.ui.define(["sap/ui/core/Lib","sap/ui/core/library","sap/m/library"],function(e,r,i){"use strict";const s=e.init({apiVersion:2,name:"ui5.guard.router",version:"1.0.1",dependencies:["sap.ui.core","sap.m"],types:[],interfaces:[],controls:[],elements:[],noLibraryCSS:true});return s});
|
|
2
|
+
//# sourceMappingURL=library.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"library.js","names":["library","Lib","init","apiVersion","name","version","dependencies","types","interfaces","controls","elements","noLibraryCSS"],"sources":["library.ts"],"sourcesContent":["import Lib from \"sap/ui/core/Lib\";\nimport \"sap/ui/core/library\";\nimport \"sap/m/library\";\n\nconst library = Lib.init({\n\tapiVersion: 2,\n\tname: \"ui5.guard.router\",\n\tversion: \"1.0.1\",\n\tdependencies: [\"sap.ui.core\", \"sap.m\"],\n\ttypes: [],\n\tinterfaces: [],\n\tcontrols: [],\n\telements: [],\n\tnoLibraryCSS: true,\n});\n\nexport default library;\n"],"mappings":"qGAIA,MAAMA,EAAUC,EAAIC,KAAK,CACxBC,WAAY,EACZC,KAAM,mBACNC,QAAS,QACTC,aAAc,CAAC,cAAe,SAC9BC,MAAO,GACPC,WAAY,GACZC,SAAU,GACVC,SAAU,GACVC,aAAc,OACZ,OAEYX,CAAO","ignoreList":[]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_version": "2.0.0",
|
|
3
|
+
"sap.app": {
|
|
4
|
+
"id": "ui5.guard.router",
|
|
5
|
+
"type": "library",
|
|
6
|
+
"applicationVersion": {
|
|
7
|
+
"version": "1.0.1"
|
|
8
|
+
},
|
|
9
|
+
"title": "UI5 Router extension with async navigation guards",
|
|
10
|
+
"description": "Extends sap.m.routing.Router with async navigation guards, running before route matching begins."
|
|
11
|
+
},
|
|
12
|
+
"sap.ui": {
|
|
13
|
+
"technology": "UI5",
|
|
14
|
+
"deviceTypes": {
|
|
15
|
+
"desktop": true,
|
|
16
|
+
"tablet": true,
|
|
17
|
+
"phone": true
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"sap.ui5": {
|
|
21
|
+
"contentDensities": {
|
|
22
|
+
"compact": true,
|
|
23
|
+
"cozy": true
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"minUI5Version": "1.144.0",
|
|
27
|
+
"libs": {
|
|
28
|
+
"sap.ui.core": {},
|
|
29
|
+
"sap.m": {}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-dbg.js","names":[],"sources":["types.ts"],"sourcesContent":["import type MobileRouter from \"sap/m/routing/Router\";\nimport type { ComponentTargetParameters, RouteInfo } from \"sap/ui/core/routing/Router\";\n\n/**\n * Redirect target with route name and optional parameters.\n */\nexport interface GuardRedirect {\n\t/** Route name to redirect to */\n\troute: string;\n\t/** Optional route parameters */\n\tparameters?: ComponentTargetParameters[\"parameters\"];\n\t/** Optional component target info for nested component routing */\n\tcomponentTargetInfo?: Record<string, ComponentTargetParameters>;\n}\n\n/**\n * Result of a guard check.\n *\n * Only strict `true` allows navigation. All other values (including truthy\n * non-boolean values) block or redirect. This avoids accidental allow from\n * falsy/truthy coercion.\n *\n * - `true` → allow navigation to proceed\n * - `false` → block navigation (stay on current route, no history entry)\n * - `string` → redirect to this route name (replaceHash, no history entry)\n * - `GuardRedirect` → redirect with route name, parameters, and optional component target info\n */\nexport type GuardResult = boolean | string | GuardRedirect;\n\n/**\n * Context passed to guard functions.\n */\nexport interface GuardContext {\n\t/** Target route name (empty string if no route matched) */\n\ttoRoute: string;\n\t/** Raw hash being navigated to */\n\ttoHash: string;\n\t/** Parsed route parameters */\n\ttoArguments: RouteInfo[\"arguments\"];\n\t/** Current route name (empty string on initial navigation) */\n\tfromRoute: string;\n\t/** Current hash */\n\tfromHash: string;\n\t/**\n\t * Abort signal for this navigation. Aborted when a newer navigation\n\t * supersedes this one or when the router is destroyed.\n\t * Pass to `fetch()` or other cancellable APIs to avoid wasted work.\n\t */\n\tsignal: AbortSignal;\n}\n\n/**\n * A guard function - can be synchronous or asynchronous.\n */\nexport type GuardFn = (context: GuardContext) => GuardResult | Promise<GuardResult>;\n\n/**\n * A leave guard function - can be synchronous or asynchronous.\n *\n * Leave guards answer the question \"can I leave this route?\" and return\n * only a boolean. They cannot redirect — use enter guards for that.\n */\nexport type LeaveGuardFn = (context: GuardContext) => boolean | Promise<boolean>;\n\n/**\n * Configuration object for registering enter and/or leave guards on a route.\n *\n * When passed to `addRouteGuard`, the object form allows registering both\n * guard types in a single call. If neither `beforeEnter` nor `beforeLeave`\n * is provided, an info message is logged and no guards are registered.\n */\nexport interface RouteGuardConfig {\n\t/** Guard that runs before entering this route */\n\tbeforeEnter?: GuardFn;\n\t/** Guard that runs before leaving this route */\n\tbeforeLeave?: LeaveGuardFn;\n}\n\n/**\n * Public instance shape of the extended Router.\n *\n * Extends `sap.m.routing.Router` with guard management methods.\n * Use this type when casting `getRouter()` in application code.\n */\nexport interface GuardRouter extends MobileRouter {\n\taddGuard(guard: GuardFn): GuardRouter;\n\tremoveGuard(guard: GuardFn): GuardRouter;\n\taddRouteGuard(routeName: string, guard: GuardFn | RouteGuardConfig): GuardRouter;\n\tremoveRouteGuard(routeName: string, guard: GuardFn | RouteGuardConfig): GuardRouter;\n\taddLeaveGuard(routeName: string, guard: LeaveGuardFn): GuardRouter;\n\tremoveLeaveGuard(routeName: string, guard: LeaveGuardFn): GuardRouter;\n}\n\n/**\n * Full internal instance shape including private state and methods.\n *\n * Used as the `this` type in Router method bodies to provide autocomplete\n * and catch property-name typos. Not intended for external consumption.\n *\n * @internal\n */\nexport interface RouterInternal extends GuardRouter {\n\t_globalGuards: GuardFn[];\n\t_enterGuards: Map<string, GuardFn[]>;\n\t_leaveGuards: Map<string, LeaveGuardFn[]>;\n\t_currentRoute: string;\n\t_currentHash: string | null;\n\t_pendingHash: string | null;\n\t_redirecting: boolean;\n\t_parseGeneration: number;\n\t_suppressNextParse: boolean;\n\t_abortController: AbortController | null;\n\n\t_commitNavigation(hash: string, route?: string): void;\n\t_runLeaveGuards(context: GuardContext): boolean | Promise<boolean>;\n\t_runEnterGuards(\n\t\tglobalGuards: GuardFn[],\n\t\ttoRoute: string,\n\t\tcontext: GuardContext,\n\t): GuardResult | Promise<GuardResult>;\n\t_runRouteGuards(toRoute: string, context: GuardContext): GuardResult | Promise<GuardResult>;\n\t_runGuards(guards: GuardFn[], context: GuardContext): GuardResult | Promise<GuardResult>;\n\t_continueGuardsAsync(\n\t\tpendingResult: Promise<GuardResult>,\n\t\tguards: Array<(context: GuardContext) => GuardResult | Promise<GuardResult>>,\n\t\tcurrentIndex: number,\n\t\tcontext: GuardContext,\n\t\tonBlock: (result: GuardResult) => GuardResult,\n\t\tlabel: string,\n\t\tisLeaveGuard: boolean,\n\t): Promise<GuardResult>;\n\t_validateGuardResult(result: GuardResult): GuardResult;\n\t_redirect(target: string | GuardRedirect): void;\n\t_blockNavigation(): void;\n\t_restoreHash(): void;\n}\n"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
declare module "ui5/guard/router/types" {
|
|
2
|
+
import type MobileRouter from "sap/m/routing/Router";
|
|
3
|
+
import type { ComponentTargetParameters, RouteInfo } from "sap/ui/core/routing/Router";
|
|
4
|
+
/**
|
|
5
|
+
* Redirect target with route name and optional parameters.
|
|
6
|
+
*/
|
|
7
|
+
interface GuardRedirect {
|
|
8
|
+
/** Route name to redirect to */
|
|
9
|
+
route: string;
|
|
10
|
+
/** Optional route parameters */
|
|
11
|
+
parameters?: ComponentTargetParameters["parameters"];
|
|
12
|
+
/** Optional component target info for nested component routing */
|
|
13
|
+
componentTargetInfo?: Record<string, ComponentTargetParameters>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Result of a guard check.
|
|
17
|
+
*
|
|
18
|
+
* Only strict `true` allows navigation. All other values (including truthy
|
|
19
|
+
* non-boolean values) block or redirect. This avoids accidental allow from
|
|
20
|
+
* falsy/truthy coercion.
|
|
21
|
+
*
|
|
22
|
+
* - `true` → allow navigation to proceed
|
|
23
|
+
* - `false` → block navigation (stay on current route, no history entry)
|
|
24
|
+
* - `string` → redirect to this route name (replaceHash, no history entry)
|
|
25
|
+
* - `GuardRedirect` → redirect with route name, parameters, and optional component target info
|
|
26
|
+
*/
|
|
27
|
+
type GuardResult = boolean | string | GuardRedirect;
|
|
28
|
+
/**
|
|
29
|
+
* Context passed to guard functions.
|
|
30
|
+
*/
|
|
31
|
+
interface GuardContext {
|
|
32
|
+
/** Target route name (empty string if no route matched) */
|
|
33
|
+
toRoute: string;
|
|
34
|
+
/** Raw hash being navigated to */
|
|
35
|
+
toHash: string;
|
|
36
|
+
/** Parsed route parameters */
|
|
37
|
+
toArguments: RouteInfo["arguments"];
|
|
38
|
+
/** Current route name (empty string on initial navigation) */
|
|
39
|
+
fromRoute: string;
|
|
40
|
+
/** Current hash */
|
|
41
|
+
fromHash: string;
|
|
42
|
+
/**
|
|
43
|
+
* Abort signal for this navigation. Aborted when a newer navigation
|
|
44
|
+
* supersedes this one or when the router is destroyed.
|
|
45
|
+
* Pass to `fetch()` or other cancellable APIs to avoid wasted work.
|
|
46
|
+
*/
|
|
47
|
+
signal: AbortSignal;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A guard function - can be synchronous or asynchronous.
|
|
51
|
+
*/
|
|
52
|
+
type GuardFn = (context: GuardContext) => GuardResult | Promise<GuardResult>;
|
|
53
|
+
/**
|
|
54
|
+
* A leave guard function - can be synchronous or asynchronous.
|
|
55
|
+
*
|
|
56
|
+
* Leave guards answer the question "can I leave this route?" and return
|
|
57
|
+
* only a boolean. They cannot redirect — use enter guards for that.
|
|
58
|
+
*/
|
|
59
|
+
type LeaveGuardFn = (context: GuardContext) => boolean | Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* Configuration object for registering enter and/or leave guards on a route.
|
|
62
|
+
*
|
|
63
|
+
* When passed to `addRouteGuard`, the object form allows registering both
|
|
64
|
+
* guard types in a single call. If neither `beforeEnter` nor `beforeLeave`
|
|
65
|
+
* is provided, an info message is logged and no guards are registered.
|
|
66
|
+
*/
|
|
67
|
+
interface RouteGuardConfig {
|
|
68
|
+
/** Guard that runs before entering this route */
|
|
69
|
+
beforeEnter?: GuardFn;
|
|
70
|
+
/** Guard that runs before leaving this route */
|
|
71
|
+
beforeLeave?: LeaveGuardFn;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Public instance shape of the extended Router.
|
|
75
|
+
*
|
|
76
|
+
* Extends `sap.m.routing.Router` with guard management methods.
|
|
77
|
+
* Use this type when casting `getRouter()` in application code.
|
|
78
|
+
*/
|
|
79
|
+
interface GuardRouter extends MobileRouter {
|
|
80
|
+
addGuard(guard: GuardFn): GuardRouter;
|
|
81
|
+
removeGuard(guard: GuardFn): GuardRouter;
|
|
82
|
+
addRouteGuard(routeName: string, guard: GuardFn | RouteGuardConfig): GuardRouter;
|
|
83
|
+
removeRouteGuard(routeName: string, guard: GuardFn | RouteGuardConfig): GuardRouter;
|
|
84
|
+
addLeaveGuard(routeName: string, guard: LeaveGuardFn): GuardRouter;
|
|
85
|
+
removeLeaveGuard(routeName: string, guard: LeaveGuardFn): GuardRouter;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Full internal instance shape including private state and methods.
|
|
89
|
+
*
|
|
90
|
+
* Used as the `this` type in Router method bodies to provide autocomplete
|
|
91
|
+
* and catch property-name typos. Not intended for external consumption.
|
|
92
|
+
*
|
|
93
|
+
* @internal
|
|
94
|
+
*/
|
|
95
|
+
interface RouterInternal extends GuardRouter {
|
|
96
|
+
_globalGuards: GuardFn[];
|
|
97
|
+
_enterGuards: Map<string, GuardFn[]>;
|
|
98
|
+
_leaveGuards: Map<string, LeaveGuardFn[]>;
|
|
99
|
+
_currentRoute: string;
|
|
100
|
+
_currentHash: string | null;
|
|
101
|
+
_pendingHash: string | null;
|
|
102
|
+
_redirecting: boolean;
|
|
103
|
+
_parseGeneration: number;
|
|
104
|
+
_suppressNextParse: boolean;
|
|
105
|
+
_abortController: AbortController | null;
|
|
106
|
+
_commitNavigation(hash: string, route?: string): void;
|
|
107
|
+
_runLeaveGuards(context: GuardContext): boolean | Promise<boolean>;
|
|
108
|
+
_runEnterGuards(globalGuards: GuardFn[], toRoute: string, context: GuardContext): GuardResult | Promise<GuardResult>;
|
|
109
|
+
_runRouteGuards(toRoute: string, context: GuardContext): GuardResult | Promise<GuardResult>;
|
|
110
|
+
_runGuards(guards: GuardFn[], context: GuardContext): GuardResult | Promise<GuardResult>;
|
|
111
|
+
_continueGuardsAsync(pendingResult: Promise<GuardResult>, guards: Array<(context: GuardContext) => GuardResult | Promise<GuardResult>>, currentIndex: number, context: GuardContext, onBlock: (result: GuardResult) => GuardResult, label: string, isLeaveGuard: boolean): Promise<GuardResult>;
|
|
112
|
+
_validateGuardResult(result: GuardResult): GuardResult;
|
|
113
|
+
_redirect(target: string | GuardRedirect): void;
|
|
114
|
+
_blockNavigation(): void;
|
|
115
|
+
_restoreHash(): void;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"..\\..\\..\\..\\..","sources":["src\\types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":[],"mappings":"","ignoreList":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ui5-lib-guard-router",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"main": "dist/resources/ui5/guard/router/library.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"author": "Marco Beier",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/wridgeu/ui5-lib-guard-router.git",
|
|
11
|
+
"directory": "packages/lib"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/wridgeu/ui5-lib-guard-router/issues"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/wridgeu/ui5-lib-guard-router#readme",
|
|
17
|
+
"description": "UI5 Router extension with async navigation guards",
|
|
18
|
+
"keywords": [
|
|
19
|
+
"ui5",
|
|
20
|
+
"openui5",
|
|
21
|
+
"sapui5",
|
|
22
|
+
"router",
|
|
23
|
+
"navigation",
|
|
24
|
+
"guards"
|
|
25
|
+
],
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"type": "module",
|
|
30
|
+
"files": [
|
|
31
|
+
"dist/**/*",
|
|
32
|
+
"src/**/*",
|
|
33
|
+
"ui5.yaml",
|
|
34
|
+
"tsconfig.json",
|
|
35
|
+
"README.md",
|
|
36
|
+
"LICENSE"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"clean": "rimraf dist .ui5",
|
|
40
|
+
"build": "ui5 build",
|
|
41
|
+
"prepublishOnly": "node -e \"import('node:fs').then(f=>f.copyFileSync('../../LICENSE','./LICENSE'))\" && npm run build",
|
|
42
|
+
"start": "ui5 serve",
|
|
43
|
+
"test": "echo \"Run tests from monorepo root: npm run test:qunit\" && exit 1",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"pack:check": "npm pack --dry-run"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/qunit": "^2.19.13",
|
|
49
|
+
"@ui5/cli": "^4.0.0",
|
|
50
|
+
"ui5-tooling-transpile": "^3.0.0"
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/.library
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
|
2
|
+
<library xmlns="http://www.sap.com/sap.ui.library.xsd">
|
|
3
|
+
<name>ui5.guard.router</name>
|
|
4
|
+
<vendor>Marco</vendor>
|
|
5
|
+
<version>${version}</version>
|
|
6
|
+
<copyright></copyright>
|
|
7
|
+
<title>UI5 Router extension with async navigation guards</title>
|
|
8
|
+
<documentation>Extends sap.m.routing.Router with async navigation guards, running before route matching begins.</documentation>
|
|
9
|
+
<dependencies>
|
|
10
|
+
<dependency>
|
|
11
|
+
<libraryName>sap.ui.core</libraryName>
|
|
12
|
+
</dependency>
|
|
13
|
+
<dependency>
|
|
14
|
+
<libraryName>sap.m</libraryName>
|
|
15
|
+
</dependency>
|
|
16
|
+
</dependencies>
|
|
17
|
+
</library>
|