import { C as InjectionToken, D as Newable, E as MaybePromise, O as Nullable, S as ValueBindingDescriptor, T as AbstractClass, _ as BindingType, a as WirestateErrorHandler, b as InstanceBindingDescriptor, c as EventEmitOptions, d as EventUnsubscribe, f as WireEvent, g as BindingScopeValue, h as BindingScope, i as WirestateErrorContext, k as Optional, l as EventHandler, m as BindingDescriptor, n as ContainerConfig, o as WirestateErrorSource, p as Binding, r as WirestatePlugin, s as defaultWirestateErrorHandler, t as Container, u as EventType, v as BindingTypeValue, w as getBindingToken, x as ServiceToken, y as FactoryBindingDescriptor } from "./lib.js"; /** * Numeric ID for one provider provision cycle of a service instance. * * @remarks * IDs are unique only within a single service instance. Pass the value handed to * `@OnProvision` and `@OnDeprovision` to {@link WireStatus.isStale} to ignore * async work from an older provision cycle. * * @group Lifecycle */ type ProvisionId = number; /** * Read-only lifecycle status for one resolved service instance. * * @remarks * Wirestate keeps one stable `WireStatus` object per resolved service instance and updates it as * the container and provider lifecycle progress. Application code can hold a reference and read * the current flags without mutating the instance or requiring a base class. The flags are * `readonly`: Wirestate advances them internally, and application code only reads them. * * @group Lifecycle */ declare class WireStatus { /** * Returns the lifecycle status tracked for a resolved service instance. * * @remarks * Use this inside service methods when async work needs to check whether the * service has been deactivated or deprovisioned. The instance must already be * tracked, which it is from activation onward, so every lifecycle hook and any * method reachable from one can call it. To start tracking from a constructor, * where activation has not run yet, use {@link WireStatus.track} instead. * * @group Lifecycle * * @param instance - Resolved service instance to inspect. * @returns The stable lifecycle status for the instance. * * @throws {@link WirestateError} If the object is not tracked by Wirestate. */ static for(instance: object): WireStatus; /** * Starts lifecycle tracking for an instance and returns its status. * * @remarks * Use this in a service constructor to hold the status as a field, which is * the only form that reaches async methods outside the lifecycle hooks: * * ```ts * public constructor(private readonly status: WireStatus = WireStatus.track(this)) {} * ``` * * Idempotent: an already-tracked instance keeps its existing status object, so * a constructor call and the later activation share one stable status. * * @group Lifecycle * * @param instance - Service instance to track. * @returns The stable lifecycle status for the instance. */ static track(instance: object): WireStatus; /** * Whether the instance was deactivated and removed from its container. */ readonly isDeactivated: boolean; /** * Whether the instance has been removed from provider ownership. * * @remarks * `null` means the instance has not reached provider lifecycle yet. * `false` means the instance is currently owned by a provider. `true` means * the provider deprovisioned it. */ readonly isDeprovisioned: Nullable; /** * Current provider provision cycle ID for the instance. * * @remarks * Every instance a container owns is stamped for the cycle, not only the ones declaring * `@OnProvision` or `@OnDeprovision`, so {@link WireStatus.isStale} can report a superseded * cycle for any service. * * `null` means the instance has not entered a tracked provider provision cycle: it is not owned * by a provisioned container, or it was resolved after the current cycle had already wired its * instances, in which case the next cycle stamps it. */ readonly provisionId: Nullable; /** * Container that activated the instance. See {@link MutableWireStatus.container}. */ private container; /** * Last provision id issued to the instance. See {@link MutableWireStatus.lastProvisionId}. */ private lastProvisionId; private constructor(); /** * Whether the instance should stop work because its lifecycle ended. * * @remarks * Derived from `isDeactivated` and `isDeprovisioned`. * * @returns `true` once the instance was deactivated or deprovisioned. */ get isInactive(): boolean; /** * Reports whether work started in a provision cycle should be discarded. * * @remarks * The guard for anything that resumes after an `await`. It is stale when the * instance ended its lifecycle (deactivated or deprovisioned) or when a newer * provision cycle has superseded the one the work belongs to: * * ```ts * public async onProvision(provisionId: ProvisionId): Promise { * const result = await loadResult(); * * if (this.status.isStale(provisionId)) { * return; * } * * this.applyResult(result); * } * ``` * * Both clauses matter. Deprovision restores `provisionId` to the value the hook * received, and deactivation leaves it untouched, so an id comparison alone stays * equal and lets a late result through after the lifecycle has ended. * * Outside a provision hook, snapshot `provisionId` before the `await` and pass * the snapshot back. A `null` snapshot means the instance had not been * provisioned yet, and stays current until a cycle starts. * * @group Lifecycle * * @param provisionId - Provision cycle the work belongs to, as passed to * `@OnProvision` or snapshotted from {@link WireStatus.provisionId}. * @returns Whether the work belongs to an ended or superseded lifecycle. */ isStale(provisionId: Nullable): boolean; } /** * Method decorator returned by the single-method lifecycle hooks: * `@OnActivation`, `@OnDeactivation`, `@OnProvision`, and `@OnDeprovision`. * * @remarks * The decorated method must accept the arguments its phase delivers and nothing more, so a hook * declaring a parameter the runtime never passes is rejected at compile time. Activation hooks * receive no arguments. Provision hooks may declare the `ProvisionId` of the cycle. * * @template Method - Signature the decorated method must be assignable to. * * @group Lifecycle */ interface LifecycleDecorator) => unknown = () => unknown> { (value: (this: This, ...args: Parameters) => unknown, context: ClassMethodDecoratorContext): void; (target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor): void; } /** * Runs an instance method after container activation completes. * * @remarks * Activation happens the first time the singleton instance is resolved. * * Use it for cheap resolution-time initialization that does not open resources. * Prefer `@OnProvision` for subscriptions, timers, sockets, observers, and * async work that needs cleanup. A class hierarchy may have one activation * hook name. * * @group Lifecycle * * @returns Method decorator. * * @example * ```typescript * import { Injectable, OnActivation } from "@wirestate/core"; * * @Injectable() * class FeedService { * @OnActivation() * public onActivation(): void { * this.initializeDefaults(); * } * } * ``` */ declare function OnActivation(): LifecycleDecorator; /** * Runs an instance method during container deactivation. * * @remarks * Deactivation happens when the container unbinds or disposes the instance. * * Use it for container-disposal cleanup. Prefer `@OnDeprovision` for work * started by provider ownership, such as subscriptions, timers, sockets, and * observers. A class hierarchy may have one deactivation hook name. * * @group Lifecycle * * @returns Method decorator. * * @example * ```typescript * import { Injectable, OnDeactivation } from "@wirestate/core"; * * @Injectable() * class FeedService { * @OnDeactivation() * public onDeactivation(): void { * this.disposeResources(); * } * } * ``` */ declare function OnDeactivation(): LifecycleDecorator; /** * Resolves the binding kind of a binding. * * @remarks * A bare service class binds as an instance binding. For a descriptor, an explicit `type` * wins, a `factory` field means a factory binding, and anything else is a value binding. * Use it instead of reading `type` directly, which is optional for value and factory * descriptors and absent on a bare class. * * @group Bind * * @param binding - Service class or descriptor to inspect. * @returns The binding kind, inferred from the binding shape when not declared. * * @example * ```typescript * import { getBindingType, Injectable } from "@wirestate/core"; * * @Injectable() * class UserService {} * * getBindingType(UserService); // "Instance" * getBindingType({ token: "API_URL", value: "https://api.example.com" }); // "Value" * getBindingType({ token: "API_CLIENT", factory: () => createClient() }); // "Factory" * ``` */ declare function getBindingType(binding: Binding): BindingTypeValue; /** * Resolves the caching scope of a binding. * * @remarks * A bare service class binds as a singleton, and value descriptors are always singletons. * Factory and instance descriptors may declare a `Transient` scope and otherwise default * to `Singleton`. Use it instead of reading `scope` directly, which is optional and absent * on both value descriptors and a bare class. * * @group Bind * * @param binding - Service class or descriptor to inspect. * @returns The binding scope, `Singleton` by default. * * @example * ```typescript * import { BindingScope, BindingType, getBindingScope, Injectable } from "@wirestate/core"; * * @Injectable() * class UserService {} * * getBindingScope(UserService); // "Singleton" * getBindingScope({ * token: "REQUEST_ID", * type: BindingType.Factory, * scope: BindingScope.Transient, * factory: () => crypto.randomUUID(), * }); // "Transient" * ``` */ declare function getBindingScope(binding: Binding): BindingScopeValue; /** * Resolves a dependency from the container currently constructing a service. * * @remarks * Use `inject()` in constructor defaults or field initializers of * `@Injectable()` classes, or inside factory bindings. Dependency resolution * uses the same rules as `Container.get()`, including parent lookup. * * @group Container * * @template T - Value type resolved for the token. * * @param token - Token to resolve from the current container. * @returns The resolved value. * * @throws {@link WirestateError} If the token is not bound, * or if a circular dependency is detected while constructing the value. * Errors thrown by a binding's constructor or factory propagate unchanged. * @throws Error If there is no active injection context. */ declare function inject(token: ServiceToken): T; /** * Optionally resolves a dependency from the current injection context. * * @template T - Value type resolved for the token. * * @param token - Token to resolve from the current container. * @param options - Optional lookup options. * @param options.optional - Return `undefined` instead of throwing on a miss. * @returns The resolved value, or `undefined` when the token is not bound. * * @throws Error If there is no active injection context. */ declare function inject(token: ServiceToken, options: { optional: true; }): Optional; /** * Returns a lazy resolver for a dependency in the current injection context. * * @remarks * The returned function closes over the active container and resolves the token * when called. Use it to break circular dependencies or avoid constructing a * dependency until a method needs it. * * @template T - Value type resolved for the token. * * @param token - Token to resolve from the current container. * @param options - Lazy lookup options. * @param options.lazy - Return a resolver function instead of resolving immediately. * @returns Function that resolves the token when called. * * @throws Error If there is no active injection context. */ declare function inject(token: ServiceToken, options: { lazy: true; }): () => T; /** * Returns a lazy optional resolver for a dependency in the current injection context. * * @template T - Value type resolved for the token. * * @param token - Token to resolve from the current container. * @param options - Lazy optional lookup options. * @param options.lazy - Return a resolver function instead of resolving immediately. * @param options.optional - Return `undefined` from the resolver on a miss. * @returns Function that resolves the token when called, or returns `undefined` when missing. * * @throws Error If there is no active injection context (thrown eagerly, before the resolver is returned). */ declare function inject(token: ServiceToken, options: { lazy: true; optional: true; }): () => Optional; /** * Validates container construction config without creating a container. * * @remarks * Use it in framework adapters or tests that accept `ContainerConfig` and want * fast feedback before a `Container` is constructed. The same validation runs * in the `Container` constructor. * * @group Container * * @param config - Container configuration to validate. * @throws {@link WirestateError} If `onError` is not a function. * @throws {@link WirestateError} If `activate` references a token missing from `bindings`. * * @example * ```typescript * import { Injectable, validateContainerConfig } from "@wirestate/core"; * * @Injectable() * class LoggerService {} * * validateContainerConfig({ * bindings: [LoggerService], * }); * ``` */ declare function validateContainerConfig(config: ContainerConfig): void; /** * Error type thrown for expected Wirestate API failures. * * @remarks * Use `code` for programmatic checks and `message` for humans. Wirestate uses * this for failures a caller can handle, such as invalid config, missing * bindings, missing required handlers, and lifecycle access after disposal. * * @group Error * * @example * ```typescript * import { Container, WirestateError } from "@wirestate/core"; * * class MissingService {} * * const container = new Container(); * * try { * container.get(MissingService); * } catch (error) { * if (error instanceof WirestateError) { * console.error(error.code, error.message); * } * } * ``` */ declare class WirestateError extends Error { /** * Error class name used for diagnostics. */ readonly name: string; /** * Stable string code identifying the failure type. * * @remarks * Use this when application code needs a specific branch. */ readonly code: string; /** * Human-readable diagnostic message. */ readonly message: string; /** * Creates a Wirestate error. * * @param message - Human-readable diagnostic message. * @param code - String code for the failure type. */ constructor(message: string, code?: string); } /** * Describes the decorator returned by {@link Injectable}. * * @remarks * Supports both TC39 and legacy experimental decorators. * * @group Container */ interface InjectableDecorator { >(value: T, context: ClassDecoratorContext): void; >(value: T): void; } /** * Marks a class as eligible for Wirestate instance bindings. * * @remarks * Instance bindings require the implementation class to be decorated with * `@Injectable()`. The mark is stored on the exact class. Subclasses must be * decorated separately when they are bound directly. * * The decorator supports both TC39 standard decorators and legacy TypeScript * decorators. * * @group Container * * @returns A class decorator registering the class as injectable. * * @throws {@link WirestateError} If the decorator is applied to a non-class TC39 target. */ declare function Injectable(): InjectableDecorator; /** * Checks whether a class was directly marked with {@link Injectable}. * * @remarks * The check does not walk the prototype chain. A subclass of an injectable * class returns `false` until that subclass is decorated too. * * @group Container * * @param target - Class to check. * @returns Whether the class is marked as injectable. */ declare function isInjectable(target: Newable): boolean; /** * Shared storage and dispatch logic for buses that route a token to one active handler. * * @remarks * Handlers are stacked per type: registering the same type repeatedly forms a * stack and the newest registration wins until it unregisters. * * @template Type - Token type used to address handlers. * * @group Messaging * @internal */ declare abstract class HandlerStackBus { /** * Internal handler storage. * Uses a stack for each type to support shadowing. */ private readonly handlers; /** * Builds the error thrown when a required dispatch finds no handler. * * @param type - Token that failed to resolve to a handler. * @returns The error to throw. */ protected abstract createMissingHandlerError(type: T): WirestateError; /** * Checks if at least one handler is registered for the given type. * * @param type - Token to inspect. * @returns `true` if a handler is available, `false` otherwise. */ hasHandler(type: T): boolean; /** * Returns the active (newest) handler for a type, or `undefined`. * * @param type - Token to inspect. * @returns The active handler, or `undefined` when the stack is empty. */ private peek; /** * Dispatches to the active handler and returns its result as-is. * * @remarks * If a handler returns a Promise, that Promise is returned untouched. * * @template R - Type of the handler result. * @template P - Type of the payload. * * @param type - Token to dispatch. * @param payload - Payload passed to the handler. * @returns The handler result. * * @throws {@link WirestateError} If no handler is registered. */ protected dispatch(type: T, payload?: P): R; /** * Dispatches to the active handler and Promise-wraps the result. * * @remarks * Sync values are wrapped. Async values are passed through. The method is `async`, so a missing * handler rejects the returned promise rather than throwing at the call site. * * @template R - Type of the handler result. * @template P - Type of the payload. * * @param type - Token to dispatch. * @param payload - Payload passed to the handler. * @returns A Promise resolving to the handler result, rejected with a {@link WirestateError} * when no handler is registered. */ protected dispatchAsync(type: T, payload?: P): Promise; /** * Dispatches to the active handler if one exists, otherwise returns `undefined`. * * @template R - Type of the handler result. * @template P - Type of the payload. * * @param type - Token to dispatch. * @param payload - Payload passed to the handler. * @returns The handler result, or `undefined` when no handler exists. */ protected dispatchOptional(type: T, payload?: P): Optional; /** * Dispatches to the active handler if one exists and Promise-wraps the result, * otherwise resolves to `undefined`. * * @template R - Type of the handler result. * @template P - Type of the payload. * * @param type - Token to dispatch. * @param payload - Payload passed to the handler. * @returns A Promise resolving to the handler result, or `undefined` when no handler exists. */ protected dispatchOptionalAsync(type: T, payload?: P): Promise>; /** * Pushes a handler onto the stack for a type. * * @remarks * Multiple handlers for one type form a stack. The newest handler is active. * * @template R - Type of the handler result. * @template P - Type of the payload. * * @param type - Token the handler answers. * @param handler - Handler function. * @returns A callback that removes this exact registration. */ protected registerHandler(type: T, handler: (payload: P) => MaybePromise): () => void; /** * Removes the newest registration whose handler matches by reference. * * @remarks * If the handler was not registered for the given type, this does nothing. * * @template R - Type of the handler result. * @template P - Type of the payload. * * @param type - Token whose stack to update. * @param handler - The handler function instance to remove. */ protected unregisterHandler(type: T, handler: (payload: P) => MaybePromise): void; /** * Removes one registration by identity and drops the stack once it is empty. * * @param type - Token whose stack to update. * @param registration - The registration instance to remove. */ private removeRegistration; } /** * Identifies one imperative message handled by a command handler. * * @remarks * Commands represent write-oriented work such as save, login, reset, etc. * Prefer strings for public command contracts and symbols for private commands * that should not collide with other packages. * * @group Commands * * @example * ```typescript * const LOGIN: CommandType = "USER/LOGIN"; * * const LOCAL_RESET: CommandType = Symbol("LOCAL_RESET"); * ``` */ type CommandType = string | symbol | number; /** * Handles a dispatched command payload and returns the command result. * * @remarks * A handler may return a plain value or a Promise. `CommandBus.execute(...)` * returns that result as-is. `CommandBus.executeAsync(...)` Promise-normalizes it. * * @group Commands * * @template R - Result type, optionally a Promise. * @template P - Payload type. * @template T - Command type. * * @example * ```typescript * const loginHandler: CommandHandler = (credentials) => auth.login(credentials); * ``` */ type CommandHandler = ((payload: P) => MaybePromise) & { readonly type?: T; }; /** * Removes one command handler registration. * * @remarks * The callback returned by `CommandBus.register(...)` removes that exact * registration. If a command has a shadowed handler underneath it, unregistering * the active handler restores the previous one. * * @group Commands * * @example * ```typescript * const unregister: CommandUnregister = commandBus.register("MY_COMMAND", handler); * * unregister(); * ``` */ type CommandUnregister = () => void; /** * Per-dispatch options for {@link CommandBus.execute} and {@link CommandBus.executeAsync}. * * @group Commands * * @example * ```typescript * const receipt = commandBus.execute("UPLOAD", draft, { optional: true }); * ``` */ interface CommandDispatchOptions { /** * Allows a missing handler and returns `undefined` instead of throwing. */ readonly optional?: boolean; } declare class CommandBus extends HandlerStackBus { /** * Builds the error thrown when a required command dispatch finds no handler. * * @param type - Command type that failed to resolve. * @returns The error to throw. */ protected createMissingHandlerError(type: CommandType): WirestateError; /** * Dispatches an optional command and returns the handler result as-is. * * @remarks * Returns `undefined` when no handler exists. If a handler returns a Promise, * this returns that Promise. Pass a literal `{ optional: true }` so the result * narrows to `Optional`. * * @template R - Result type. * @template P - Payload type. * @template T - Command type. * * @param type - Command token. * @param payload - Command payload. * @param options - Dispatch options with `optional: true`. * @returns The command result, or `undefined` when no handler exists. */ execute(type: T, payload: Optional

, options: CommandDispatchOptions & { optional: true; }): Optional; /** * Dispatches a required command and returns the handler result as-is. * * @remarks * Throws when no handler is registered. If a handler returns a Promise, this * returns that Promise. Use {@link executeAsync} when the caller should always * receive a Promise. * * @template R - Result type. * @template P - Payload type. * @template T - Command type. * * @param type - Command token. * @param payload - Command payload. * @param options - Dispatch options. * @returns The command handler result. * * @throws {@link WirestateError} If no handler is registered. * * @example * ```typescript * const saved: SaveResult = commandBus.execute("SAVE_DRAFT", draft); * ``` */ execute(type: T, payload?: P, options?: CommandDispatchOptions & { optional?: false; }): R; /** * Dispatches a command whose optionality is decided at runtime. * * @template R - Result type. * @template P - Payload type. * @template T - Command type. * * @param type - Command token. * @param payload - Command payload. * @param options - Dispatch options with a runtime-decided `optional` flag. * @returns The command result, or `undefined` when the dispatch is optional and no handler exists. * * @throws {@link WirestateError} If the dispatch is required and no handler is registered. */ execute(type: T, payload: Optional

, options: CommandDispatchOptions): Optional; /** * Dispatches an optional command and returns a Promise for the result. * * @remarks * Synchronous handler results are wrapped. Resolves to `undefined` when no * handler exists. Pass a literal `{ optional: true }` so the result narrows to * `Optional`. * * @template R - Result type. * @template P - Payload type. * @template T - Command type. * * @param type - Command token. * @param payload - Command payload. * @param options - Dispatch options with `optional: true`. * @returns A Promise resolving to the command result, or `undefined` when no handler exists. */ executeAsync(type: T, payload: Optional

, options: CommandDispatchOptions & { optional: true; }): Promise>; /** * Dispatches a required command and returns a Promise for the result. * * @remarks * Rejects when no handler is registered - it never throws synchronously, so the miss has to be * caught by awaiting or by a `.catch`, not by a `try` around the call. Use {@link execute} when * a missing handler should surface at the call site instead. Synchronous handler results are * wrapped. Promises returned by handlers are passed through. * * @template R - Result type. * @template P - Payload type. * @template T - Command type. * * @param type - Command token. * @param payload - Command payload. * @param options - Dispatch options. * @returns A Promise resolving to the command result, rejected with a * {@link WirestateError} when no handler is registered. */ executeAsync(type: T, payload?: P, options?: CommandDispatchOptions & { optional?: false; }): Promise; /** * Dispatches a command whose optionality is decided at runtime and returns a Promise. * * @remarks * Selected when `optional` is a plain `boolean`, as with an options object built elsewhere. The * result is `Optional` because the call may resolve to `undefined` for a miss. Pass a literal * `{ optional: true }` or omit the option to select a narrower overload. * * @template R - Result type. * @template P - Payload type. * @template T - Command type. * * @param type - Command token. * @param payload - Command payload. * @param options - Dispatch options with a runtime-decided `optional` flag. * @returns A Promise resolving to the command result, or `undefined` when the dispatch is optional and * no handler exists, rejected with a {@link WirestateError} when it is required and no handler exists. */ executeAsync(type: T, payload: Optional

, options: CommandDispatchOptions): Promise>; /** * Registers a command handler. * * @remarks * Registering another handler for the same type shadows the previous one. Unregistering the newest restores it. * * @template R - Result type. * @template P - Payload type. * @template T - Command type. * * @param type - Command type. * @param handler - Function to execute when the command is dispatched. * @returns A function to unregister the handler. * * @example * ```typescript * const unregister: CommandUnregister = commandBus.register("LOG_MESSAGE", (message: string) => { * console.log(message); * }); * ``` */ register(type: T, handler: CommandHandler): CommandUnregister; /** * Removes a previously registered command handler. * * @remarks * If the handler was not registered for the given type, this operation does nothing. * * @template R - Result type. * @template P - Payload type. * @template T - Command type. * * @param type - Command type. * @param handler - The handler function instance to remove. */ unregister(type: T, handler: CommandHandler): void; } /** * Self-contained wiring for one kind of messaging handler. * * @remarks * Each messaging decorator (`@OnEvent` / `@OnCommand` / `@OnQuery`) contributes * one registration per class, carrying the bus token it needs and a strategy * that wires an activated instance's handlers of that kind to the bus. The * activation dispatcher reads these generically and never imports a bus, so an * unused bus is never pulled into the bundle by the activation path. * * @group Container * @internal */ interface MessagingRegistration { /** * Distinguishes the kind (one registration per kind survives per class). */ readonly kind: symbol; /** * Bus this kind resolves and wires handlers onto. */ readonly token: ServiceToken; /** * Wires the instance's handlers of this kind onto the bus. * * @param bus - The resolved bus instance. * @param instance - The activated instance. * @param container - Container that owns the instance. * @returns Teardown callbacks collected onto the activation record. */ readonly register: (bus: object, instance: object, container: Container) => Array<() => void>; } /** * Built-in base for the messaging plugins (`EventsPlugin` / `CommandsPlugin` / * `QueriesPlugin`). * * @remarks * Each concrete plugin supplies the {@link MessagingRegistration} for its kind * (`{ kind, token, register }`, declared beside the decorator). The base then: * * @internal */ declare abstract class MessagingPlugin implements WirestatePlugin { private readonly registration; protected constructor(registration: MessagingRegistration); install(container: Container): void; participates(token: ServiceToken): boolean; onProvision(instance: object, container: Container, addDisposer: (dispose: () => void) => void): void; } /** * Enables command messaging on a container. * * @remarks * Register it (`new Container({ plugins: [new CommandsPlugin()] })`) to bind the * {@link CommandBus} and wire `@OnCommand` handlers at provision. Importing this * class is what pulls the command bus into the bundle. * * A child container can register its own `CommandsPlugin` for a local bus, or * omit it to use the nearest ancestor bus. * * @group Plugins * * @example * ```typescript * import { CommandsPlugin, Container, Injectable } from "@wirestate/core"; * * @Injectable() * class CartService {} * * const container = new Container({ bindings: [CartService], plugins: [new CommandsPlugin()] }); * ``` */ declare class CommandsPlugin extends MessagingPlugin { constructor(); } /** * Method decorator shape shared by the messaging handler decorators. * * @group Messaging * @internal */ interface MessagingHandlerDecorator { (value: (this: This, ...args: Array) => unknown, context: ClassMethodDecoratorContext): void; (target: object, propertyKey: string | symbol, descriptor: PropertyDescriptor): void; } /** * Describes the decorator returned by {@link OnCommand}. * * @remarks * Supports both TC39 and legacy experimental decorators. * * @group Commands */ type OnCommandDecorator = MessagingHandlerDecorator; /** * Marks an injectable service method as a provision-scoped command handler. * * @remarks * The handler is registered when the owning container is provisioned and * unregistered when that provision cycle ends. Register {@link CommandsPlugin} * on the container, or on an ancestor container, to enable command handlers. * * One command call goes to one handler: the newest registered handler for the * command token. The method receives the command payload and may return either a * plain value or a Promise. * * @group Commands * * @param type - Command token. * @returns Method decorator. * * @example * ```typescript * import { Injectable, OnCommand } from "@wirestate/core"; * * @Injectable() * class UserService { * @OnCommand("USER_LOGIN") * public onUserLogin(credentials: Credentials): Promise { * return auth.login(credentials); * } * } * ``` */ declare function OnCommand(type: CommandType): OnCommandDecorator; /** * Describes the decorator returned by {@link OnEvent}. * * @remarks * Supports both TC39 and legacy experimental decorators. * * @group Events */ type OnEventDecorator = MessagingHandlerDecorator; /** * Marks an injectable service method as a provision-scoped event handler. * * @remarks * The handler is registered when the owning container is provisioned and * unregistered when that provision cycle ends. Register {@link EventsPlugin} * on the container, or on an ancestor container, to enable event handlers. * * Omit `types` to receive every event emitted on the active event bus. Repeated * types are deduplicated for one decorated method. * * @group Events * * @param types - Event token or tokens. Omit for all events. * @returns Method decorator. * * @example * ```typescript * import { Injectable, OnEvent, type WireEvent } from "@wirestate/core"; * * interface User { * id: string; * } * * @Injectable() * class MyService { * @OnEvent("USER_LOGGED_IN") * private onLogin(event: WireEvent): void { * console.log(event.payload?.id); * } * } * ``` */ declare function OnEvent(types?: EventType | ReadonlyArray): OnEventDecorator; declare class EventBus { private readonly container; /** * Subscriptions indexed by event type. */ private readonly handlers; constructor(container?: Container); /** * Emits an event to matching subscribers. * * @remarks * Every matching handler is snapshotted before the first one runs, so subscriptions can change * while an event is being emitted: one emit reaches exactly the subscribers that existed when it * started, whether a handler subscribes or unsubscribes mid-dispatch. Those changes take effect * from the next emit. Dispatch does not await handler promises. If a handler throws or rejects, * Wirestate reports it through the container error handler and continues with the next * subscriber. Catch-all subscribers run before type-specific subscribers. * * @template P - Payload type. * @template T - Event type. * @template S - Source type. * * @param type - Event token. * @param payload - Event payload. * @param options - Event emission options. * * @example * ```typescript * eventBus.emit("USER_LOGGED_IN", { userId: "123" }, { source: authService }); * ``` */ emit

(type: T, payload?: P, options?: EventEmitOptions): void; /** * Subscribes to every event on this bus. * * @remarks * Equivalent to `subscribe(null, handler)`. * * @param handler - Event handler invoked for every emitted event. * @returns Function that removes this subscription. * * @example * ```typescript * const unsubscribe: EventUnsubscribe = eventBus.subscribe((event) => { * console.log("Received event:", event); * }); * ``` */ subscribe(handler: EventHandler): EventUnsubscribe; /** * Subscribes to one or more event types. * * @remarks * Pass `null` to subscribe to every event. Each call is independent: * subscribing the same function twice delivers the event twice, and each * returned unsubscriber removes only its own subscription. An empty type list * subscribes to nothing. * * @param types - Event type, list of event types, or `null` for every event. * @param handler - Event handler invoked for matching events. * @returns Function that removes this subscription. * * @example * ```typescript * const unsubscribe: EventUnsubscribe = eventBus.subscribe(["USER_ADDED", "USER_REMOVED"], (event) => { * refreshList(); * }); * ``` */ subscribe(types: Nullable>, handler: EventHandler): EventUnsubscribe; /** * Removes one of a handler's catch-all subscriptions. * * @remarks * Prefer the unsubscriber returned by {@link subscribe}. This by-reference form * removes the newest catch-all subscription that uses the handler. * * @param handler - The handler function instance to remove. */ unsubscribe(handler: EventHandler): void; /** * Removes one of a handler's subscriptions for one or more event types. * * @remarks * For each given type, removes the newest subscription that uses the handler. * Pass `null` to target catch-all subscriptions. * * @param types - Event type, list of event types, or `null` for catch-all. * @param handler - The handler function instance to remove. */ unsubscribe(types: Nullable>, handler: EventHandler): void; /** * Checks if the bus has any active subscribers. * * @returns `true` if at least one handler is registered, `false` otherwise. */ hasSubscribers(): boolean; /** * Resolves the bucket keys a subscription targets. * * @remarks * `null` (catch-all) maps to the private {@link ALL_EVENTS_TYPE} key. Types are * deduplicated so one call registers a subscription once per distinct type. * * @param types - Event type, list of event types, or `null` for catch-all. * @returns The distinct bucket keys. */ private resolveKeys; /** * Removes one subscription from a bucket and drops the bucket once it is empty. * * @param key - Event type, or the {@link ALL_EVENTS_TYPE} key, whose bucket to update. * @param subscription - The subscription instance to remove. */ private removeSubscription; /** * Removes a single subscription that uses a handler from a bucket and drops the bucket once it is empty. * * @param key - Event type, or the {@link ALL_EVENTS_TYPE} key, whose bucket to update. * @param handler - Handler whose subscription to remove. */ private removeByHandler; /** * Invokes a snapshot of subscriptions, isolating individual handler failures. * * @param subscriptions - Snapshot of subscriptions to invoke. * @param event - Event passed to each handler. */ private dispatch; } /** * Enables event messaging on a container. * * @remarks * Register it (`new Container({ plugins: [new EventsPlugin()] })`) to bind the * {@link EventBus} and wire `@OnEvent` handlers at provision. Importing this class * is what pulls the event bus into the bundle. * * A child container can register its own `EventsPlugin` for a local bus, or omit * it to use the nearest ancestor bus. * * @group Plugins * * @example * ```typescript * import { Container, EventsPlugin, Injectable } from "@wirestate/core"; * * @Injectable() * class CartService {} * * const container = new Container({ bindings: [CartService], plugins: [new EventsPlugin()] }); * ``` */ declare class EventsPlugin extends MessagingPlugin { constructor(); } /** * Identifies one read-oriented message handled by a query handler. * * @remarks * Queries represent request/response reads such as current user, labels, cached * state, or computed view data. Prefer strings for public query contracts and * symbols for private queries that should not collide with other packages. * * @group Queries * * @example * ```typescript * const CURRENT_USER: QueryType = "USER/CURRENT"; * * const LOCAL_SUMMARY: QueryType = Symbol("LOCAL_SUMMARY"); * ``` */ type QueryType = string | symbol | number; /** * Answers a dispatched query payload and returns the query result. * * @remarks * A handler may return a plain value or a Promise. `QueryBus.query(...)` * returns that result as-is. `QueryBus.queryAsync(...)` Promise-normalizes it. * * @group Queries * * @template R - Result type, optionally a Promise. * @template P - Payload type. * @template T - Query type. * * @example * ```typescript * const currentUserHandler: QueryHandler = () => userRepository.current(); * ``` */ type QueryHandler = ((payload: P) => MaybePromise) & { readonly type?: T; }; /** * Removes one query handler registration. * * @remarks * The callback returned by `QueryBus.register(...)` removes that exact * registration. If a query has a shadowed handler underneath it, unregistering * the active handler restores the previous one. * * @group Queries * * @example * ```typescript * const unregister: QueryUnregister = queryBus.register("GET_USER", handler); * * unregister(); * ``` */ type QueryUnregister = () => void; /** * Per-dispatch options for {@link QueryBus.query} and {@link QueryBus.queryAsync}. * * @group Queries * * @example * ```typescript * const flags = queryBus.query("FEATURE_FLAGS", undefined, { optional: true }); * ``` */ interface QueryDispatchOptions { /** * Allows a missing handler and returns `undefined` instead of throwing. * * @remarks * Pass a literal `true` so TypeScript selects the optional overload. */ readonly optional?: boolean; } declare class QueryBus extends HandlerStackBus { /** * Builds the error thrown when a required query dispatch finds no handler. * * @param type - Query type that failed to resolve. * @returns The error to throw. */ protected createMissingHandlerError(type: QueryType): WirestateError; /** * Dispatches an optional query and returns the handler result as-is. * * @remarks * Returns `undefined` when no handler exists. If a handler returns a Promise, * this returns that Promise. Pass a literal `{ optional: true }` so the result * narrows to `Optional`. * * @template R - Result type. * @template P - Payload type. * @template T - Query type. * * @param type - Query type. * @param payload - Optional payload for the handler. * @param options - Dispatch options with `optional: true`. * @returns The query result, or `undefined` when no handler exists. */ query(type: T, payload: Optional

, options: QueryDispatchOptions & { optional: true; }): Optional; /** * Dispatches a required query and returns the handler result as-is. * * @remarks * Throws when no handler is registered. If a handler returns a Promise, this * method returns that Promise. Use {@link queryAsync} when the caller should * always receive a Promise. * * @template R - Result type. * @template P - Payload type. * @template T - Query type. * * @param type - Query type. * @param payload - Optional payload for the handler. * @param options - Dispatch options. * @returns The result of the query execution. * * @throws {@link WirestateError} If no handler is registered for the given type. * * @example * ```typescript * const user: User = queryBus.query("FIND_USER", "user-id-123"); * ``` */ query(type: T, payload?: P, options?: QueryDispatchOptions & { optional?: false; }): R; /** * Dispatches a query whose optionality is decided at runtime. * * @template R - Result type. * @template P - Payload type. * @template T - Query type. * * @param type - Query token. * @param payload - Query payload. * @param options - Dispatch options with a runtime-decided `optional` flag. * @returns The query result, or `undefined` when the dispatch is optional and no handler exists. * * @throws {@link WirestateError} If the dispatch is required and no handler is registered. */ query(type: T, payload: Optional

, options: QueryDispatchOptions): Optional; /** * Dispatches an optional query and returns a Promise for the result. * * @remarks * Synchronous handler results are wrapped. Resolves to `undefined` when no * handler exists. Pass a literal `{ optional: true }` so the result narrows to * `Optional`. * * @template R - Result type. * @template P - Payload type. * @template T - Query type. * * @param type - Query type. * @param payload - Optional payload for the handler. * @param options - Dispatch options with `optional: true`. * @returns A Promise resolving to the query result, or `undefined` when no handler exists. */ queryAsync(type: T, payload: Optional

, options: QueryDispatchOptions & { optional: true; }): Promise>; /** * Dispatches a required query and returns a Promise for the result. * * @remarks * Rejects when no handler is registered - it never throws synchronously, so the miss has to be * caught by awaiting or by a `.catch`, not by a `try` around the call. Use {@link query} when a * missing handler should surface at the call site instead. Synchronous handler results are * wrapped. Promises returned by handlers are passed through. * * @template R - Result type. * @template P - Payload type. * @template T - Query type. * * @param type - Query type. * @param payload - Optional payload for the handler. * @param options - Dispatch options. * @returns A Promise resolving to the query result, rejected with a {@link WirestateError} when * no handler is registered for the given type. */ queryAsync(type: T, payload?: P, options?: QueryDispatchOptions & { optional?: false; }): Promise; /** * Dispatches a query whose optionality is decided at runtime and returns a Promise. * * @template R - Result type. * @template P - Payload type. * @template T - Query type. * * @param type - Query token. * @param payload - Query payload. * @param options - Dispatch options with a runtime-decided `optional` flag. * @returns A Promise resolving to the query result, or `undefined` when the dispatch is optional and * no handler exists, rejected with a {@link WirestateError} when it is required and no handler exists. */ queryAsync(type: T, payload: Optional

, options: QueryDispatchOptions): Promise>; /** * Registers a query handler. * * @remarks * Registering another handler for the same type shadows the previous one. Unregistering the newest restores it. * * @template R - Result type. * @template P - Payload type. * @template T - Query type. * * @param type - Query token. * @param handler - Query handler. * @returns Function that unregisters this handler. * * @example * ```typescript * const unregister: QueryUnregister = queryBus.register("GET_NOW", () => Date.now()); * ``` */ register(type: T, handler: QueryHandler): QueryUnregister; /** * Removes a previously registered query handler. * * @remarks * If the handler was not registered for the given type, this operation does nothing. * * @template R - Result type. * @template P - Payload type. * @template T - Query type. * * @param type - Query type. * @param handler - The handler function instance to remove. */ unregister(type: T, handler: QueryHandler): void; } /** * Enables query messaging on a container. * * @remarks * Register it (`new Container({ plugins: [new QueriesPlugin()] })`) to bind the * {@link QueryBus} and wire `@OnQuery` handlers at provision. Importing this class * is what pulls the query bus into the bundle. * * A child container can register its own `QueriesPlugin` for a local bus, or * omit it to use the nearest ancestor bus. * * @group Plugins * * @example * ```typescript * import { Container, QueriesPlugin, Injectable } from "@wirestate/core"; * * @Injectable() * class CartService {} * * const container = new Container({ bindings: [CartService], plugins: [new QueriesPlugin()] }); * ``` */ declare class QueriesPlugin extends MessagingPlugin { constructor(); } /** * Describes the decorator returned by {@link OnQuery}. * * @remarks * Supports both TC39 and legacy experimental decorators. * * @group Queries */ type OnQueryDecorator = MessagingHandlerDecorator; /** * Marks an injectable service method as a provision-scoped query handler. * * @remarks * The handler is registered when the owning container is provisioned and * unregistered when that provision cycle ends. Register {@link QueriesPlugin} * on the container, or on an ancestor container, to enable query handlers. * * Queries answer read-oriented requests. One query call goes to one handler: * the newest registered handler for the query token. * * @group Queries * * @param type - Query token. * @returns Method decorator. * * @example * ```typescript * import { Injectable, OnQuery } from "@wirestate/core"; * * @Injectable() * class UserProfileService { * private readonly avatars = new Map(); * * @OnQuery("GET_USER_AVATAR") * public onGetUserAvatar(userId: string): string { * return this.avatars.get(userId) ?? ""; * } * } * ``` */ declare function OnQuery(type: QueryType): OnQueryDecorator; /** * Signature a provision-phase hook must be assignable to: zero parameters, or the cycle's `ProvisionId`. */ type ProvisionHook$1 = (provisionId: ProvisionId) => unknown; /** * Runs before a framework provider stops exposing the container. * * @remarks * React and Lit providers call this when a container leaves a UI subtree. * This is provider lifetime, not instance lifetime. * * Use it to clean up work started by `@OnProvision`. A class hierarchy may * have one deprovision hook name. * * Hooks run in the exact reverse of `@OnProvision` order, so a service can still use the * dependencies it injected: they deprovision after it does. * * @group Lifecycle * * @returns Method decorator. * * @example * ```typescript * import { Injectable, OnDeprovision } from "@wirestate/core"; * * @Injectable() * class PanelService { * @OnDeprovision() * public onDeprovision(): void { * this.stopPolling(); * this.disconnect(); * } * } * ``` */ declare function OnDeprovision(): LifecycleDecorator; /** * Signature a provision-phase hook must be assignable to: zero parameters, or the cycle's `ProvisionId`. */ type ProvisionHook = (provisionId: ProvisionId) => unknown; /** * Runs when a framework provider exposes the container. * * @remarks * React and Lit providers call this when a container enters a UI subtree. * This is provider lifetime, not instance lifetime. * * Use it for subscriptions, timers, sockets, observers, provider-scoped async * work, or any resource that should be cleaned up when the provider releases * the container. A class hierarchy may have one provision hook name. * * Hooks run in creation order, so a service can rely on the dependencies it injected having * provisioned already. `@OnDeprovision` unwinds the exact reverse. * * @group Lifecycle * * @returns Method decorator. * * @example * ```typescript * import { Injectable, OnProvision } from "@wirestate/core"; * * @Injectable() * class PanelService { * @OnProvision() * public onProvision(): void { * this.startPolling(); * this.connect(); * } * } * ``` */ declare function OnProvision(): LifecycleDecorator; export { type AbstractClass, type Binding, type BindingDescriptor, BindingScope, type BindingScopeValue, BindingType, type BindingTypeValue, CommandBus, type CommandDispatchOptions, type CommandHandler, type CommandType, type CommandUnregister, CommandsPlugin, Container, type ContainerConfig, EventBus, type EventEmitOptions, type EventHandler, type EventType, type EventUnsubscribe, EventsPlugin, type FactoryBindingDescriptor, Injectable, type InjectableDecorator, InjectionToken, type InstanceBindingDescriptor, type LifecycleDecorator, type Newable, OnActivation, OnCommand, type OnCommandDecorator, OnDeactivation, OnDeprovision, OnEvent, type OnEventDecorator, OnProvision, OnQuery, type OnQueryDecorator, type ProvisionId, QueriesPlugin, QueryBus, type QueryDispatchOptions, type QueryHandler, type QueryType, type QueryUnregister, type ServiceToken, type ValueBindingDescriptor, type WireEvent, WireStatus, WirestateError, type WirestateErrorContext, type WirestateErrorHandler, type WirestateErrorSource, type WirestatePlugin, defaultWirestateErrorHandler, getBindingScope, getBindingToken, getBindingType, inject, isInjectable, validateContainerConfig };