@xylabs/threads
Version:
Web workers & worker threads as simple as a function call
69 lines (57 loc) • 2.49 kB
text/typescript
/* eslint-disable import-x/no-internal-modules */
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { SerializedError } from './types/messages.ts'
export interface Serializer<Msg = JsonSerializable, Input = any> {
deserialize(message: Msg): Input
serialize(input: Input): Msg
}
export interface SerializerImplementation<Msg = JsonSerializable, Input = any> {
deserialize(message: Msg, defaultDeserialize: (msg: Msg) => Input): Input
serialize(input: Input, defaultSerialize: (inp: Input) => Msg): Msg
}
export function extendSerializer<MessageType, InputType = any>(
extend: Serializer<MessageType, InputType>,
implementation: SerializerImplementation<MessageType, InputType>,
): Serializer<MessageType, InputType> {
const fallbackDeserializer = extend.deserialize.bind(extend)
const fallbackSerializer = extend.serialize.bind(extend)
return {
deserialize(message: MessageType): InputType {
return implementation.deserialize(message, fallbackDeserializer)
},
serialize(input: InputType): MessageType {
return implementation.serialize(input, fallbackSerializer)
},
}
}
type JsonSerializablePrimitive = string | number | boolean | null
type JsonSerializableObject = {
[key: string]: JsonSerializablePrimitive | JsonSerializablePrimitive[] | JsonSerializableObject | JsonSerializableObject[] | undefined
}
export type JsonSerializable = JsonSerializablePrimitive | JsonSerializablePrimitive[] | JsonSerializableObject | JsonSerializableObject[]
const DefaultErrorSerializer: Serializer<SerializedError, Error> = {
deserialize(message: SerializedError): Error {
return Object.assign(new Error(message.message), {
name: message.name,
stack: message.stack,
})
},
serialize(error: Error): SerializedError {
return {
__error_marker: '$$error',
message: error.message,
name: error.name,
stack: error.stack,
}
},
}
const isSerializedError = (thing: any): thing is SerializedError =>
thing && typeof thing === 'object' && '__error_marker' in thing && thing.__error_marker === '$$error'
export const DefaultSerializer: Serializer<JsonSerializable> = {
deserialize(message: JsonSerializable): any {
return isSerializedError(message) ? DefaultErrorSerializer.deserialize(message) : message
},
serialize(input: any): JsonSerializable {
return input instanceof Error ? (DefaultErrorSerializer.serialize(input) as any as JsonSerializable) : input
},
}