import { u as SymbolBatcherExecutor, f as RateLimitOptions, v as Session, e as SessionManager, w as CandlesUpdate, x as CandleTick, q as TvSymbolError, b as Timeframe, C as Candle } from './errors-B_SFtuRv.cjs';
export { y as BackoffOptions, B as BarTick, z as CloseInfo, D as DEFAULT_BACKOFF, A as DEFAULT_RATE_LIMIT, F as FullQuoteSnapshot, d as QuoteErrorInfo, Q as QuoteField, h as QuoteFieldTypeMap, g as QuoteSession, E as QuoteSessionOptions, c as QuoteSnapshot, a as QuoteUpdate, i as RawTimeframe, R as ReconnectOptions, G as SessionManagerOptions, H as SessionManagerState, S as SymbolInfo, j as TIMEFRAME_ALIASES, k as TimeframeAlias, T as TradeTick, I as Transport, J as TransportOptions, K as TransportState, l as TvConnectionError, m as TvError, n as TvErrorOptions, o as TvProtocolError, p as TvSessionError, r as TvTimeoutError, L as calculateBackoff, s as normalizeTimeframe, M as resolveRateLimit, t as symbolInfoFromRaw } from './errors-B_SFtuRv.cjs';
import debug from 'debug';

/**
 * Types for the TradingView wire protocol.
 *
 * TradingView frames incoming data as `~m~<length>~m~<payload>` where
 * `<length>` is the decimal character length of `<payload>`. A single
 * WebSocket message may contain one or more back-to-back frames.
 *
 * Payloads come in three flavours:
 *
 *   1. Heartbeat:  `~h~<number>` — server pings, client echoes back
 *   2. Hello:      a JSON object without an `m` field, sent once after
 *                  the connection is established (server/session info)
 *   3. Message:    a JSON object of the form `{ "m": <method>, "p": <params> }`
 */
type ProtocolMessage = HeartbeatMessage | HelloMessage | CommandMessage;
interface HeartbeatMessage {
    type: 'heartbeat';
    /** Sequence number sent by the server; must be echoed back unchanged. */
    id: number;
}
interface HelloMessage {
    type: 'hello';
    /** Arbitrary JSON payload from the initial server handshake. */
    data: unknown;
}
interface CommandMessage {
    type: 'message';
    /** The `m` field of the inbound JSON — e.g. `'qsd'`, `'quote_completed'`. */
    method: string;
    /** The `p` field of the inbound JSON. */
    params: unknown[];
}

/**
 * TradingView wire protocol — pure encode/decode functions.
 *
 * This module has no side effects and no I/O. It only translates between
 * raw strings received from the WebSocket and strongly typed messages.
 *
 * See `protocol.types.ts` for a description of the frame format.
 */

/**
 * Wrap a raw payload in the TradingView frame header.
 *
 * The payload length is measured in character-count (UTF-16 code units),
 * matching TradingView's own behaviour.
 */
declare function encodeFrame(payload: string | object): string;
/** Build a heartbeat echo frame for a given server-provided id. */
declare function encodeHeartbeat(id: number): string;
/** Build a command frame like `{ m: "quote_add_symbols", p: [...] }`. */
declare function encodeCommand(method: string, params: unknown[]): string;
/**
 * Decode a raw WebSocket message (which may contain multiple concatenated
 * frames) into an array of typed `ProtocolMessage`s.
 *
 * Throws `TvProtocolError` on malformed input.
 */
declare function decodeFrames(raw: string): ProtocolMessage[];

/**
 * SymbolBatcher — batching + chunking + dedup for quote add/remove ops.
 *
 * See `rate-limiter.types.ts` for a description of the semantics.
 */

