@xylabs/threads
Version:
Web workers & worker threads as simple as a function call
79 lines (74 loc) • 3.54 kB
TypeScript
import { Observable } from 'observable-fns';
import { ObservablePromise } from './observable-promise.js';
declare const $errors: unique symbol;
declare const $events: unique symbol;
declare const $terminate: unique symbol;
declare const $transferable: unique symbol;
declare const $worker: unique symbol;
interface TransferDescriptor<T = any> {
[$transferable]: true;
send: T;
transferables: Transferable[];
}
interface ObservableLikeSubscription {
unsubscribe(): any;
}
interface ObservableLike<T> {
subscribe(onNext: (value: T) => any, onError?: (error: any) => any, onComplete?: () => any): ObservableLikeSubscription;
subscribe(listeners: {
complete?(): any;
error?(error: any): any;
next?(value: T): any;
}): ObservableLikeSubscription;
}
type StripAsync<Type> = Type extends Promise<infer PromiseBaseType> ? PromiseBaseType : Type extends ObservableLike<infer ObservableBaseType> ? ObservableBaseType : Type;
type StripTransfer<Type> = Type extends TransferDescriptor<infer BaseType> ? BaseType : Type;
type ModuleMethods = {
[methodName: string]: (...args: any) => any;
};
type ProxyableArgs<Args extends any[]> = Args extends [arg0: infer Arg0, ...rest: infer RestArgs] ? [Arg0 extends Transferable ? Arg0 | TransferDescriptor<Arg0> : Arg0, ...RestArgs] : Args;
type ProxyableFunction<Args extends any[], ReturnType> = Args extends [] ? () => ObservablePromise<StripTransfer<StripAsync<ReturnType>>> : (...args: ProxyableArgs<Args>) => ObservablePromise<StripTransfer<StripAsync<ReturnType>>>;
type ModuleProxy<Methods extends ModuleMethods> = {
[method in keyof Methods]: ProxyableFunction<Parameters<Methods[method]>, ReturnType<Methods[method]>>;
};
interface PrivateThreadProps {
[$errors]: Observable<Error>;
[$events]: Observable<WorkerEvent>;
[$terminate]: () => Promise<void>;
[$worker]: Worker;
}
type FunctionThread<Args extends any[] = any[], ReturnType = any> = ProxyableFunction<Args, ReturnType> & PrivateThreadProps;
type ModuleThread<Methods extends ModuleMethods = any> = ModuleProxy<Methods> & PrivateThreadProps;
interface AnyFunctionThread extends PrivateThreadProps {
(...args: any[]): ObservablePromise<any>;
}
interface AnyModuleThread extends PrivateThreadProps {
}
/** Worker thread. Either a `FunctionThread` or a `ModuleThread`. */
type Thread = AnyFunctionThread | AnyModuleThread;
type TransferList = Transferable[];
/** Worker instance. Either a web worker or a node.js Worker provided by `worker_threads` or `tiny-worker`. */
interface Worker extends EventTarget {
postMessage(value: any, transferList?: TransferList): void;
/** In nodejs 10+ return type is Promise while with tiny-worker and in browser return type is void */
terminate(callback?: (error?: Error, exitCode?: number) => void): void | Promise<number>;
}
/** Event as emitted by worker thread. Subscribe to using `Thread.events(thread)`. */
declare enum WorkerEventType {
internalError = "internalError",
message = "message",
termination = "termination"
}
interface WorkerInternalErrorEvent {
error: Error;
type: WorkerEventType.internalError;
}
interface WorkerMessageEvent<Data> {
data: Data;
type: WorkerEventType.message;
}
interface WorkerTerminationEvent {
type: WorkerEventType.termination;
}
type WorkerEvent = WorkerInternalErrorEvent | WorkerMessageEvent<any> | WorkerTerminationEvent;
export type { FunctionThread as F, ModuleThread as M, StripAsync as S, Thread as T, WorkerEvent as W, Worker as a };