import thrift from 'thrift'; import { EventEmitter } from 'events'; import IDBSQLClient, { ClientOptions, ConnectionOptions, OpenSessionRequest } from './contracts/IDBSQLClient'; import IDriver from './contracts/IDriver'; import IClientContext, { ClientConfig } from './contracts/IClientContext'; import IThriftClient from './contracts/IThriftClient'; import IDBSQLSession from './contracts/IDBSQLSession'; import IAuthentication from './connection/contracts/IAuthentication'; import IDBSQLLogger from './contracts/IDBSQLLogger'; import IConnectionProvider from './connection/contracts/IConnectionProvider'; import TelemetryEventEmitter from './telemetry/TelemetryEventEmitter'; import MetricsAggregator from './telemetry/MetricsAggregator'; export type ThriftLibrary = Pick; export default class DBSQLClient extends EventEmitter implements IDBSQLClient, IClientContext { private static defaultLogger?; private readonly config; private connectionProvider?; private authProvider?; private client?; private readonly driver; private readonly logger; private thrift; private readonly sessions; private backend?; private host?; private httpPath?; private authType?; private useProxy?; private telemetryClient?; private telemetryEmitter?; private driverConfigShipped; private static getDefaultLogger; private static getDefaultConfig; constructor(options?: ClientOptions); private getConnectionOptions; private createAuthProvider; /** * Wraps a token provider with caching and optional federation. * Caching is always enabled by default. Federation is opt-in. */ private wrapTokenProvider; private createConnectionProvider; /** * Extract the numeric workspace ID for telemetry. * * Two URL shapes carry the workspace ID today: * - Warehouse, query form: `/sql/1.0/warehouses/?o=` * - All-purpose cluster, path form: `sql/protocolv1/o//` * * Host-based extraction was tried previously but produced confidently-wrong * values: * - AWS `dbc-XXXXX-YYYY.cloud.databricks.com` → `dbc-XXXXX-YYYY` * is the deployment shard prefix, not the workspace ID. * - Azure `adb-NNNNNNNNNNNNN.NN.azuredatabricks.net` → the workspace ID is * the numeric portion after the `adb-` prefix (and before the form-factor * digit), not `adb-NNN`. * * Returns `undefined` when no workspace ID can be derived. Server-side * attribution is better off seeing a missing field than a wrong value. */ private static extractWorkspaceId; private static hasMalformedOrgParam; /** * Build the customHeaders map applied to telemetry POSTs and feature-flag * GETs (SPOG / Single Panel of Glass support). When `httpPath` carries a * workspace ID — either as a `?o=` query (warehouse) or a * `/o//` path segment (all-purpose cluster) — endpoints * that don't include the workspace in their URL path need it conveyed via * the `x-databricks-org-id` header instead. A user-supplied value in * `userHeaders` (case-insensitively keyed) wins over the parsed value. * * `httpPath` is passed explicitly (rather than read off `this.httpPath`) so * the SPOG-routing dependency is visible in the signature — a future * refactor that reorders connect() can't silently break injection. */ private buildCustomHeaders; /** * Build driver configuration for telemetry reporting. * @returns DriverConfiguration object with current driver settings */ private buildDriverConfiguration; /** * Map Node.js auth type to telemetry auth enum string. * Distinguishes between U2M and M2M OAuth flows. */ private mapAuthType; /** * Get locale name in format language_country (e.g., en_US). * Matches JDBC format: user.language + '_' + user.country */ private getLocaleName; /** * Get process name, similar to JDBC's ProcessNameUtil. * Returns the script name or process title. */ private getProcessName; /** * Initialize telemetry components if enabled. * CRITICAL: All errors swallowed and logged at LogLevel.debug ONLY. * Driver NEVER throws exceptions due to telemetry. */ private initializeTelemetry; /** * Connects DBSQLClient to endpoint * @public * @param options - host, path, and token are required * @param authProvider - [DEPRECATED - use `authType: 'custom'] Optional custom authentication provider * @returns Session object that can be used to execute statements * @example * const session = client.connect({host, path, token}); */ connect(options: ConnectionOptions, authProvider?: IAuthentication): Promise; private forwardConnectionEvent; /** * Starts new session * @public * @param request - Can be instantiated with initialSchema, empty by default * @returns Session object that can be used to execute statements * @throws {StatusError} * @example * const session = await client.openSession(); */ openSession(request?: OpenSessionRequest): Promise; /** * Closes the client, releasing sessions and telemetry resources. * * The internal telemetry flush timer uses `setInterval(...).unref()` so it * cannot keep the Node.js process alive on its own. As a consequence, any * telemetry buffered between flush ticks is lost if the process exits * without calling `close()`. Long-lived applications should `await` this * method on shutdown so the aggregator drains its remaining metrics. */ close(): Promise; getConfig(): ClientConfig; getLogger(): IDBSQLLogger; getConnectionProvider(): Promise; getClient(): Promise; getDriver(): Promise; /** * Returns the authentication provider associated with this client, if any. * Intended for internal telemetry/feature-flag call sites that need to * obtain auth headers directly without routing through `IClientContext`. * * @internal Not part of the public API. May change without notice. */ getAuthProvider(): IAuthentication | undefined; /** @internal */ getTelemetryEmitter(): TelemetryEventEmitter | undefined; /** @internal */ getTelemetryAggregator(): MetricsAggregator | undefined; /** * Operator-visible snapshot of the client's telemetry state: current * buffer depth, in-flight statement aggregations, cumulative drops/ * evictions, and circuit-breaker state. Returns `undefined` when * telemetry is disabled (config, env-kill, or feature-flag). * * Use this in health-check endpoints or shutdown banners to verify that * telemetry is flowing. A non-zero `droppedMetrics` between observations * means buffer overflow — raise `telemetryMaxPendingMetrics`. */ getTelemetryStats(): { host: string; pendingMetricsCount: number; inFlightStatements: number; droppedMetrics: number; evictedStatements: number; circuitBreakerState: string; } | undefined; }