declare class SymbolBatcher {
    private readonly executor;
    private readonly opts;
    private pendingAdd;
    private pendingRemove;
    private flushTimer;
    private inFlight;
    private disposed;
    constructor(executor: SymbolBatcherExecutor, opts?: RateLimitOptions);
    /**
     * Queue a symbol for addition. If the same symbol has a pending
     * removal in the current window, the two cancel out and nothing is
     * dispatched.
     */
    add(symbol: string): void;
    /**
     * Queue a symbol for removal. If the same symbol has a pending
     * addition in the current window, the two cancel out and nothing is
     * dispatched.
     */
    remove(symbol: string): void;
    /** Number of pending operations (both adds and removes). */
    get pendingCount(): number;
    /**
     * Force an immediate flush of any pending operations, bypassing the
     * batch window timer. Resolves once all resulting chunks have been
     * dispatched through the executor.
     */
    flushNow(): Promise<void>;
    /**
     * Destroy the batcher. Any pending operations are dropped — the
     * caller is responsible for calling `flushNow()` first if that's
     * undesired.
     */
    destroy(): void;
    private scheduleFlush;
    private flush;
    private dispatchChunks;
}

/**
 * ChartSession — manages a TradingView `chart_create_session` container.
 *
 * This session type is used for historical candle data and live bar
 * updates. A typical flow:
 *
 *   1. `chart_create_session` to open the container
 *   2. `resolve_symbol` to bind a symbol key (e.g. `sym_1`) to a market pair
 *   3. `create_series` to request N bars for that symbol at a timeframe
 *   4. Receive `timescale_update` (initial bars) and subsequent `du`
 *      (data update) messages as bars tick
 *   5. `chart_delete_session` on teardown
 *
 * This class wraps all of that into a simple callback-driven API. A
 * higher-level layer (Phase 4 `Symbol.candles()`) will consume it via
 * a promise-returning helper.
 */

interface SeriesRequest {
    /** Full TradingView pair, e.g. `'BINANCE:BTCUSDT'`. */
    symbol: string;
    /** Candle timeframe (TradingView native, e.g. `'60'` for 1h, `'1D'` for daily). */
    timeframe: Timeframe;
    /** Number of bars to request on initial load. */
    barCount: number;
}
interface ChartSessionOptions {
    manager: SessionManager;
    /** Called when a batch of bars arrives on a series (initial load). */
    onCandles?: (update: CandlesUpdate) => void;
    /** Called when a single bar ticks live after the initial load. */
    onTick?: (tick: CandleTick) => void;
    /** Called when TradingView rejects a symbol or a series. */
    onError?: (err: TvSymbolError) => void;
}
declare class ChartSession implements Session {
    readonly id: string;
    private readonly manager;
    private readonly series;
    private readonly seriesBySymbolKey;
    private nextSymbolSeq;
    private nextSeriesSeq;
    private created;
    private disposed;
    private readonly onCandlesCb?;
    private readonly onTickCb?;
    private readonly onErrorCb?;
    private readonly pendingResolves;
    private readonly pendingCandles;
    constructor(opts: ChartSessionOptions);
    /**
     * Request a series of bars for a symbol. The `onCandles` callback is
     * invoked once the initial batch arrives; subsequent bar updates come
     * through `onTick`.
     *
     * Returns the generated `seriesId`, which can be used with
     * `requestMore()` to fetch additional historical bars.
     */
    requestSeries(request: SeriesRequest): string;
    /** Request additional historical bars for an existing series. */
    requestMore(seriesId: string, additionalBars: number): void;
    /** Remove a series (stop receiving updates for it). */
    removeSeries(seriesId: string): void;
    /** All active series keyed by `seriesId`. */
    getSeries(): ReadonlyMap<string, {
        symbol: string;
        timeframe: string;
    }>;
    /**
     * Promise-based helper: resolve a symbol without creating a series.
     * Returns the raw `symbol_resolved` payload from TradingView.
     *
     * Useful for fetching symbol metadata (description, exchange, type,
     * session hours, etc.) without paying for a candle subscription.
     */
    resolvePair(pair: string, timeoutMs?: number): Promise<Record<string, unknown>>;
    /**
     * Promise-based helper: fetch a historical candle window in one call.
     * Creates a temporary series, waits for the initial backfill, then
     * removes the series and returns the candles.
     */
    fetchCandlesOnce(symbol: string, opts: {
        timeframe: Timeframe;
        barCount: number;
    }, timeoutMs?: number): Promise<Candle[]>;
    /** Close the chart session on the server and release local state. */
    delete(): Promise<void>;
    handleMessage(method: string, params: unknown[]): void;
    handleDisconnect(): void;
    replay(): void;
    private sendCreate;
    private handleSymbolResolved;
    private handleSymbolError;
    private handleSeriesError;
    /**
     * Handle `timescale_update` and `du` (data update). Both carry a
     * payload of the form:
     *
     *   { sds_1: { s: [ { i, v: [time, open, high, low, close, volume] }, ... ] } }
     *
     * `timescale_update` is typically the initial historical dump;
     * subsequent `du` updates usually contain only the last tick.
     */
    private handleSeriesData;
}

