( target: T, validator: ServiceValidator )
| 674 | } |
| 675 | |
| 676 | export function wrapServerTarget<T extends object>( |
| 677 | target: T, |
| 678 | validator: ServiceValidator |
| 679 | ): T { |
| 680 | return new Proxy(target, { |
| 681 | get(t, prop) { |
| 682 | if (typeof prop !== "string") { |
| 683 | // Symbol-keyed members (Symbol.dispose etc.): forward bound to `t`. |
| 684 | let orig = Reflect.get(t, prop, t); |
| 685 | return typeof orig === "function" ? orig.bind(t) : orig; |
| 686 | } |
| 687 | let methodSpec = own(validator.methods, prop); |
| 688 | if (!methodSpec) { |
| 689 | // Infra / platform hook: forward the real member (read or bound). |
| 690 | if (canPassThrough(prop, validator, "server")) { |
| 691 | let orig = Reflect.get(t, prop, t); |
| 692 | return typeof orig === "function" ? orig.bind(t) : orig; |
| 693 | } |
| 694 | // Outside the surface: refuse a real member without invoking it (a |
| 695 | // getter would otherwise run and leak); an absent prop reads undefined. |
| 696 | let desc = exposedDescriptor(t, prop); |
| 697 | if (!desc) return undefined; |
| 698 | return typeof desc.value === "function" |
| 699 | ? (..._args: unknown[]): never => |
| 700 | missingMethod(validator.serviceName, prop) |
| 701 | : missingMethod(validator.serviceName, prop); |
| 702 | } |
| 703 | // `t` as receiver so a declared getter can read private state. |
| 704 | let orig = Reflect.get(t, prop, t); |
| 705 | if (isWrappedMethod(orig)) { |
| 706 | // Already wrapped in place by @validateRpc() on the class; don't |
| 707 | // validate twice. |
| 708 | return (orig as (...a: unknown[]) => unknown).bind(t); |
| 709 | } |
| 710 | if (!isUncheckedMethod(methodSpec) && methodSpec.isGetter) { |
| 711 | return validateReturn( |
| 712 | orig, |
| 713 | methodSpec.returns, |
| 714 | [validator.serviceName, prop], |
| 715 | "server", |
| 716 | validator.mode ?? "throw" |
| 717 | ); |
| 718 | } |
| 719 | if (typeof orig !== "function") return orig; |
| 720 | let mode = validator.mode ?? "throw"; |
| 721 | return function wrapped(this: unknown, ...args: unknown[]): unknown { |
| 722 | if (isUncheckedMethod(methodSpec)) { |
| 723 | return Reflect.apply(orig as (...a: unknown[]) => unknown, t, args); |
| 724 | } |
| 725 | checkArgs(mode, args, methodSpec, validator.serviceName, prop); |
| 726 | let wrappedArgs = wrapArgs(args, methodSpec, validator.serviceName, prop); |
| 727 | let result = Reflect.apply( |
| 728 | orig as (...a: unknown[]) => unknown, |
| 729 | t, |
| 730 | wrappedArgs |
| 731 | ); |
| 732 | return validateReturn( |
| 733 | result, |
no outgoing calls
no test coverage detected
searching dependent graphs…