import { ZodType } from 'zod'; import { HyperRPCEvent } from './event'; import { FnBuilder, HyperRPCFn } from './fn'; export type MetaObject = { connId: string; authToken?: string; }; type HyperRPCBaseFn = HyperRPCFn; type HyperRPCBaseEvent = HyperRPCEvent; type ServiceFields = HyperRPCService | HyperRPCBaseFn | HyperRPCBaseEvent; export class HyperRPCService { path: string = ''; constructor( public hyperRPC: HyperRPC, public subservices: Record, public functions: Record, public events: Record, ) {} root(path: string = '') { // defines the current service as the root. // sets the root path for all subservices relative to this service, recursively. // remove leading slash this.path = path; Object.entries(this.subservices).forEach(([name, svc]) => { svc.root(path === '' ? name : `${path}/${name}`); }); return this; } } export class HyperRPC { contextFn: (base: { $meta: MetaObject }) => Context | Promise = async () => ({}) as any; context( fn: (base: { $meta: MetaObject }) => T | Promise, ): HyperRPC { this.contextFn = fn as any; return this as any; } fn, O extends ZodType>( input: I, output: O, ) { return new FnBuilder(input, output); } event(event: T) { return new HyperRPCEvent(event); } service(handlers: { [key: string]: ServiceFields }) { const subservices: Record = {}; const functions: Record = {}; const events: Record = {}; Object.entries(handlers).forEach(([name, p]) => { if (p instanceof HyperRPCService) { subservices[name] = p; } else if (p instanceof HyperRPCFn) { functions[name] = p; } else if (p instanceof HyperRPCEvent) { events[name] = p; } }); return new HyperRPCService(this, subservices, functions, events); } }