/// <reference types="node" resolution-mode="require"/>
import { BroadcastChannel } from 'worker_threads';
import type { MessengerRawData } from '../types/messenger.js';
import type { Awaitable } from '../types/utilities.js';
import type { Messagable } from '../types/streams.js';
import type { ConfirmStreamCallback } from '../types/streams.js';
import type { RemoveListenerFunction } from '../types/messages.js';
/**
 * Communicate like a boss 🗣️
 *
 * Use {@link Messenger} to send messages between tasks and services (workers), as well
 * as between the main thread and workers. Supported seamlessly by the rest of Nanolith.
 */
export declare class Messenger {
    #private;
    get closed(): boolean;
    /**
     * @param identifier An optional (but recommended) name for the `Messenger` that can be used
     * to reference it later on.
     *
     * @example
     * const messenger = new Messenger();
     * const messenger2 = new Messenger('my-messenger');
     */
    constructor(identifier?: string);
    /**
     * @param raw A {@link MessengerRawData} object containing an identifier reference to
     * another messenger.
     *
     * @example
     * const messenger = new Messenger('my-messenger');
     * const messenger2 = new Messenger(messenger.raw);
     */
    constructor(rawData: MessengerRawData);
    /**
     * The unique identifier that is shared across all messenger instances using
     * the two ports originally created when instantiating the first {@link Messenger}.
     *
     * @example
     * const messenger = new Messenger('my-messenger');
     * console.log(messenger.ID); // -> 'my-messenger'
     *
     * const messenger2 = new Messenger(messenger.raw);
     * console.log(messenger.ID === messenger2.ID) // -> true
     */
    get ID(): string;
    /**
     * Each `Messenger` instance is assigned a unique key that allows it to internally ignore
     * messages on the {@link BroadcastChannel} which were sent by itself.
     *
     * @example
     * const messenger = new Messenger('my-messenger');
     * const messenger2 = new Messenger(messenger.raw);
     *
     * console.log(messenger.ID === messenger2.ID) // -> true
     * console.log(messenger.uniqueKey === messenger2.uniqueKey) // -> false
     */
    get uniqueKey(): `${string}-${string}-${string}-${string}-${string}`;
    /**
     * Create a {@link Writable} instance that can be piped into in order to stream data to
     * other `Messenger`s on the channel. The messengers can listen for incoming streams with the
     * `messenger.onStream()` listener.
     *
     * @param metaData Any specific data about the stream that should be accessible when
     * using it.
     */
    createStream(metaData?: Record<string | number, any>): Promise<import("../streams/index.js").WritableToPort<Messagable>>;
    /**
     * Receive data streams on the `Messenger`.
     *
     * @param callback The callback to run once the stream has been initialized and is ready to consume.
     */
    onStream(callback: ConfirmStreamCallback<Messagable>): RemoveListenerFunction;
    /**
     * Listen for messages coming to the `Messenger`.
     *
     * @param callback A function to run each time a message is received.
     *
     * @returns A function that will remove the listener when called.
     *
     * @example
     * messenger.onMessage<string>((data) => console.log(data, 'received!'));
     */
    onMessage<Data = any>(callback: (data: Data) => Awaitable<void>): RemoveListenerFunction;
    /**
     * Wait for specific messages on the `Messenger`.
     *
     * @param callback A function returning a boolean that will be run each time a message is received from another `Messenger`
     * Once the condition is met and the function returns `true`, the promise will resolve with the data received.
     *
     * @returns A promise of the received data.
     *
     * @example
     * const data = await messenger.waitForMessage<{ foo: string }>(({ foo }) => foo === 'bar');
     *
     * console.log(data);
     */
    waitForMessage<Data = any>(callback: (data: Data) => Awaitable<boolean>): Promise<Data>;
    /**
     * Send a messenger to be received by any other `Messenger` instances with the same identifier.
     *
     * @param data The data to send to the other `Messenger`s.
     *
     * @example
     * messenger.sendMessage('foo');
     * messenger.sendMessage({ hello: 'world' });
     */
    sendMessage<Data = any>(data: Data): void;
    /**
     * Turns the {@link Messenger} instance into an object that can be sent to and from workers.
     *
     * @returns A {@link MessengerRawData} object
     */
    get raw(): MessengerRawData;
    /**
     * By default, the {@link BroadcastChannel} is unreffed. Use this method to change that.
     * When `true`, [`ref()`](https://nodejs.org/api/worker_threads.html#broadcastchannelref) will be called.
     * When `false`, [`unref()`](https://nodejs.org/api/worker_threads.html#broadcastchannelunref) will be called.
     */
    setRef(option: boolean): BroadcastChannel | undefined;
    /**
     * Closes the underlying {@link BroadcastChannel} connection that is being used.
     * Does not close all Messenger objects. Use `messenger.closeAll()` instead for that.
     */
    close(): void;
    /**
     * Closes all underlying {@link BroadcastChannel} connections on all {@link Messenger}
     * objects that are currently active for the corresponding identifier.
     */
    closeAll(): void;
}
