import type { ServiceInfo } from '@nats-io/services'; import type { RPCClient } from './client.js'; import type { Promisify, ProxyCallOptions, ProxyTimingReporter } from './types.js'; /** * Mark a plain object of functions as a callback bundle that can be passed * as an argument to pull-callback RPC methods. The proxy detects the marker * and routes the call through callPullIteratorWithCallback(). * * @example * const cbs = rpcCallbacks({ * onItem: (data) => queue.push(data), * onEndOfBatch: () => batchEnd.resolve(), * }, { oneway: ['onItem', 'onEndOfBatch'] }); * * for await (const _ of service.pullBatches(count, cbs)) { * // batch boundary — apply backpressure here * } */ export declare function rpcCallbacks any>>(obj: T, options?: { oneway?: (keyof T)[]; }): T; /** Test whether a value was produced by rpcCallbacks(). */ export declare function isRpcCallbacks(v: any): v is Record any>; /** Read the oneway-method list from a callback bundle. */ export declare function getCallbacksOneway(v: any): string[]; /** What a proxy and its nested proxies have learned about the methods of their namespace. */ export interface ProxyMethodCache { /** Method names from the responder, null until a response brought them */ methods: Set | null; /** First path segments of `methods`, built on first use */ roots: Set | null; /** Calls made while `methods` is null: discovery starts with the second */ calls: number; } /** * Promise check. Used internally to detect async handlers * that need to be awaited so dispatch stays ordered. */ export declare function isPromise(value: unknown): value is Promise; /** * Create a proxy for RPC calls with support for nested objects * Works for both flat and deep object structures * * @param client - RPC client with call and callStream methods * @param namespace - RPC namespace * @param path - Current path in proxy hierarchy (internal use) * @param cache - Method cache shared with the nested proxies * @param onTiming - Receives the cost of every call * @param callOptions - Retry and timeout for every plain call, inherited by nested proxies * @returns Proxy that intercepts property access and method calls * * @example * // Flat usage * const service = client.createProxy('myservice'); * await service.someMethod(); * * // Nested usage * const app = client.createProxy('app'); * await app.db.find('key'); * * // Streaming * for await (const item of service.dataStream()) { * console.log(item); * } * * // Optional chaining for unknown methods * const result = await service.maybeMethod?.(); // undefined if method doesn't exist */ export declare function createProxy(client: RPCClient, namespace: string, path?: string[], cache?: ProxyMethodCache, onTiming?: ProxyTimingReporter, callOptions?: ProxyCallOptions): Promisify; /** * Create a service proxy with proper streaming support * Handles NATS service endpoints with automatic discovery * * @param client - RPC client instance * @param selected - Selected service info from discovery * @param timeout - Optional timeout for requests * @param path - Current path in proxy hierarchy (internal use) * @returns Proxy that intercepts property access and method calls * * @example * const service = await client.createServiceProxy('myservice'); * await service.someMethod(); * * // Nested endpoints * await service.config.get(); * * // Streaming * for await (const item of service.generateData()) { * console.log(item); * } */ export declare function createServiceProxy(client: RPCClient, selected: ServiceInfo, timeout?: number, path?: string[]): Promisify; export declare function generateId(replyPrefix?: string): string; /** * Generate a client-local reply prefix: ~10 base36 chars (48 random bits), * crypto-backed where available. Used as the first dot-separated segment of * every call id when no connId is configured, so all reply subjects of a * client share one wildcard-subscribable prefix (`rpc.reply..>`). */ export declare function generateReplyPrefix(): string; /** Resolves after `ms`, or as soon as `signal` aborts. */ export declare function sleep(ms: number, signal?: AbortSignal): Promise; /** * Per-subscription serial dispatcher with a sync fast path. * * Guarantees: handlers run strictly serially in dispatch order — also for * mixed sync/async handlers. This matches the previous "chain every call" * behavior (and Python's awaited dispatch) that backpressure-sensitive * callers rely on: an awaiting handler blocks the next message. * * Optimization: when the chain is idle (no async handler still pending), * the handler is invoked inline. Only if it returns a promise does the * chain become busy; purely synchronous traffic never allocates promises. * While the chain is busy, every subsequent dispatch is appended to the * chain so ordering is preserved. * * flush() resolves once every message dispatched so far has had its * handler executed (resolved immediately when the chain is idle). */ export declare function createSerialDispatcher(handler: (data: any) => void | Promise, onError: (error: unknown) => void): { dispatch: (data: any) => void; flush: () => Promise; }; /** * Per-subscription dispatcher with up to `limit` handlers in flight. * * Messages start in arrival order. A message for which `isShared` returns * false waits until nothing else runs and blocks later messages until it is * done, so it keeps the serial semantics of createSerialDispatcher. * * flush() resolves once the dispatcher is idle: nothing running, nothing queued. */ export declare function createBoundedDispatcher(handler: (data: any) => void | Promise, limit: number, isShared: (data: any) => boolean, onError: (error: unknown) => void): { dispatch: (data: any) => void; flush: () => Promise; };