UNPKG

worker-channel

Version:

A modern zero-dependency Worker communication and orchestration library

1 lines 25.4 kB
{"mappings":"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","sources":["src/main.ts","src/utils.ts","src/types.ts"],"sourcesContent":["/** @public @module main*/\nimport type {\n DataMessage,\n InternalReadQueue,\n InternalWriteQueue,\n InternalReadWriteQueue,\n NecessaryMessages,\n IChannelOptions,\n ChannelRelease,\n ChannelWrite,\n ChannelRead,\n ChannelReadAll,\n} from \"./types\";\nimport { consumeReader, writerIsClosed } from \"./utils\";\n\nexport abstract class Channel<\n Read extends DataMessage,\n Write extends DataMessage\n> {\n /** @internal */\n protected internalQueues!: {\n read?: InternalReadQueue<Read>;\n write?: InternalWriteQueue<Write>;\n transform?: InternalReadWriteQueue<Read, Write>;\n };\n\n /** Connect the readFrom or writeTo worker/port to either recieve from or send to to a different message port.\n * @param target The worker/port to send the `connection` change to.\n * @param action Whether you want to change the \"writable\" end or the \"readable\" end of the `target`\n * @param connection The connection that should now be written to or read from.\n */\n connect(\n target: \"readFrom\" | \"writeTo\",\n action: \"change-reader\" | \"change-writer\",\n connection: MessagePort\n ) {\n this._sendInternal(target, `worker-channel:${action}`, connection, [\n connection,\n ]);\n }\n\n /** @internal */\n private _sendInternal<T extends NecessaryMessages<Read, Write>[\"type\"]>(\n target: \"readFrom\" | \"writeTo\",\n type: T,\n data: (NecessaryMessages<Read, Write> & { type: T })[\"data\"],\n transfers?: Transferable[]\n ) {\n this[target]?.postMessage?.(\n {\n type,\n data,\n } as NecessaryMessages<Read, Write>,\n transfers ?? []\n );\n }\n\n constructor({\n controller = new AbortController(),\n writeTo = globalThis,\n readFrom = globalThis,\n }: IChannelOptions = {}) {\n this.controller = controller;\n // this.writeCommands = writeCommands;\n // this.readCommands = readCommands;\n this.writeTo = writeTo;\n this.readFrom = readFrom;\n this.listener = this.listener.bind(this);\n this.internalQueues = {};\n this.start();\n }\n /** @internal */\n protected readonly controller?: IChannelOptions[\"controller\"];\n /** @internal */\n protected writeTo: IChannelOptions[\"writeTo\"];\n /** @internal */\n protected readFrom: IChannelOptions[\"readFrom\"];\n\n /** @internal */\n private transforms?: Map<\n keyof InternalReadWriteQueue<Read, Write>,\n InternalReadWriteQueue<Read, Write>[keyof InternalReadWriteQueue<\n Read,\n Write\n >]\n >;\n\n /** @internal */\n private readables?: Map<\n keyof InternalReadQueue<Read>,\n InternalReadQueue<Read>[keyof InternalReadQueue<Read>]\n >;\n\n /** @internal */\n private writables?: Map<\n keyof InternalWriteQueue<Write>,\n InternalWriteQueue<Write>[keyof InternalWriteQueue<Write>]\n >;\n\n /** @internal */\n protected readWriteSetup() {\n this.transforms = new Map();\n this.internalQueues.transform = new Proxy(\n {} as InternalReadWriteQueue<Read, Write>,\n {\n get: (_obj, command) => {\n if (this.transforms?.has(command) ?? false) {\n const stream = this.transforms?.get(command);\n if (stream) return stream;\n }\n const transformStream = new TransformStream();\n this.transforms?.set(command, transformStream);\n return transformStream;\n },\n }\n );\n this.readSetup();\n this.writeSetup();\n }\n\n /** @internal */\n protected readSetup() {\n this.readables = new Map();\n this.internalQueues.read = new Proxy({} as InternalReadQueue<Read>, {\n get: (_obj, command) => {\n if (this.readables?.has(command) ?? false) {\n const stream = this.readables?.get(command);\n if (stream) return stream;\n }\n const readableStream = (\n this.internalQueues?.transform?.[\n command as keyof InternalReadWriteQueue<Read, Write>\n ]?.readable ?? new ReadableStream()\n ).getReader();\n this.readables?.set(command, readableStream);\n return readableStream;\n },\n });\n }\n\n /** @internal */\n protected writeSetup() {\n this.writables = new Map();\n this.internalQueues.write = new Proxy({} as InternalWriteQueue<Write>, {\n get: (_obj, command) => {\n if (this.writables?.has(command) ?? false) {\n const stream = this.writables?.get(command);\n if (stream) return stream;\n }\n const stream = (\n this.internalQueues?.transform?.[\n command as keyof InternalReadWriteQueue<Read, Write>\n ]?.writable ?? new WritableStream()\n ).getWriter();\n this.writables?.set(command, stream);\n return stream;\n },\n });\n }\n\n /** Propagate close on all writers of channel\n *\n * @example\n *\n * ```ts\n * const writer = new WriteChannel();\n *\n * // closes the \"string\" channel.\n * writer.close.writer.string();\n * ```\n */\n close = {\n writer: new Proxy({} as ChannelRelease<Write>, {\n get: (_target, command) => {\n return () => {\n (async () => {\n const writer = this.writables?.get(command);\n this._sendInternal(\n \"writeTo\",\n \"worker-channel:close-writer\",\n command\n );\n if (this.writeTo instanceof MessagePort) this.writeTo.close();\n if (writer && (await writerIsClosed(writer))) return;\n this.writables?.get(command)?.close();\n })();\n };\n },\n }),\n };\n\n /** Propagate cancel on all readers\n *\n * @example\n *\n * ```ts\n * const rChannel = new ReadChannel();\n *\n * // cancels the \"string\" channel.\n * rChannel.cancel.reader.string();\n * ```\n */\n cancel = {\n reader: new Proxy({} as ChannelRelease<Read>, {\n get: (_target, command) => {\n return () => {\n this.readables?.get(command)?.releaseLock();\n this._sendInternal(\n \"readFrom\",\n \"worker-channel:close-reader\",\n command\n );\n if (this.readFrom instanceof MessagePort) this.readFrom.close();\n };\n },\n }),\n };\n\n /** @internal */\n protected _send<T extends Write[\"type\"]>(\n type: T,\n data: (Write & { type: T })[\"data\"],\n transfer?: Transferable[]\n ) {\n return this.writeTo?.postMessage({ type, data }, transfer ?? []);\n }\n\n /** @internal */\n protected async _read<T extends Read[\"type\"]>(\n type: T\n ): Promise<Read[\"data\"] | undefined> {\n return (await this.internalQueues.read?.[type]?.read())?.value;\n }\n\n /** @internal */\n protected async *_readAll<T extends Read[\"type\"]>(\n type: T\n ): AsyncGenerator<(Read & { type: T })[\"data\"]> {\n const result = this.internalQueues.read?.[type];\n if (!result) return;\n yield* consumeReader(result);\n }\n\n /** @internal */\n protected async listen() {\n this.readFrom?.addEventListener?.(\n \"message\",\n this.listener as unknown as EventListener\n );\n }\n\n /** @internal */\n protected async unlisten() {\n this.readFrom?.removeEventListener?.(\n \"message\",\n this.listener as unknown as EventListener\n );\n }\n\n /** @internal */\n protected async listener(ev: MessageEvent<NecessaryMessages<Read, Write>>) {\n if (ev.data.type === \"worker-channel:change-reader\") {\n // sending inner listening channel\n this.unlisten();\n this.readFrom = ev.data.data;\n ev.data.data.start();\n this.listen();\n return;\n } else if (ev.data.type === \"worker-channel:change-writer\") {\n // Sending inner posting channel.\n // this._send(\"acknowledge\", true);\n this.writeTo = ev.data.data;\n return;\n } else if (ev.data.type === \"worker-channel:close-writer\") {\n this.close.writer[ev.data.data]();\n } else if (ev.data.type === \"worker-channel:close-reader\") {\n this.cancel.reader[ev.data.data]();\n } else {\n // send data accordingi to type.\n this.internalQueues.write?.[\n (ev.data as Write).type as Write[\"type\"]\n ]?.write((ev.data as Write).data);\n }\n }\n\n /** Starts the channel. Called automatically from the constructor,\n * but if you ever `.end()` the channel this will start it again.\n */\n start() {\n this.controller?.signal.addEventListener(\n \"abort\",\n () => {\n return this.end();\n },\n {\n once: true,\n }\n );\n }\n\n /** Ends the communication of the channel.\n * You can always restart the channel with `.start()`.\n */\n end() {\n this.readFrom?.removeEventListener(\n \"message\",\n this.listener as unknown as EventListener\n );\n this.readables?.clear();\n this.writables?.clear();\n this.transforms?.clear();\n }\n}\n\n/** Allows writing to a worker.\n *\n *\n * @example\n * An example worker script:\n *\n * ```ts\n * // Setup the channel to be \"string\" (denoted by the type) with data of type string (denoted by data).\n * type MyMessage = {type: \"string\", data: string};\n * const rwChannel = new ReadWriteChannel<MyMessage, MyMessage>();\n *\n * // writes to the string channel:\n * rwChannel.write.string(\"foo\");\n * ```\n */\nexport class WriteChannel<Write extends DataMessage> extends Channel<\n DataMessage<void>,\n Write\n> {\n start(): void {\n super.start();\n this.writeSetup();\n }\n /** Write to the channel.\n *\n * @example\n * An example worker script:\n * ```ts\n * // Setup the channel to be \"string\" (denoted by the type) with data of type string (denoted by data).\n * type MyMessage = {type: \"string\", data: string};\n * const rwChannel = new ReadWriteChannel<MyMessage, MyMessage>();\n *\n * // writes to the string channel:\n * rwChannel.write.string(\"foo\");\n * ```\n */\n readonly write: ChannelWrite<Write> = new Proxy({} as ChannelWrite<Write>, {\n get: (_target, command): ChannelWrite<Write>[keyof ChannelWrite<Write>] => {\n return (data, transfer) => this._send(command, data, transfer);\n },\n });\n}\n\n/** Creates a readable channel.\n *\n * @example\n * An example worker script:\n *\n * ```ts\n * // Setup the channel to be \"string\" (denoted by the type) with data of type string (denoted by data).\n * type MessageType = {type: \"string\", data: string};\n * const rChannel = new ReadChannel<MessageType>();\n *\n * // Read a single item from \"string\" channel.\n * console.log(await rChannel.read.string());\n * // Read everything from the \"string\" channel.\n * for await (const item of rChannel.readAll.string()) {\n * console.log(item);\n * }\n * ```\n * @public\n */\nexport class ReadChannel<Read extends DataMessage> extends Channel<\n Read,\n DataMessage<void>\n> {\n start(): void {\n super.start();\n this.listen();\n this.readWriteSetup();\n }\n /** Read from a channel.\n *\n * @example\n * An example worker script:\n *\n * ```ts\n * // Setup the channel to be \"string\" (denoted by the type) with data of type string (denoted by data).\n * type MessageType = {type: \"string\", data: string};\n * const rChannel = new ReadChannel<MessageType>();\n *\n * console.log(await rChannel.read.string())\n * ```\n */\n readonly read: ChannelRead<Read> = new Proxy({} as ChannelRead<Read>, {\n get: (_target, command) => {\n return () => this._read(command);\n },\n });\n\n /** Read everything from a channel.\n *\n * @example\n * An example worker script:\n *\n * ```ts\n *\n * // Setup the channel to be \"string\" (denoted by the type) with data of type string (denoted by data).\n * type MessageType = {type: \"string\", data: string};\n * const rChannel = new ReadChannel<MessageType>();\n *\n * // Read everything from the \"string\" channel.\n * for await (const item of rChannel.readAll.string()) {\n * console.log(item);\n * }\n * ```\n */\n readonly readAll: ChannelReadAll<Read> = new Proxy(\n {} as ChannelReadAll<Read>,\n {\n get: (_target, command: Read[\"type\"]) => {\n return () => this._readAll(command);\n },\n }\n );\n}\n\n/** ReadWriteChannel is a readable and writable Channel.\n * @example\n *\n * An example worker script:\n *\n * ```ts\n * // Setup the channel to be \"string\" (denoted by the type) with data of type string (denoted by data).\n * type MyMessage = {type: \"string\", data: string};\n * const rwChannel = new ReadWriteChannel<MyMessage, MyMessage>();\n *\n * (async () => {\n * // read each string from the 'string' channel (as declared by MyMessage).\n * for await (const item of rwChannel.readAll.string()) {\n * // write to the 'string' channel.\n * rwChannel.write.string(worker);\n * }\n * })();\n * ```\n */\nexport class ReadWriteChannel<\n Read extends DataMessage,\n Write extends DataMessage\n> extends Channel<Read, Write> {\n start(): void {\n super.start();\n this.listen();\n this.readWriteSetup();\n }\n /** Write to the channel.\n *\n * @example\n * ```ts\n * // Setup the channel to be \"string\" (denoted by the type) with data of type string (denoted by data).\n * type MyMessage = {type: \"string\", data: string};\n * const rwChannel = new ReadWriteChannel<MyMessage, MyMessage>();\n *\n * // writes to the string channel:\n * rwChannel.write.string(\"foo\");\n * ```\n */\n readonly write: ChannelWrite<Write> = new Proxy({} as ChannelWrite<Write>, {\n get: (_target, command): ChannelWrite<Write>[keyof ChannelWrite<Write>] => {\n return (data, transfer) => this._send(command, data, transfer);\n },\n });\n\n /** Read from the channel\n *\n * @example\n * ```ts\n * // Setup the channel to be \"string\" (denoted by the type) with data of type string (denoted by data).\n * type MyMessage = {type: \"string\", data: string};\n * const rwChannel = new ReadWriteChannel<MyMessage, MyMessage>();\n *\n * // Read data of type string from the \"string\" channel.\n * const str = await rwChannel.read.string();\n * ```\n */\n readonly read: ChannelRead<Read> = new Proxy({} as ChannelRead<Read>, {\n get: (_target, command) => {\n return () => this._read(command);\n },\n });\n\n /** Read from the channel\n *\n * @example\n * ```ts\n * // Setup the channel to be \"string\" (denoted by the type) with data of type string (denoted by data).\n * type MyMessage = {type: \"string\", data: string};\n * const rwChannel = new ReadWriteChannel<MyMessage, MyMessage>();\n *\n * for await (const item of rwChannel.readAll.string()) {\n * console.log(item);\n * }\n * ```\n */\n readonly readAll: ChannelReadAll<Read> = new Proxy(\n {} as ChannelReadAll<Read>,\n {\n get: (_target, command) => {\n return () => this._readAll(command);\n },\n }\n );\n}\n\nexport * from \"./utils\";\nexport * from \"./types\";\n","export async function* consumeStream<T>(\n readable: ReadableStream<T>\n): AsyncGenerator<Awaited<T>> {\n const reader = readable.getReader();\n yield* consumeReader(reader);\n}\nexport async function* consumeReader<T>(\n reader: ReadableStreamDefaultReader<T>\n): AsyncGenerator<Awaited<T>> {\n let done, value;\n do {\n ({ done, value } = await reader.read());\n if (!done) yield value as T;\n } while (!done);\n}\n\nexport class SleepAbortError extends Error {\n constructor(message = \"Sleep Aborted.\") {\n super(message);\n }\n}\n\nexport const sleep = (ms: number, controller?: AbortController) =>\n new Promise((res, rej) => {\n const id = setTimeout(res, ms);\n controller?.signal.addEventListener(\"abort\", () => {\n clearTimeout(id);\n rej(new SleepAbortError());\n }),\n {\n once: true,\n };\n });\n\nexport const Deferred = <Resolve, Reject>() => {\n let resolve!: (value: Resolve | PromiseLike<Resolve>) => void;\n let reject!: (reason?: Reject) => void;\n const promise = new Promise<Resolve>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n return { resolve, reject, promise };\n};\n\nexport function isDefined<T>(x: T): x is NonNullable<T> {\n return Boolean(x);\n}\n\nexport function writerIsClosed(writer: WritableStreamDefaultWriter) {\n return Promise.race([\n sleep(0).then(() => false),\n writer.closed.then(() => true),\n ]);\n}\n","export type ChannelWrite<DataMessages extends DataMessage> = {\n [P in DataMessages[\"type\"]]: (\n data: (DataMessages & { type: P })[\"data\"],\n transfer?: Transferable[]\n ) => void;\n};\n\nexport type ChannelRelease<DataMessages extends DataMessage> = {\n [P in DataMessages[\"type\"]]: () => void;\n};\n\nexport type ChannelRead<DataMessages extends DataMessage> = {\n [P in DataMessages[\"type\"]]: () => Promise<\n (DataMessages & { type: P })[\"data\"]\n >;\n};\n\nexport type ChannelReadAll<DataMessages extends DataMessage> = {\n [P in DataMessages[\"type\"]]: () => AsyncGenerator<\n (DataMessages & { type: P })[\"data\"]\n >;\n};\n\nexport type NecessaryMessages<\n Write extends DataMessage,\n Read extends DataMessage\n> =\n | { type: \"worker-channel:change-reader\"; data: MessagePort }\n | { type: \"worker-channel:change-writer\"; data: MessagePort }\n | { type: \"worker-channel:close-writer\"; data: Write[\"type\"] }\n | { type: \"worker-channel:close-reader\"; data: Read[\"type\"] }\n | { type: \"worker-channel:acknowledge\"; data: boolean };\n\n/** @public */\nexport type ChannelConnection = MessagePort | Worker | typeof globalThis;\n\n/** Channel options */\nexport interface IChannelOptions {\n /** Controls aborting the Channel. Basically the same as calling end. */\n controller?: AbortController;\n /** Where to write the messages to.\n * Defaults to the UI/main thread.\n * @default globalThis\n */\n writeTo?: ChannelConnection;\n /** Where to read the messages from.\n * Defaults to the UI/main thread.\n * @default globalThis\n */\n readFrom?: ChannelConnection;\n}\n\n/** A message type should usually be denoted by a union from the consumer of this library.\n * @public\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type DataMessage<Data = any> =\n | {\n /** The channel to create, write and read from. */\n type: string | number | symbol;\n /** The data the channel writes or reads */\n data: Data;\n }\n | {\n /** The channel to create, write and read from. */\n type: string | number | symbol;\n /** The data the channel writes or reads */\n data?: Data;\n };\nexport type InternalReadQueue<Read extends DataMessage> = Record<\n Read[\"type\"],\n ReadableStreamDefaultReader<Read[\"data\"]>\n>;\nexport type InternalWriteQueue<Write extends DataMessage> = Record<\n Write[\"type\"],\n WritableStreamDefaultWriter<Write[\"data\"]>\n>;\nexport type InternalReadWriteQueue<\n Read extends DataMessage,\n Write extends DataMessage\n> = Record<\n Read[\"type\"] | Write[\"type\"],\n TransformStream<Read[\"data\"], Write[\"data\"]>\n>;\n"],"names":[],"version":3,"file":"index.cjs.map"}