import type { ErrorObject } from 'serialize-error' import type { EventEmitter } from 'events' import type { Readable } from 'stream' import type { msgType } from './constants.js' export interface test { foo: boolean } export type NonEmptyArray = [T, ...T[]] export type MsgId = number export type Prop = string type EventName = string export type Args = Array type Params = Array type More = boolean type IsObjectMode = boolean export type MsgRequest = [ typeof msgType.REQUEST, MsgId, NonEmptyArray, Args, ] // The last message in a streaming request type MsgResponseEnd = [ typeof msgType.RESPONSE, MsgId, ErrorObject | null, any, false, // More data to come? IsObjectMode, // Last message in streaming response indicates if was objectMode ] export type MsgResponse = | [ typeof msgType.RESPONSE, MsgId, // messageId null, // error any, // result More?, // more data to come? ] | [typeof msgType.RESPONSE, MsgId, ErrorObject] | MsgResponseEnd export type MsgOn = [typeof msgType.ON, EventName, Array] export type MsgOff = [typeof msgType.OFF, EventName, Array] export type MsgEmit = [ typeof msgType.EMIT, EventName, Array, ErrorObject | null, Params?, ] export type Message = MsgRequest | MsgResponse | MsgOn | MsgOff | MsgEmit export type MessageContainer = { value: Message metadata?: Record } export type SubClient = ((...args: any[]) => Promise) & Client interface AnyMethod { [method: string]: SubClient } export type Client = AnyMethod & EventEmitter export interface MessagePortLike { on(event: 'message', listener: (value: any) => void): this off(event: 'message', listener: (value: any) => void): this postMessage(value: any): void } // Turn a sync function into an async function, or stream to return the collated stream type Asyncify any> = ReturnType extends Promise ? T : ReturnType extends Readable ? // TODO: Is there a way to type streams that we can use here? ( ...args: Parameters ) => Promise : (...args: Parameters) => Promise> type Filter = KeyType extends ExcludeType ? never : KeyType // These EventEmitter methods are unavailable in EventEmitter3, which is what is used on the client type UnavailableEmitterMethods = | 'setMaxListeners' | 'getMaxListeners' | 'prependListener' | 'prependOnceListener' export type ClientApi = { [KeyType in keyof ServerApi as Filter< KeyType, Symbol | UnavailableEmitterMethods >]: KeyType extends keyof EventEmitter ? ServerApi[KeyType] : ServerApi[KeyType] extends (...args: any[]) => any ? Asyncify : ServerApi[KeyType] extends Array ? () => Promise : ServerApi[KeyType] extends { [key: string]: any } ? ClientApi & (() => Promise) : ServerApi[KeyType] extends Symbol ? never : () => Promise } export type Metadata = Record export type MsgRequestObj = { msgId: MsgId method: NonEmptyArray args: Args metadata?: Metadata } export type Result = Promise | Readable