/**
 * Convert `kebab-case` and `snake_case` strings to `camelCase`.
 *
 * TradingView's wire format mixes both conventions: `series-key`,
 * `base_name`, `session-regular-display`, `is_tradable`, etc. Our
 * public API exposes everything as camelCase — this helper is the
 * single conversion point.
 *
 * Examples:
 *   kebabToCamel('series-key')             → 'seriesKey'
 *   kebabToCamel('base_name')              → 'baseName'
 *   kebabToCamel('session-regular-display') → 'sessionRegularDisplay'
 *   kebabToCamel('is_tradable')            → 'isTradable'
 *   kebabToCamel('has-no-bbo')             → 'hasNoBbo'
 *
 * Edge behaviour:
 *   - Already-camelCase strings pass through unchanged.
 *   - Numeric segments are kept: `rt-lag` → `rtLag`, `price_52_week_high` → `price52WeekHigh`.
 *   - Leading separators are preserved (`-foo` → `-foo`, unlikely to appear in TV payloads).
 *   - Consecutive separators collapse: `a--b` → `aB`.
 */
declare function kebabToCamel(key: string): string;
/**
 * Shallow-transform the top-level keys of an object from kebab/snake to
 * camelCase. Values are passed through unchanged — nested objects keep
 * their original key casing, because TradingView nests things like
 * `local_popularity: { US: 123, DE: 45 }` where the inner keys are
 * country codes and must NOT be lowercased.
 *
 * If you need recursive transformation, do it explicitly at each level
 * where it makes sense.
 */
declare function transformKeys<T = Record<string, unknown>>(obj: Record<string, unknown>): T;

/**
 * Random alphanumeric id generator.
 *
 * Used for session identifiers (quote session, chart session) sent to
 * TradingView. Not cryptographically secure — just collision-resistant
 * enough for in-flight session multiplexing.
 */
declare function randomId(length?: number, random?: () => number): string;

/**
 * Debug logging wrapper.
 *
 * Usage:
 *   const log = createLogger('transport')
 *   log('connect() → %s', url)
 *
 * Enable at runtime via the `DEBUG` environment variable:
 *   DEBUG=tradingview-adapter:*              (all namespaces)
 *   DEBUG=tradingview-adapter:transport      (one namespace)
 *   DEBUG=tradingview-adapter:transport,tradingview-adapter:protocol
 */

type Logger = debug.Debugger;
declare function createLogger(namespace: string): Logger;

/**
 * Stable TradingView protocol constants.
 *
 * These values come from reverse-engineering the public TradingView
 * widget WebSocket — they may change without notice if TradingView
 * updates its infrastructure.
 */
/** WebSocket endpoint for quote/chart sessions. */
declare const TV_WS_URL = "wss://widgetdata.tradingview.com/socket.io/websocket";
/** Origin header required by TradingView when connecting from Node. */
declare const TV_ORIGIN = "https://s.tradingview.com";

export { Candle, CandleTick, CandlesUpdate, ChartSession, type ChartSessionOptions, type CommandMessage, type HeartbeatMessage, type HelloMessage, type Logger, type ProtocolMessage, RateLimitOptions, type SeriesRequest, Session, SessionManager, SymbolBatcher, SymbolBatcherExecutor, TV_ORIGIN, TV_WS_URL, Timeframe, TvSymbolError, createLogger, decodeFrames, encodeCommand, encodeFrame, encodeHeartbeat, kebabToCamel, randomId, transformKeys };
