@cloudpss/ubrpc
Version:
Rpc server/client build on websocket and ubjson.
91 lines (77 loc) • 3.23 kB
text/typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { InteropObservable, Observable } from 'rxjs';
/** 可转换为 Observable 的类型 */
export type ObservableLike<T> = Observable<T> | InteropObservable<T> | AsyncIterable<T>;
/** Returns a boolean for whether the two given types are equal. */
type IsEqual<A, B> = (<G>() => G extends A ? 1 : 2) extends <G>() => G extends B ? 1 : 2 ? true : false;
/** 作为通知输出的方法 */
type IsNotificationReturn<R> =
IsEqual<R, void> extends true
? true
: IsEqual<R, undefined> extends true
? true
: R extends PromiseLike<void> | void
? true
: false;
/** 作为 Observable 输出的方法 */
type ObservableReturn = ObservableLike<any> | PromiseLike<ObservableLike<any>>;
/** 提取类型中的方法 */
export type Methods<T> = {
[P in keyof T]: T[P] extends (...args: any[]) => infer R ? (R extends ObservableReturn ? never : P) : never;
}[keyof T] &
string;
/** 提取类型中的通知 */
export type Notifications<T> = {
[P in keyof T]: T[P] extends (...args: any[]) => infer R
? IsNotificationReturn<R> extends true
? P
: never
: never;
}[keyof T] &
string;
/** 提取类型中的订阅主题 */
export type Subjects<T> = {
[P in keyof T]: T[P] extends (...args: any[]) => ObservableReturn ? P : never;
}[keyof T] &
string;
/** RPC 调用的参数 */
export type RpcParameters<T> = T extends (...args: infer R) => any ? R : never;
/** RPC 调用的返回 */
type RpcReturnsMap<R> = Awaited<R> extends ObservableLike<infer U> ? U : Awaited<R>;
/** RPC 调用的返回 */
export type RpcReturns<T> = T extends (...args: any[]) => infer R ? RpcReturnsMap<R> : never;
/** RPC 调用函数的实现 */
type RpcField<T> = T extends (...args: infer P) => infer R
? Awaited<R> extends ObservableReturn
? (...args: P) => ObservableLike<RpcReturnsMap<R>> | PromiseLike<ObservableLike<RpcReturnsMap<R>>>
: (...args: P) => RpcReturnsMap<R> | PromiseLike<RpcReturnsMap<R>>
: never;
/** RPC 调用对象的实现 */
export type RpcObject<T> = {
[K in keyof T as K & (Subjects<T> | Methods<T>)]: RpcField<T[K]>;
};
// interface A {
// field: number;
// /** methodA */
// methodA(x: number): number | undefined;
// methodB: (x: string, y: number) => Promise<number>;
// readonly methodC: () => Iterable<number>;
// readonly methodD: () => void | Promise<null | undefined>;
// readonly notificationA: () => undefined;
// readonly notificationB: () => Promise<void>;
// notificationC(): void;
// readonly notificationD: () => void | PromiseLike<undefined>;
// readonly notificationE: () => void | Promise<void>;
// subjectA(x: number): Observable<number>;
// subjectB: (x: string) => Promise<Observable<number>>;
// subjectC: () => PromiseLike<InteropObservable<number>>;
// subjectD: () => AsyncGenerator<number>;
// subjectE: () => PromiseLike<AsyncGenerator<number>>;
// }
// type X = Methods<A>;
// type Y = Subjects<A>;
// type Z = Notifications<A>;
// type R = RpcObject<A>;
// type Test = R['field'];
// declare const r: R;
// r.subjectA;