(type: 'route' | 'conn', routeName: string, path: string, HandlerClass: any, ...permPrivChecker)
| 731 | } |
| 732 | |
| 733 | private register(type: 'route' | 'conn', routeName: string, path: string, HandlerClass: any, ...permPrivChecker) { |
| 734 | if (!HandlerClass?.[kHandler] || !isClass(HandlerClass)) throw new Error('Invalid registration.'); |
| 735 | const name = ((Object.hasOwn(HandlerClass, kHandler) && typeof HandlerClass[kHandler] === 'string') |
| 736 | ? HandlerClass[kHandler] : HandlerClass.name).replace(/Handler$/, ''); |
| 737 | if (this.registrationCount[name] && this.registry[name] !== HandlerClass) { |
| 738 | logger.warn('Route with name %s already exists.', name); |
| 739 | } |
| 740 | this.registry[name] = HandlerClass; |
| 741 | this.registrationCount[name]++; |
| 742 | |
| 743 | const Checker = (args) => { |
| 744 | let perm: bigint; |
| 745 | let priv: number; |
| 746 | let checker = () => { }; |
| 747 | for (const item of args) { |
| 748 | if (typeof item === 'object') { |
| 749 | if (typeof item.call !== 'undefined') { |
| 750 | checker = item; |
| 751 | } else if (typeof item[0] === 'number') { |
| 752 | priv = item; |
| 753 | } else if (typeof item[0] === 'bigint') { |
| 754 | perm = item; |
| 755 | } |
| 756 | } else if (typeof item === 'number') { |
| 757 | priv = item; |
| 758 | } else if (typeof item === 'bigint') { |
| 759 | perm = item; |
| 760 | } |
| 761 | } |
| 762 | return function check(this: Handler) { |
| 763 | checker(); |
| 764 | if (perm) this.checkPerm(perm); |
| 765 | if (priv) this.checkPriv(priv); |
| 766 | }; |
| 767 | }; |
| 768 | |
| 769 | // We hope to use parent context for handler (the context that calls register) |
| 770 | // So that handler can use services injected before calling register |
| 771 | const savedContext = Object.hasOwn(this.ctx, Symbol.for('cordis.shadow')) |
| 772 | ? Object.getPrototypeOf(this.ctx) |
| 773 | : this.ctx; |
| 774 | const checker = Checker(permPrivChecker); |
| 775 | if (type === 'route') { |
| 776 | router.all(routeName, path, (ctx) => this.handleHttp(ctx as any, HandlerClass, checker, savedContext)); |
| 777 | } else { |
| 778 | const layer = router.ws(path, async (conn, _req, ctx) => { |
| 779 | await this.handleWS(ctx as any, HandlerClass, checker, conn, layer, savedContext); |
| 780 | }); |
| 781 | if (this.config.enableSSE) { |
| 782 | router.get(routeName, path, async (ctx) => { |
| 783 | Object.assign(ctx.HydroContext.args, ctx.params); |
| 784 | await this.handleWS(ctx as any, HandlerClass, checker, null, null, savedContext); |
| 785 | }); |
| 786 | } |
| 787 | } |
| 788 | const dispose = router.disposeLastOp; |
| 789 | this.rebuildRouteMap(); |
| 790 | // @ts-ignore |
no test coverage detected