{"version":3,"file":"PostMessageStream.cjs","sourceRoot":"","sources":["../../src/browser/PostMessageStream.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * This module provides a pair of classes for creating readable and writable streams\n * over a [postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage).\n * function.\n *\n * @module PostMessage streams\n */\n\nimport { isObject } from '@metamask/utils';\n\nimport type { OnMessage, PostMessage } from './utils.ts';\nimport {\n  BaseDuplexStream,\n  isDuplexStreamSignal,\n  makeDuplexStreamInputValidator,\n} from '../BaseDuplexStream.ts';\nimport type { BaseReaderArgs, BaseWriterArgs } from '../BaseStream.ts';\nimport { BaseReader, BaseWriter } from '../BaseStream.ts';\nimport { isSignalLike } from '../utils.ts';\nimport type { Dispatchable } from '../utils.ts';\n\nexport type PostMessageTarget = {\n  addEventListener: (type: 'message', listener: OnMessage) => void;\n  removeEventListener: (type: 'message', listener: OnMessage) => void;\n  postMessage: PostMessage;\n};\n\ntype PostMessageReaderArgs<Read> = BaseReaderArgs<Read> & {\n  messageTarget: PostMessageTarget;\n} & (Read extends MessageEvent\n    ? {\n        messageEventMode: 'event';\n      }\n    : {\n        messageEventMode?: 'data' | undefined;\n      });\n\n/**\n * A readable stream over a {@link PostMessage} function.\n *\n * Ignores message events dispatched on its port that contain ports, but otherwise\n * expects {@link Dispatchable} values to be posted to its port.\n *\n * @see {@link PostMessageWriter} for the corresponding writable stream.\n */\nexport class PostMessageReader<Read> extends BaseReader<Read> {\n  /**\n   * Constructs a new {@link PostMessageReader}.\n   *\n   * @param options - Options bag for configuring the reader.\n   * @param options.messageTarget - The target to listen for messages on.\n   * @param options.validateInput - A function that validates input from the transport.\n   * @param options.onEnd - A function that is called when the stream ends.\n   * @param options.messageEventMode - Whether to pass the message event or just the data to the stream.\n   */\n  constructor({\n    validateInput,\n    onEnd,\n    messageTarget,\n    messageEventMode = 'data',\n  }: PostMessageReaderArgs<Read>) {\n    // eslint-disable-next-line prefer-const\n    let onMessage: OnMessage;\n\n    super({\n      validateInput,\n      onEnd: async (error) => {\n        messageTarget.removeEventListener('message', onMessage);\n        await onEnd?.(error);\n      },\n    });\n\n    const receiveInput = super.getReceiveInput();\n    onMessage = (messageEvent) => {\n      const value =\n        messageEventMode === 'data' ||\n        isSignalLike(messageEvent.data) ||\n        isDuplexStreamSignal(messageEvent.data)\n          ? messageEvent.data\n          : messageEvent;\n      receiveInput(value).catch(async (error) => this.throw(error));\n    };\n    messageTarget.addEventListener('message', onMessage);\n\n    harden(this);\n  }\n}\nharden(PostMessageReader);\n\nexport type PostMessageEnvelope<Write> = {\n  payload: Write;\n  transfer: Transferable[];\n};\n\n/**\n * Checks if the value is a post message envelope with a payload and transfer array.\n *\n * @param value - The value to check.\n * @returns True if the value is a post message envelope.\n */\nconst isPostMessageEnvelope = <Write>(\n  value: unknown,\n): value is PostMessageEnvelope<Write> =>\n  isObject(value) &&\n  typeof value.payload !== 'undefined' &&\n  Array.isArray(value.transfer);\n\n/**\n * A writable stream over a {@link PostMessage} function.\n *\n * @see {@link PostMessageReader} for the corresponding readable stream.\n */\nexport class PostMessageWriter<Write> extends BaseWriter<Write> {\n  /**\n   * Constructs a new {@link PostMessageWriter}.\n   *\n   * @param messageTarget - The target to post messages to.\n   * @param options - Options bag for configuring the writer.\n   * @param options.name - The name of the stream, for logging purposes.\n   * @param options.onEnd - A function that is called when the stream ends.\n   */\n  constructor(\n    messageTarget: PostMessageTarget,\n    { name, onEnd }: Omit<BaseWriterArgs<Write>, 'onDispatch'> = {},\n  ) {\n    super({\n      name,\n      onDispatch: (value: Dispatchable<Write>) => {\n        return isPostMessageEnvelope(value)\n          ? messageTarget.postMessage(value.payload, value.transfer)\n          : messageTarget.postMessage(value);\n      },\n      onEnd: async (error) => {\n        await onEnd?.(error);\n      },\n    });\n    harden(this);\n  }\n}\nharden(PostMessageWriter);\n\ntype PostMessageDuplexStreamArgs<Read> = PostMessageReaderArgs<Read>;\n\n/**\n * A duplex stream over a {@link PostMessage} function.\n *\n * @see {@link PostMessageReader} for the corresponding readable stream.\n * @see {@link PostMessageWriter} for the corresponding writable stream.\n */\nexport class PostMessageDuplexStream<\n  Read,\n  Write = Read,\n> extends BaseDuplexStream<\n  Read,\n  PostMessageReader<Read>,\n  Write,\n  PostMessageWriter<Write>\n> {\n  /**\n   * Constructs a new {@link PostMessageDuplexStream}.\n   *\n   * @param options - Options bag for configuring the duplex stream.\n   * @param options.messageTarget - The target for sending and receiving messages.\n   * @param options.validateInput - A function that validates input from the transport.\n   * @param options.onEnd - A function that is called when the stream ends.\n   */\n  constructor({\n    messageTarget,\n    validateInput,\n    onEnd,\n    ...args\n  }: PostMessageDuplexStreamArgs<Read>) {\n    let writer: PostMessageWriter<Write>; // eslint-disable-line prefer-const\n    const reader = new PostMessageReader<Read>({\n      ...args,\n      messageTarget,\n      validateInput: makeDuplexStreamInputValidator(validateInput),\n      onEnd: async () => {\n        await onEnd?.();\n        await writer.return();\n      },\n    } as PostMessageReaderArgs<Read>);\n    writer = new PostMessageWriter<Write>(messageTarget, {\n      name: 'PostMessageDuplexStream',\n      onEnd: async () => {\n        await onEnd?.();\n        await reader.return();\n      },\n    });\n    super(reader, writer);\n  }\n\n  /**\n   * Creates and synchronizes a new {@link PostMessageDuplexStream}.\n   *\n   * @param args - The options for configuring the duplex stream.\n   * @returns A synchronized duplex stream.\n   */\n  static async make<Read, Write = Read>(\n    args: PostMessageDuplexStreamArgs<Read>,\n  ): Promise<PostMessageDuplexStream<Read, Write>> {\n    const stream = new PostMessageDuplexStream<Read, Write>(args);\n    await stream.synchronize();\n    return stream;\n  }\n}\nharden(PostMessageDuplexStream);\n"]}