/** * Mailbox - Pure XState v5 Implementation * https://github.com/huan/mailbox * * @copyright 2024 Huan LI (李卓桓) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Pure XState v5 Mailbox Implementation * * Key differences from the v4-compat implementation: * 1. Uses native XState v5 APIs (setup, createActor, sendTo, etc.) * 2. Uses invoke instead of spawnChild for proper parent-child communication * 3. Simplified queue management leveraging XState v5's native FIFO mailbox * 4. Uses inspection API for event tracking * 5. No compatibility shim needed */ import { SimulatedClock as XStateSimulatedClock, waitFor as xstateWaitFor } from 'xstate'; import type { ActorOptions, AnyActorLogic, AnyEventObject, EventObject } from 'xstate'; /** * Clock type extracted from XState's ActorOptions. * This ensures compatibility with future XState versions. * @see https://github.com/statelyai/xstate/blob/main/packages/core/src/system.ts */ type Clock = NonNullable['clock']>; import { type Observer, type Unsubscribable } from 'rxjs'; import 'symbol-observable'; /** * Mailbox event types - these are the internal protocol events */ export declare const Type: { /** Child actor signals it's ready for next message */ readonly ACTOR_IDLE: "mailbox/ACTOR_IDLE"; /** Child actor sends a reply to be forwarded to original sender */ readonly ACTOR_REPLY: "mailbox/ACTOR_REPLY"; /** Dead letter - message that couldn't be delivered */ readonly DEAD_LETTER: "mailbox/DEAD_LETTER"; }; export type MailboxType = (typeof Type)[keyof typeof Type]; /** * Mailbox states - for checking mailbox wrapper state */ export declare const State: { /** Mailbox is idle, ready for messages */ readonly Idle: "idle"; /** Mailbox is processing a message (child is busy) */ readonly Processing: "processing"; }; export type MailboxState = (typeof State)[keyof typeof State]; /** * Mailbox events - factory functions for creating typed events */ export declare const Event: { ACTOR_IDLE: () => { readonly type: "mailbox/ACTOR_IDLE"; }; ACTOR_REPLY: (message: T) => { readonly type: "mailbox/ACTOR_REPLY"; readonly payload: { readonly message: T; }; }; DEAD_LETTER: (message: AnyEventObject, reason?: string) => { readonly type: "mailbox/DEAD_LETTER"; readonly payload: { readonly message: AnyEventObject; readonly reason: string | undefined; }; }; }; export type MailboxEvent = ReturnType | ReturnType | ReturnType; /** * Options for creating a Mailbox */ export interface MailboxOptions { /** Maximum queue capacity (default: Infinity) */ capacity?: number; /** Logger function for debugging */ logger?: (...args: any[]) => void; /** Enable XState devTools */ devTools?: boolean; /** Custom clock for testing with SimulatedClock */ clock?: Clock; } /** * Address interface for sending messages to a Mailbox */ export interface Address { /** Send an event to this address */ send: (event: AnyEventObject) => void; /** Get the session ID of this address */ id: string; /** String representation */ toString: () => string; } /** * Mailbox interface - the public API for interacting with a Mailbox */ export interface Mailbox { /** Send an event to the mailbox */ send: (event: TEvent | TEvent['type']) => void; /** The mailbox address for external communication */ address: Address; /** String ID of the mailbox */ id: string; /** Start the mailbox */ open: () => void; /** Stop the mailbox */ close: () => void; /** Subscribe to events from the child actor */ subscribe: (observer: Partial>) => Unsubscribable; /** RxJS interop */ [Symbol.observable]: () => Mailbox; /** RxJS interop (legacy) */ '@@observable': () => Mailbox; } interface QueueItem { event: AnyEventObject; origin?: string; } interface MailboxContext { /** Message queue */ queue: QueueItem[]; /** Currently processing message */ currentMessage?: QueueItem; /** Maximum queue capacity */ capacity: number; } /** * Check if an event type is a Mailbox internal type * Only mailbox/* events are internal - xstate.* events are valid state machine events */ export declare function isMailboxType(type: string): boolean; /** * Create a mailbox wrapper machine for the given child logic */ export declare function createMailboxMachine(childLogic: TChildLogic, options?: MailboxOptions): import("xstate").StateMachine | undefined; }, { src: "childActor"; logic: TChildLogic; id: string | undefined; }, { type: "logMessage"; params: { message: string; }; } | { type: "enqueueMessage"; params: import("xstate").NonReducibleUnknown; } | { type: "dequeueMessage"; params: import("xstate").NonReducibleUnknown; } | { type: "clearCurrentMessage"; params: import("xstate").NonReducibleUnknown; } | { type: "forwardToChild"; params: import("xstate").NonReducibleUnknown; }, { type: "hasQueuedMessages"; params: unknown; } | { type: "isNotMailboxEvent"; params: unknown; }, never, "idle" | "processing", string, import("xstate").NonReducibleUnknown, import("xstate").NonReducibleUnknown, EventObject, import("xstate").MetaObject, { id: "mailbox"; states: { readonly idle: {}; readonly processing: {}; }; }>; /** * Actions to be used by child machines wrapped in a Mailbox */ export declare const actions: { /** * Signal that the child actor is idle and ready for the next message. * Call this in entry actions of idle states. */ idle: (_machineId: string) => any; /** * Send a reply back through the mailbox to the original sender. * The mailbox will route it to whoever sent the original message. */ reply: (eventOrFn: TEvent | ((args: { context: any; event: any; }) => TEvent)) => any; /** * Proxy events to a mailbox */ proxy: (_sourceId: string) => (mailbox: Mailbox) => any; }; /** * Create a Mailbox from an actor logic definition * * @param logic The child actor logic to wrap in a mailbox * @param options Mailbox options * @returns A Mailbox instance * * @example * ```ts * const childMachine = createMachine({ * id: 'worker', * initial: 'idle', * states: { * idle: { * entry: Mailbox.actions.idle('worker'), * on: { WORK: 'working' } * }, * working: { * entry: Mailbox.actions.reply({ type: 'DONE' }), * always: 'idle' * } * } * }) * * const mailbox = Mailbox.from(childMachine) * mailbox.open() * mailbox.send({ type: 'WORK' }) * ``` */ export declare function from(logic: TLogic, options?: MailboxOptions): Mailbox; /** * Check if a value is a Mailbox */ export declare function isMailbox(value: unknown): value is Mailbox; /** * Check if a value is an Address */ export declare function isAddress(value: unknown): value is Address; export declare const SimulatedClock: typeof XStateSimulatedClock; export declare const waitFor: typeof xstateWaitFor; export {}; //# sourceMappingURL=mailbox.d.ts.map