@wavehouse/sdk 0.0.0-dev.0f8826c → 0.0.0-dev.h825a5d7fa405

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -124,13 +124,12 @@ npm run test:coverage # coverage report
124
124
 
125
125
  ### E2E Integration Tests
126
126
 
127
- E2E tests live in `tests/sdk/` (repo root) and exercise the full pipeline through the SDK. See `make test-e2e` in the [Development Guide](../../docs/development.md#e2e-tests-via-sdk).
127
+ E2E tests live in `tests/e2e/sdk/` (repo root) and exercise the full pipeline through the SDK. See `make test-e2e` in the [Development Guide](https://wavehouse.dev/development#e2e-tests-via-sdk).
128
128
 
129
129
  ## API Reference
130
130
 
131
- See the full [SDK API Reference](../../docs/sdk.md) for detailed documentation of every method, type, and option.
131
+ See the full [SDK API Reference](https://wavehouse.dev/sdk) for detailed documentation of every method, type, and option.
132
132
 
133
133
  ## License
134
134
 
135
135
  Apache-2.0 © Wave RF — see [LICENSE](./LICENSE).
136
-
package/dist/index.cjs CHANGED
@@ -782,11 +782,11 @@ var QueryBuilder = class _QueryBuilder {
782
782
  if (error) return err(error);
783
783
  const rows = data;
784
784
  const hasMore = effectiveLimit != null && rows.length >= effectiveLimit;
785
- if (hasMore) {
785
+ if (hasMore && this._state.orderBy.length > 0) {
786
786
  const nextFn = () => this._fetchNext(rows, effectiveLimit, opts);
787
787
  return okPage(rows, true, nextFn);
788
788
  }
789
- return okPage(rows, false);
789
+ return okPage(rows, hasMore);
790
790
  }
791
791
  stream(opts) {
792
792
  const raw = this._createStream(this._state.table, opts);
@@ -829,27 +829,23 @@ var QueryBuilder = class _QueryBuilder {
829
829
  if (this._state.aggregations.length > 0) ast.aggregations = this._state.aggregations;
830
830
  if (this._state.filters.length > 0) ast.filters = this._state.filters;
831
831
  if (this._state.groupBy.length > 0) ast.group_by = this._state.groupBy;
832
- if (this._state.orderBy.length > 0) {
833
- ast.order_by = this._state.orderBy;
834
- } else if (effectiveLimit != null && this._state.aggregations.length === 0) {
835
- ast.order_by = [{ column: "received_timestamp", dir: "desc" }];
836
- }
832
+ if (this._state.orderBy.length > 0) ast.order_by = this._state.orderBy;
837
833
  if (effectiveLimit != null) ast.limit = effectiveLimit;
838
834
  if (this._state.timeRange) ast.time_range = this._state.timeRange;
839
835
  return ast;
840
836
  }
841
837
  async _fetchNext(prevRows, _limit, opts) {
842
- const orderCol = this._state.orderBy[0]?.column ?? "received_timestamp";
843
- const orderDir = this._state.orderBy[0]?.dir ?? "desc";
838
+ const cursor = this._state.orderBy[0];
839
+ if (cursor == null) return okPage([], false);
840
+ const { column: orderCol, dir: orderDir } = cursor;
844
841
  const lastRow = prevRows[prevRows.length - 1];
845
842
  const lastValue = lastRow?.[orderCol];
846
843
  if (lastValue === void 0) return okPage([], false);
847
844
  const cursorOp = orderDir === "desc" ? "lt" : "gt";
848
845
  const cursorFilter = { column: orderCol, op: cursorOp, value: lastValue };
849
- const orderBy = this._state.orderBy.length > 0 ? this._state.orderBy : [{ column: orderCol, dir: orderDir }];
850
846
  const nextBuilder = this._clone({
851
847
  filters: [...this._state.filters, cursorFilter],
852
- orderBy
848
+ orderBy: this._state.orderBy
853
849
  });
854
850
  return nextBuilder.fetch(opts);
855
851
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/dlq.ts","../src/pipes.ts","../src/policy.ts","../src/schema.ts","../src/sql.ts","../src/stream/controller.ts","../src/stream/sse.ts","../src/sys.ts","../src/stream/live-query.ts","../src/query-builder.ts","../src/table.ts","../src/client.ts"],"sourcesContent":["// ============================================================================\n// @wavehouse/sdk — Public API\n// ============================================================================\n\n// --- Main entry point ---\nexport { createClient, WaveHouseClient } from \"./client.js\";\nexport { DLQNamespace } from \"./dlq.js\";\nexport { PipeRef, PipesNamespace } from \"./pipes.js\";\nexport { PolicyNamespace } from \"./policy.js\";\nexport { QueryBuilder } from \"./query-builder.js\";\nexport { SchemaNamespace } from \"./schema.js\";\nexport { StreamController } from \"./stream/controller.js\";\nexport { LiveQuery } from \"./stream/live-query.js\";\nexport { SysNamespace } from \"./sys.js\";\n// --- Core classes ---\nexport { TableRef } from \"./table.js\";\n\n// --- Types ---\nexport type {\n Aggregation,\n // Config\n ClientConfig,\n ClientOptions,\n // Schema\n Column,\n // Database & result\n Database,\n // DLQ\n DLQStats,\n FetchOptions,\n // Query\n FilterOp,\n // Ingest\n InsertResult,\n OrderClause,\n ParamDef,\n // Pipes\n Pipe,\n // Policy\n Policy,\n PolicyFilter,\n QueryFilter,\n Result,\n RolePermissions,\n Schemas,\n StreamEvent,\n StreamOptions,\n // Streaming\n StreamStatus,\n StreamSubscriber,\n StructuredQuery,\n TablePolicy,\n TableSchema,\n TimeRange,\n ValidationResult,\n WaveHouseError,\n} from \"./types.js\";\n","import type { Result, WaveHouseError } from \"./types.js\";\n\n/** Create a WaveHouseError from an HTTP response. */\nexport async function parseErrorResponse(res: Response): Promise<WaveHouseError> {\n let body: Record<string, unknown> | undefined;\n try {\n body = (await res.json()) as Record<string, unknown>;\n } catch {\n body = undefined;\n }\n\n const message =\n typeof body?.error === \"string\"\n ? body.error\n : typeof body?.message === \"string\"\n ? body.message\n : res.statusText;\n\n const retryable = res.status === 503 || res.status >= 500;\n return {\n status: res.status,\n code: `HTTP_${res.status}`,\n message,\n details: body,\n retryable,\n };\n}\n\n/** Create a WaveHouseError from a network/fetch error. */\nexport function networkError(cause: unknown): WaveHouseError {\n const message = cause instanceof Error ? cause.message : String(cause);\n return {\n status: 0,\n code: \"NETWORK_ERROR\",\n message,\n retryable: true,\n };\n}\n\n/** Wrap a successful value in a Result. */\nexport function ok<T>(data: T): Result<T> {\n return { ok: true, data, error: null };\n}\n\n/** Wrap a successful paginated value in a Result. */\nexport function okPage<T>(data: T, hasMore: boolean, next?: () => Promise<Result<T>>): Result<T> {\n return { ok: true, data, error: null, hasMore, next };\n}\n\n/** Wrap an error in a Result. */\nexport function err<T = unknown>(error: WaveHouseError): Result<T> {\n return { ok: false, data: null, error };\n}\n","import { networkError, parseErrorResponse } from \"./errors.js\";\nimport type { HttpContext, WaveHouseError } from \"./types.js\";\n\ninterface RequestOptions {\n method: string;\n path: string;\n body?: unknown;\n params?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/** @internal */\nexport interface HttpResult<T> {\n data: T | null;\n error: WaveHouseError | null;\n headers: Headers;\n}\n\n/**\n * Internal fetch wrapper with auth injection, retry, backoff, and Retry-After.\n * @internal\n */\nexport async function request<T>(ctx: HttpContext, opts: RequestOptions): Promise<HttpResult<T>> {\n const url = buildURL(ctx.baseURL, opts.path, opts.params);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n };\n\n if (ctx.auth) {\n const token = await ctx.auth();\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n }\n\n let lastError: WaveHouseError | null = null;\n const maxAttempts = ctx.options.maxRetries + 1;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n const res = await fetch(url, {\n method: opts.method,\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n signal: opts.signal,\n });\n\n if (res.ok) {\n const text = await res.text();\n const data = text ? (JSON.parse(text) as T) : (undefined as T);\n return { data, error: null, headers: res.headers };\n }\n\n const error = await parseErrorResponse(res);\n\n // 503 with Retry-After: wait the specified duration\n if (res.status === 503) {\n const retryAfter = res.headers.get(\"Retry-After\");\n if (retryAfter && attempt < maxAttempts - 1) {\n const delay = parseInt(retryAfter, 10) * 1000 || 30_000;\n await sleep(delay, opts.signal);\n lastError = error;\n continue;\n }\n }\n\n // Retryable server errors (5xx)\n if (error.retryable && attempt < maxAttempts - 1) {\n await sleep(backoff(attempt), opts.signal);\n lastError = error;\n continue;\n }\n\n return { data: null, error, headers: res.headers };\n } catch (e) {\n // AbortError — return immediately, no retry\n if (e instanceof DOMException && e.name === \"AbortError\") {\n return {\n data: null,\n error: { status: 0, code: \"ABORTED\", message: \"Request aborted\", retryable: false },\n headers: new Headers(),\n };\n }\n\n lastError = networkError(e);\n if (attempt < maxAttempts - 1) {\n await sleep(backoff(attempt), opts.signal);\n }\n }\n }\n\n return { data: null, error: lastError!, headers: new Headers() };\n}\n\nfunction buildURL(base: string, path: string, params?: Record<string, string>): string {\n const url = new URL(path, base.endsWith(\"/\") ? base : `${base}/`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n url.searchParams.set(k, v);\n }\n }\n return url.toString();\n}\n\nfunction backoff(attempt: number): number {\n return Math.min(1000 * 2 ** attempt, 30_000);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n return;\n }\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timer);\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n },\n { once: true },\n );\n });\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { StreamController } from \"./stream/controller.js\";\nimport type { DLQStats, HttpContext, Result, StreamOptions } from \"./types.js\";\n\ntype CreateStreamFn = (table: string, opts?: StreamOptions) => StreamController;\n\n/** Namespace for Dead Letter Queue operations. */\nexport class DLQNamespace {\n private readonly _ctx: HttpContext;\n private readonly _createStream: CreateStreamFn;\n\n constructor(ctx: HttpContext, createStream: CreateStreamFn) {\n this._ctx = ctx;\n this._createStream = createStream;\n }\n\n /** Get DLQ statistics (message counts per table). */\n async list(opts?: { signal?: AbortSignal }): Promise<Result<DLQStats>> {\n const { data, error } = await request<DLQStats>(this._ctx, {\n method: \"GET\",\n path: \"/v1/dlq/stats\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Get DLQ stats filtered by table name. */\n async table(name: string, opts?: { signal?: AbortSignal }): Promise<Result<DLQStats>> {\n const { data, error } = await request<DLQStats>(this._ctx, {\n method: \"GET\",\n path: \"/v1/dlq/stats\",\n params: { table: name },\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Subscribe to live DLQ events. */\n stream(opts?: StreamOptions): StreamController {\n return this._createStream(\"dlq\", opts);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { StreamController } from \"./stream/controller.js\";\nimport type { FetchOptions, HttpContext, Pipe, Result, StreamOptions } from \"./types.js\";\n\ntype CreateStreamFn<Row> = (table: string, opts?: StreamOptions) => StreamController<Row>;\n\n/** Reference to a named query pipe — PromiseLike for convenient `await`. */\nexport class PipeRef<Row = Record<string, unknown>> implements PromiseLike<Result<Row[]>> {\n private readonly _ctx: HttpContext;\n private readonly _name: string;\n private readonly _params?: Record<string, unknown>;\n private readonly _createStream: CreateStreamFn<Row>;\n\n constructor(\n ctx: HttpContext,\n name: string,\n params: Record<string, unknown> | undefined,\n createStream: CreateStreamFn<Row>,\n ) {\n this._ctx = ctx;\n this._name = name;\n this._params = params;\n this._createStream = createStream;\n }\n\n /** Execute the pipe and return results. */\n async fetch(opts?: FetchOptions): Promise<Result<Row[]>> {\n const { data, error } = await request<Row[]>(this._ctx, {\n method: \"POST\",\n path: `/v1/pipes/${encodeURIComponent(this._name)}`,\n body: this._params ?? {},\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Subscribe to live events from the pipe's underlying query. */\n stream(opts?: StreamOptions): StreamController<Row> {\n return this._createStream(this._name, opts);\n }\n\n then<TResult1 = Result<Row[]>, TResult2 = never>(\n onfulfilled?: ((value: Result<Row[]>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.fetch().then(onfulfilled, onrejected);\n }\n}\n\n/** Admin namespace for managing named query pipes. */\nexport class PipesNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /** List all registered pipes. */\n async list(opts?: { signal?: AbortSignal }): Promise<Result<Pipe[]>> {\n const { data, error } = await request<Pipe[]>(this._ctx, {\n method: \"GET\",\n path: \"/v1/admin/pipes\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Get a single pipe definition by name. */\n async get(name: string, opts?: { signal?: AbortSignal }): Promise<Result<Pipe>> {\n const { data, error } = await request<Pipe>(this._ctx, {\n method: \"GET\",\n path: `/v1/admin/pipes/${encodeURIComponent(name)}`,\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Create or update a pipe. */\n async set(\n name: string,\n def: Omit<Pipe, \"name\">,\n opts?: { signal?: AbortSignal },\n ): Promise<Result<void>> {\n const { error } = await request<{ ok: boolean }>(this._ctx, {\n method: \"PUT\",\n path: `/v1/admin/pipes/${encodeURIComponent(name)}`,\n body: def,\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n\n /** Delete a pipe by name. */\n async delete(name: string, opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<{ ok: boolean }>(this._ctx, {\n method: \"DELETE\",\n path: `/v1/admin/pipes/${encodeURIComponent(name)}`,\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Policy, Result, ValidationResult } from \"./types.js\";\n\n/** Namespace for access control policy management. Requires the admin role (the configured `admin_role`, `\"admin\"` by default). */\nexport class PolicyNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /** Get the current access control policy. */\n async get(opts?: { signal?: AbortSignal }): Promise<Result<Policy>> {\n const { data, error } = await request<Policy>(this._ctx, {\n method: \"GET\",\n path: \"/v1/admin/policy\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Replace the entire access control policy. */\n async set(policy: Policy, opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<{ ok: boolean }>(this._ctx, {\n method: \"PUT\",\n path: \"/v1/admin/policy\",\n body: policy,\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n\n /** Validate a policy without applying it (dry run). */\n async validate(\n policy: Policy,\n opts?: { signal?: AbortSignal },\n ): Promise<Result<ValidationResult>> {\n const { data, error } = await request<ValidationResult>(this._ctx, {\n method: \"POST\",\n path: \"/v1/admin/policy/validate\",\n body: policy,\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Result, Schemas } from \"./types.js\";\n\n/** Namespace for schema introspection. */\nexport class SchemaNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /** List all table schemas discovered from ClickHouse. */\n async list(opts?: { signal?: AbortSignal }): Promise<Result<Schemas>> {\n // The backend returns TableSchema[] — transform to Record<string, TableSchema>.\n const { data, error } = await request<unknown>(this._ctx, {\n method: \"GET\",\n path: \"/v1/schema\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n\n let schemas: Schemas;\n if (Array.isArray(data)) {\n schemas = {};\n for (const table of data) {\n if (table && typeof table === \"object\" && \"name\" in table) {\n schemas[(table as { name: string }).name] = table as Schemas[string];\n }\n }\n } else {\n schemas = data as Schemas;\n }\n return ok(schemas);\n }\n\n /** Force a schema refresh from ClickHouse system.columns. */\n async refresh(opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<Schemas>(this._ctx, {\n method: \"POST\",\n path: \"/v1/schema/refresh\",\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Result } from \"./types.js\";\n\n/**\n * Execute a raw SQL query against ClickHouse.\n *\n * Backed by `POST /v1/admin/query`, which requires the admin role — the same\n * gate as the rest of `/v1/admin/*`. Callers must hold a JWT whose role is the\n * configured `admin_role` (`\"admin\"` by default); there is no separate\n * `service` role. The JWT middleware always runs, so a request with no token\n * or an invalid one is denied, never granted. Non-admin use cases should use\n * the structured query builder (`wh.from(table)...`) instead.\n *\n * The server proxies the SQL string verbatim to ClickHouse's HTTP interface,\n * so any ClickHouse-accepted statement works — including multi-statement\n * input (`SELECT 1; TRUNCATE t`) and arbitrary DDL/DML/SYSTEM verbs.\n *\n * **JSON-row contract.** This helper returns `Result<Row[]>` and assumes the\n * response is the standard `FORMAT JSON` envelope (or an empty body for\n * no-result mutations — coerced to `[]`). Inline non-JSON `FORMAT` overrides\n * (`SELECT 1 FORMAT CSV` / `FORMAT TSV` / `FORMAT Pretty` / etc.) are NOT\n * compatible with `sql()` — the proxy passes the upstream Content-Type\n * through, and the SDK's JSON decoder throws on a non-JSON body, which the\n * retry layer surfaces as a `NETWORK_ERROR` result (not a structured\n * format-mismatch error). For CSV/TSV exports, hit `/v1/admin/query`\n * directly with `fetch()` and read the body as text.\n *\n * **No parameter binding.** Positional `?` substitution is not supported.\n * The SDK has no way to forward ClickHouse-style named params\n * (`WHERE id = {id:UInt32}` with `param_id=42` on the query string) —\n * the proxy doesn't forward arbitrary query-string params to ClickHouse\n * and the SDK doesn't expose a hook to add them. Inline literals into\n * the SQL string, or — for safe binding from user-supplied input — use\n * the structured query builder (`wh.from(...).select(...).where(...)`).\n */\nexport async function sql<Row = Record<string, unknown>>(\n ctx: HttpContext,\n query: string,\n opts?: { signal?: AbortSignal },\n): Promise<Result<Row[]>> {\n const { data, error } = await request<Row[]>(ctx, {\n method: \"POST\",\n path: \"/v1/admin/query\",\n body: { sql: query },\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n}\n","import type { StreamEvent, StreamStatus, StreamSubscriber, WaveHouseError } from \"../types.js\";\n\n/** @internal Transport abstraction for SSE backend. */\nexport interface StreamTransport<T = Record<string, unknown>> {\n connect(): void;\n disconnect(): void;\n onEvent: ((event: StreamEvent<T>) => void) | null;\n onStatus: ((status: StreamStatus) => void) | null;\n onError: ((error: WaveHouseError) => void) | null;\n}\n\n/**\n * Controls a live event stream. NOT thenable.\n * Use `.subscribe()` for callback-based consumption or `for await` for async iteration.\n */\nexport class StreamController<T = Record<string, unknown>> {\n private _transport: StreamTransport<T>;\n private _subscribers = new Set<StreamSubscriber<T>>();\n private _status: StreamStatus = \"connecting\";\n private _buffer: StreamEvent<T>[] = [];\n private _waiters: { resolve: (value: IteratorResult<StreamEvent<T>>) => void }[] = [];\n private _done = false;\n\n constructor(transport: StreamTransport<T>) {\n this._transport = transport;\n\n this._transport.onEvent = (event) => {\n for (const sub of this._subscribers) {\n sub.next(event);\n }\n // Async iterator support\n const waiter = this._waiters.shift();\n if (waiter) {\n waiter.resolve({ value: event, done: false });\n } else {\n this._buffer.push(event);\n }\n };\n\n this._transport.onStatus = (status) => {\n // Deduplicate: skip if status hasn't changed (e.g. transport fires\n // 'connecting' after StreamController already set it as the initial state).\n if (status === this._status) return;\n this._status = status;\n for (const sub of this._subscribers) {\n sub.status?.(status);\n }\n if (status === \"closed\") {\n this._done = true;\n for (const w of this._waiters) {\n w.resolve({ value: undefined as never, done: true });\n }\n this._waiters = [];\n }\n };\n\n this._transport.onError = (error) => {\n for (const sub of this._subscribers) {\n sub.error?.(error);\n }\n };\n\n this._transport.connect();\n }\n\n /** Current connection status. */\n get status(): StreamStatus {\n return this._status;\n }\n\n /**\n * Returns a promise that resolves when the stream status reaches `'live'`,\n * rejects immediately if the stream is already `'closed'`, or rejects after\n * `timeoutMs` milliseconds (default: 5 000) if it never connects.\n *\n * Safe to call before `.subscribe()` — does not trigger auto-close when\n * the internal waiter is removed.\n *\n * `@example`\n * const stream = client.from('events').stream();\n * const unsub = stream.subscribe({ next: (e) => console.log(e) });\n * await stream.connected(); // waits until the transport is live\n * await client.from('events').insert({ ... });\n */\n connected(timeoutMs = 5_000): Promise<void> {\n if (this._status === \"live\") return Promise.resolve();\n if (this._status === \"closed\") return Promise.reject(new Error(\"Stream is closed\"));\n if (this._done) return Promise.reject(new Error(\"Stream closed before connecting\"));\n\n return new Promise((resolve, reject) => {\n let settled = false;\n\n const timer = setTimeout(() => {\n if (settled) return;\n settled = true;\n this._subscribers.delete(watcher);\n reject(new Error(`Stream did not connect within ${timeoutMs}ms`));\n }, timeoutMs);\n\n // Use a private subscriber directly to avoid the auto-close side-effect\n // that the public subscribe() triggers when subscriber count drops to zero.\n const watcher: StreamSubscriber<T> = {\n next: () => {\n // no-op: we only care about status transitions here\n },\n status: (s) => {\n if (s === \"live\") {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n this._subscribers.delete(watcher);\n resolve();\n } else if (s === \"closed\") {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n this._subscribers.delete(watcher);\n reject(new Error(\"Stream closed before connecting\"));\n }\n },\n };\n\n this._subscribers.add(watcher);\n });\n }\n\n /** Subscribe to stream events via callbacks. Returns an unsubscribe function. */\n subscribe(subscriber: StreamSubscriber<T>): () => void {\n this._subscribers.add(subscriber);\n subscriber.status?.(this._status);\n\n return () => {\n this._subscribers.delete(subscriber);\n if (this._subscribers.size === 0 && this._waiters.length === 0) {\n this.close();\n }\n };\n }\n\n /** Attach an AbortSignal — when aborted, the stream is closed. */\n attachSignal(signal: AbortSignal): void {\n if (signal.aborted) {\n this.close();\n return;\n }\n signal.addEventListener(\"abort\", () => this.close(), { once: true });\n }\n\n /** Close the stream and release resources. */\n close(): void {\n this._transport.disconnect();\n if (this._status !== \"closed\") {\n this._status = \"closed\";\n for (const sub of this._subscribers) {\n sub.status?.(\"closed\");\n }\n }\n this._done = true;\n for (const w of this._waiters) {\n w.resolve({ value: undefined as never, done: true });\n }\n this._waiters = [];\n }\n\n /** Async iterator protocol — enables `for await (const event of stream)`. */\n [Symbol.asyncIterator](): AsyncIterableIterator<StreamEvent<T>> {\n const self = this;\n return {\n next(): Promise<IteratorResult<StreamEvent<T>>> {\n if (self._buffer.length > 0) {\n return Promise.resolve({ value: self._buffer.shift()!, done: false });\n }\n if (self._done) {\n return Promise.resolve({ value: undefined as never, done: true });\n }\n return new Promise((resolve) => {\n self._waiters.push({ resolve });\n });\n },\n return(): Promise<IteratorResult<StreamEvent<T>>> {\n self.close();\n return Promise.resolve({ value: undefined as never, done: true });\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n }\n}\n","import type { StreamEvent, StreamStatus, WaveHouseError } from \"../types.js\";\nimport type { StreamTransport } from \"./controller.js\";\n\nexport interface SSEOptions {\n baseURL: string;\n table: string;\n since?: string;\n auth?: () => Promise<string> | string;\n}\n\n/** Module-level active SSE connection counter. */\nlet activeSSEConnections = 0;\nconst SSE_WARN_THRESHOLD = 5;\n\n/** SSE transport. Native EventSource auto-reconnects. */\nexport class SSETransport<T = Record<string, unknown>> implements StreamTransport<T> {\n private _opts: SSEOptions;\n private _es: EventSource | null = null;\n\n onEvent: ((event: StreamEvent<T>) => void) | null = null;\n onStatus: ((status: StreamStatus) => void) | null = null;\n onError: ((error: WaveHouseError) => void) | null = null;\n\n constructor(opts: SSEOptions) {\n this._opts = opts;\n }\n\n connect(): void {\n if (typeof EventSource === \"undefined\") {\n throw new Error(\n \"[wavehouse] EventSource is not available in this environment. \" +\n \"Please provide a global polyfill (e.g., `globalThis.EventSource = require('eventsource')`).\",\n );\n }\n\n this._doConnect().catch((err) => {\n this.onError?.({\n status: 0,\n code: \"SSE_CONNECT_ERROR\",\n message: err instanceof Error ? err.message : String(err),\n retryable: true,\n });\n });\n }\n\n disconnect(): void {\n if (this._es) {\n this._es.close();\n this._es = null;\n activeSSEConnections = Math.max(0, activeSSEConnections - 1);\n }\n this.onStatus?.(\"closed\");\n }\n\n private async _doConnect(): Promise<void> {\n const url = new URL(\"/v1/stream\", this._opts.baseURL);\n url.searchParams.set(\"table\", this._opts.table);\n if (this._opts.since) {\n url.searchParams.set(\"since\", this._opts.since);\n }\n\n // EventSource can't set request headers, so the JWT goes in ?token=\n // (the server also accepts an Authorization header for non-browser clients)\n if (this._opts.auth) {\n const token = await this._opts.auth();\n if (token) {\n url.searchParams.set(\"token\", token);\n }\n }\n\n activeSSEConnections++;\n if (activeSSEConnections > SSE_WARN_THRESHOLD) {\n console.warn(\n `[wavehouse] ${activeSSEConnections} SSE connections open. ` +\n `Browsers limit HTTP/1.1 to 6 connections per domain.`,\n );\n }\n\n this._es = new EventSource(url.toString());\n\n this._es.onopen = () => {\n this.onStatus?.(\"live\");\n };\n\n this._es.onmessage = (e) => {\n try {\n const msg = JSON.parse(e.data as string) as {\n table_name: string;\n received_timestamp: string;\n data: T;\n };\n const event: StreamEvent<T> = {\n table: msg.table_name,\n timestamp: msg.received_timestamp,\n data: msg.data,\n };\n this.onEvent?.(event);\n } catch {\n console.warn(\"[wavehouse] SSE received malformed message:\", e.data);\n // ignore malformed messages\n }\n };\n\n this._es.onerror = () => {\n if (this._es?.readyState === EventSource.CONNECTING) {\n this.onStatus?.(\"reconnecting\");\n } else if (this._es?.readyState === EventSource.CLOSED) {\n this.onStatus?.(\"closed\");\n } else if (this._es?.readyState === EventSource.OPEN) {\n this.onStatus?.(\"live\");\n } else {\n this.onError?.({\n status: 0,\n code: \"SSE_ERROR\",\n message: \"SSE connection error\",\n retryable: true,\n });\n }\n };\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Result } from \"./types.js\";\n\n/** Namespace for the SDK's content-free server-online check. */\nexport class SysNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /**\n * Liveness ping — resolves with no error when the server is reachable and\n * past boot. Hits the public, content-free `/v1/health` route (200/503, no\n * body), kept intentionally distinct from the `/livez` Kubernetes probe so\n * it stays reachable even in deployments that filter probe paths at the\n * reverse proxy. Use it to check a server is online before sending data, or\n * to pick among servers in a distributed setup.\n */\n async health(opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<void>(this._ctx, {\n method: \"GET\",\n path: \"/v1/health\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok<void>(undefined);\n }\n}\n","import type { QueryFilter, Result, StreamEvent, StreamSubscriber } from \"../types.js\";\nimport type { StreamController } from \"./controller.js\";\n\n/**\n * Stream-first live query orchestrator.\n *\n * 1. Opens a live stream immediately (buffers events).\n * 2. Fetches historical data.\n * 3. Calls `subscriber.initial(result)` with the historical snapshot.\n * 4. Deduplicates buffered events against the fetch result.\n * 5. Flushes remaining buffered events through `subscriber.next()`.\n * 6. Resumes live: pipes stream events directly to `subscriber.next()`.\n */\nexport class LiveQuery<T = Record<string, unknown>> {\n private _stream: StreamController<T>;\n private _subscriber: StreamSubscriber<T>;\n private _buffer: StreamEvent<T>[] = [];\n private _buffering = true;\n private _unsubStream: (() => void) | null = null;\n private _closed = false;\n\n constructor(\n stream: StreamController<T>,\n fetchFn: () => Promise<Result<T[]>>,\n subscriber: StreamSubscriber<T>,\n _filters: QueryFilter[],\n ) {\n this._stream = stream;\n this._subscriber = subscriber;\n\n // Step 1: Subscribe to live events and buffer them.\n this._unsubStream = stream.subscribe({\n next: (event) => {\n if (this._closed) return;\n if (this._buffering) {\n this._buffer.push(event);\n } else {\n subscriber.next(event);\n }\n },\n status: (s) => subscriber.status?.(s),\n error: (e) => subscriber.error?.(e),\n });\n\n // Step 2-5: Fetch historical and flush.\n this._runBackfill(fetchFn);\n }\n\n private async _runBackfill(fetchFn: () => Promise<Result<T[]>>): Promise<void> {\n try {\n const result = await fetchFn();\n\n if (this._closed) return;\n\n // Step 3: Call initial() with the historical snapshot.\n this._subscriber.initial?.(result);\n\n if (result.error) {\n this._buffering = false;\n return;\n }\n\n // Step 4: Deduplicate buffered events against fetched rows.\n // Use received_timestamp as the dedup boundary: only flush events\n // that are newer than the latest row in the fetch result.\n const rows = result.data;\n let lastTimestamp: string | undefined;\n if (rows.length > 0) {\n const lastRow = rows[rows.length - 1] as Record<string, unknown>;\n lastTimestamp = lastRow?.received_timestamp as string | undefined;\n }\n\n // Step 5: Flush buffered events that are newer than the fetch.\n this._buffering = false;\n for (const event of this._buffer) {\n if (this._closed) break;\n if (lastTimestamp && event.timestamp <= lastTimestamp) {\n continue; // already covered by the fetch\n }\n this._subscriber.next(event);\n }\n this._buffer = [];\n } catch {\n // Fetch failed — stop buffering and resume live only.\n this._buffering = false;\n this._buffer = [];\n }\n }\n\n /** Close the live query and the underlying stream. */\n close(): void {\n this._closed = true;\n this._buffering = false;\n this._buffer = [];\n this._unsubStream?.();\n this._stream.close();\n }\n}\n","import { err, okPage } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { StreamTransport } from \"./stream/controller.js\";\nimport { StreamController } from \"./stream/controller.js\";\nimport { LiveQuery } from \"./stream/live-query.js\";\nimport type {\n Aggregation,\n FetchOptions,\n FilterOp,\n HttpContext,\n OrderClause,\n QueryFilter,\n Result,\n StreamOptions,\n StreamSubscriber,\n StructuredQuery,\n TimeRange,\n} from \"./types.js\";\n\n/** SDK operator → backend operator mapping. */\nconst OP_MAP: Record<FilterOp, string> = {\n \"=\": \"eq\",\n \"!=\": \"neq\",\n \">\": \"gt\",\n \">=\": \"gte\",\n \"<\": \"lt\",\n \"<=\": \"lte\",\n in: \"in\",\n like: \"like\",\n not_like: \"not_like\",\n};\n\ninterface QueryState {\n table: string;\n columns: string[];\n aggregations: Aggregation[];\n filters: QueryFilter[];\n groupBy: string[];\n orderBy: OrderClause[];\n limit?: number;\n timeRange?: TimeRange;\n cacheTTL?: number;\n}\n\ntype CreateStreamFn<Row> = (table: string, opts?: StreamOptions) => StreamController<Row>;\n\n/**\n * Immutable, PromiseLike query builder.\n * Every chain method returns a new instance. `await builder` auto-executes `.fetch()`.\n */\nexport class QueryBuilder<Row = Record<string, unknown>> implements PromiseLike<Result<Row[]>> {\n /** @internal */\n private readonly _state: Readonly<QueryState>;\n /** @internal */\n private readonly _ctx: HttpContext;\n /** @internal */\n private readonly _createStream: CreateStreamFn<Row>;\n\n constructor(ctx: HttpContext, state: QueryState, createStream: CreateStreamFn<Row>) {\n this._ctx = ctx;\n this._state = Object.freeze({ ...state });\n this._createStream = createStream;\n }\n\n // --- Builder methods (each returns a new QueryBuilder) ---\n\n select(...columns: string[]): QueryBuilder<Row> {\n return this._clone({ columns: [...this._state.columns, ...columns] });\n }\n\n where(column: string, op: FilterOp, value: unknown): QueryBuilder<Row> {\n const filter: QueryFilter = { column, op: OP_MAP[op], value };\n return this._clone({ filters: [...this._state.filters, filter] });\n }\n\n count(column = \"*\", alias = \"count\"): QueryBuilder<Row> {\n return this._addAgg(\"count\", column, alias);\n }\n\n sum(column: string, alias = `sum_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"sum\", column, alias);\n }\n\n avg(column: string, alias = `avg_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"avg\", column, alias);\n }\n\n min(column: string, alias = `min_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"min\", column, alias);\n }\n\n max(column: string, alias = `max_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"max\", column, alias);\n }\n\n countDistinct(column: string, alias = `count_distinct_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"countDistinct\", column, alias);\n }\n\n aggregate(fn: string, column: string, alias: string): QueryBuilder<Row> {\n return this._addAgg(fn, column, alias);\n }\n\n groupBy(...columns: string[]): QueryBuilder<Row> {\n return this._clone({ groupBy: [...this._state.groupBy, ...columns] });\n }\n\n orderBy(column: string, dir: \"asc\" | \"desc\" = \"asc\"): QueryBuilder<Row> {\n return this._clone({ orderBy: [...this._state.orderBy, { column, dir }] });\n }\n\n limit(n: number): QueryBuilder<Row> {\n return this._clone({ limit: n });\n }\n\n timeRange(column: string, since: string, until?: string): QueryBuilder<Row> {\n return this._clone({ timeRange: { column, since, until } });\n }\n\n cacheTTL(seconds: number): QueryBuilder<Row> {\n return this._clone({ cacheTTL: seconds });\n }\n\n // --- Execution ---\n\n /** Default row limit when none is specified. Matches backend DefaultMaxRows. */\n static readonly DEFAULT_LIMIT = 1000;\n\n async fetch(opts?: FetchOptions): Promise<Result<Row[]>> {\n const effectiveLimit = opts?.limit ?? this._state.limit ?? QueryBuilder.DEFAULT_LIMIT;\n const ast = this._buildAST(effectiveLimit);\n\n const { data, error } = await request<Row[]>(this._ctx, {\n method: \"POST\",\n path: `/v1/query?table=${encodeURIComponent(this._state.table)}`,\n body: ast,\n signal: opts?.signal,\n });\n\n if (error) return err(error);\n\n const rows = data!;\n const hasMore = effectiveLimit != null && rows.length >= effectiveLimit;\n\n if (hasMore) {\n const nextFn = () => this._fetchNext(rows, effectiveLimit!, opts);\n return okPage(rows, true, nextFn);\n }\n\n return okPage(rows, false);\n }\n\n stream(opts?: StreamOptions): StreamController<Row> {\n const raw = this._createStream(this._state.table, opts);\n const filters = this._state.filters;\n const columns = this._state.columns;\n\n // If no filters or column projection, return the raw stream.\n if (filters.length === 0 && columns.length === 0) {\n return raw;\n }\n\n // Wrap with a filtering transport that applies AST predicates client-side.\n return new FilteredStreamController<Row>(raw, filters, columns);\n }\n\n /**\n * Start a live query: fetches historical data, then streams live updates.\n *\n * The subscriber's `initial()` is called once with the fetch result, then\n * `next()` fires for each live event. Events that arrived during the fetch\n * are deduplicated and flushed automatically.\n *\n * Returns a LiveQuery handle with a `.close()` method.\n */\n liveQuery(subscriber: StreamSubscriber<Row>, opts?: StreamOptions): LiveQuery<Row> {\n const stream = this.stream(opts);\n const fetchFn = () => this.fetch();\n return new LiveQuery<Row>(stream, fetchFn, subscriber, this._state.filters);\n }\n\n // --- PromiseLike implementation ---\n\n then<TResult1 = Result<Row[]>, TResult2 = never>(\n onfulfilled?: ((value: Result<Row[]>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.fetch().then(onfulfilled, onrejected);\n }\n\n // --- Private helpers ---\n\n private _clone(overrides: Partial<QueryState>): QueryBuilder<Row> {\n return new QueryBuilder(this._ctx, { ...this._state, ...overrides }, this._createStream);\n }\n\n private _addAgg(fn: string, column: string, alias: string): QueryBuilder<Row> {\n const agg: Aggregation = { fn, column, alias };\n return this._clone({ aggregations: [...this._state.aggregations, agg] });\n }\n\n private _buildAST(effectiveLimit?: number): StructuredQuery {\n const ast: StructuredQuery = {};\n if (this._state.columns.length > 0) ast.columns = this._state.columns;\n if (this._state.aggregations.length > 0) ast.aggregations = this._state.aggregations;\n if (this._state.filters.length > 0) ast.filters = this._state.filters;\n if (this._state.groupBy.length > 0) ast.group_by = this._state.groupBy;\n if (this._state.orderBy.length > 0) {\n ast.order_by = this._state.orderBy;\n } else if (effectiveLimit != null && this._state.aggregations.length === 0) {\n // Default ordering for deterministic cursor pagination.\n ast.order_by = [{ column: \"received_timestamp\", dir: \"desc\" }];\n }\n if (effectiveLimit != null) ast.limit = effectiveLimit;\n if (this._state.timeRange) ast.time_range = this._state.timeRange;\n return ast;\n }\n\n private async _fetchNext(\n prevRows: Row[],\n _limit: number,\n opts?: FetchOptions,\n ): Promise<Result<Row[]>> {\n const orderCol = this._state.orderBy[0]?.column ?? \"received_timestamp\";\n const orderDir = this._state.orderBy[0]?.dir ?? \"desc\";\n const lastRow = prevRows[prevRows.length - 1] as Record<string, unknown>;\n const lastValue = lastRow?.[orderCol];\n\n if (lastValue === undefined) return okPage([] as unknown as Row[], false);\n\n const cursorOp = orderDir === \"desc\" ? \"lt\" : \"gt\";\n const cursorFilter: QueryFilter = { column: orderCol, op: cursorOp, value: lastValue };\n // Ensure the next page uses the same order the cursor assumes.\n const orderBy: OrderClause[] =\n this._state.orderBy.length > 0 ? this._state.orderBy : [{ column: orderCol, dir: orderDir }];\n const nextBuilder = this._clone({\n filters: [...this._state.filters, cursorFilter],\n orderBy,\n });\n\n return nextBuilder.fetch(opts);\n }\n}\n\n// ============================================================================\n// Client-side stream filtering\n// ============================================================================\n\n/**\n * Wraps a StreamController, applying client-side filters and column projection\n * before delivering events to subscribers.\n *\n * Lifecycle: by the time we reach this constructor, `inner` has already been\n * built (and is opening its own SSE connection). The outer transport's\n * `connect()` doesn't open a new connection — it bridges `inner`'s events\n * through a filter into the outer subscriber set. On `disconnect()`, closing\n * `inner` is what actually tears down the SSE socket; the subscription we\n * register on `inner` is left to be garbage-collected with it, which is why\n * we don't bother saving the unsubscribe handle.\n * @internal\n */\nclass FilteredStreamController<T = Record<string, unknown>> extends StreamController<T> {\n constructor(inner: StreamController<T>, filters: QueryFilter[], columns: string[]) {\n const transport: StreamTransport<T> = {\n onEvent: null,\n onStatus: null,\n onError: null,\n connect() {\n inner.subscribe({\n next: (event) => {\n if (!matchesFilters(event.data as Record<string, unknown>, filters)) {\n return;\n }\n const projected =\n columns.length > 0\n ? {\n ...event,\n data: projectColumns(event.data as Record<string, unknown>, columns) as T,\n }\n : event;\n this.onEvent?.(projected);\n },\n status: (s) => this.onStatus?.(s),\n error: (e) => this.onError?.(e),\n });\n },\n disconnect() {\n inner.close();\n },\n };\n super(transport);\n }\n}\n\n/** @internal Evaluate all filters against a data row. All must pass (AND). */\nfunction matchesFilters(row: Record<string, unknown>, filters: QueryFilter[]): boolean {\n for (const f of filters) {\n const val = row[f.column];\n if (!evaluateFilter(val, f.op, f.value)) return false;\n }\n return true;\n}\n\n/** @internal Evaluate a single filter predicate. */\nfunction evaluateFilter(actual: unknown, op: string, expected: unknown): boolean {\n switch (op) {\n case \"eq\":\n return actual === expected;\n case \"neq\":\n return actual !== expected;\n case \"gt\":\n return compareOrdered(actual, expected, (a, b) => a > b);\n case \"gte\":\n return compareOrdered(actual, expected, (a, b) => a >= b);\n case \"lt\":\n return compareOrdered(actual, expected, (a, b) => a < b);\n case \"lte\":\n return compareOrdered(actual, expected, (a, b) => a <= b);\n case \"in\":\n return Array.isArray(expected) && expected.includes(actual);\n case \"like\": {\n if (typeof actual !== \"string\" || typeof expected !== \"string\") return false;\n // Convert SQL LIKE pattern to regex: % → .*, _ → .\n const escaped = expected.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = escaped.replace(/%/g, \".*\").replace(/_/g, \".\");\n return new RegExp(`^${pattern}$`, \"i\").test(actual);\n }\n case \"not_like\": {\n if (typeof actual !== \"string\" || typeof expected !== \"string\") return false;\n const escaped = expected.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = escaped.replace(/%/g, \".*\").replace(/_/g, \".\");\n return !new RegExp(`^${pattern}$`, \"i\").test(actual);\n }\n default:\n return true; // unknown op — pass through\n }\n}\n\n/**\n * @internal Apply an ordered comparison only when both sides are the same\n * comparable primitive (number-vs-number or string-vs-string — strings are\n * lexicographic, which is correct for ISO-8601 timestamps). Mismatched or\n * unsupported types return false instead of relying on JS coercion.\n */\nfunction compareOrdered(\n actual: unknown,\n expected: unknown,\n cmp: (a: number, b: number) => boolean,\n): boolean {\n if (typeof actual === \"number\" && typeof expected === \"number\") {\n return cmp(actual, expected);\n }\n if (typeof actual === \"string\" && typeof expected === \"string\") {\n // `>`/`<` on strings is lexicographic; reuse the same comparator by\n // casting through `as unknown as number` — the runtime operator works\n // identically on strings.\n return cmp(actual as unknown as number, expected as unknown as number);\n }\n return false;\n}\n\n/** @internal Project a row to only the specified columns. */\nfunction projectColumns(row: Record<string, unknown>, columns: string[]): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const col of columns) {\n if (col in row) result[col] = row[col];\n }\n return result;\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport { QueryBuilder } from \"./query-builder.js\";\nimport type { StreamController } from \"./stream/controller.js\";\nimport type {\n FetchOptions,\n HttpContext,\n InsertResult,\n Result,\n StreamOptions,\n TableSchema,\n} from \"./types.js\";\n\ntype CreateStreamFn<Row> = (table: string, opts?: StreamOptions) => StreamController<Row>;\n\n/**\n * Reference to a table. NOT thenable — safe to pass around without triggering requests.\n * Use `.fetch()`, `.select()`, `.insert()`, `.schema()`, or `.stream()` to act on it.\n */\nexport class TableRef<Row = Record<string, unknown>> {\n private readonly _ctx: HttpContext;\n private readonly _table: string;\n private readonly _createStream: CreateStreamFn<Row>;\n\n constructor(ctx: HttpContext, table: string, createStream: CreateStreamFn<Row>) {\n this._ctx = ctx;\n this._table = table;\n this._createStream = createStream;\n }\n\n /** SELECT * shortcut — fetches rows with optional pagination. */\n async fetch(opts?: FetchOptions): Promise<Result<Row[]>> {\n return this.select()\n .limit(opts?.limit ?? 1000)\n .fetch(opts);\n }\n\n /** Start building a typed query. Returns an immutable, PromiseLike QueryBuilder. */\n select(...columns: string[]): QueryBuilder<Row> {\n return new QueryBuilder<Row>(\n this._ctx,\n {\n table: this._table,\n columns,\n aggregations: [],\n filters: [],\n groupBy: [],\n orderBy: [],\n },\n this._createStream,\n );\n }\n\n /** Insert one or more rows into this table. */\n async insert(\n data: Partial<Row> | Partial<Row>[],\n opts?: { signal?: AbortSignal },\n ): Promise<Result<InsertResult>> {\n if (Array.isArray(data)) {\n // TODO: Switch to NDJSON\n // FAST: Fire all HTTP requests concurrently instead of waiting for each one\n const promises = data.map((row) =>\n request<{ ok?: boolean; duplicate?: boolean }>(this._ctx, {\n method: \"POST\",\n path: `/v1/ingest?table=${encodeURIComponent(this._table)}`,\n body: row,\n signal: opts?.signal,\n }),\n );\n\n // TODO: with NDJSON/array version, need to rework how to show errors if only some/one fail\n const results = await Promise.all(promises);\n\n // Check if any of the concurrent requests failed\n for (const res of results) {\n if (res.error) return err(res.error);\n }\n return ok({ ok: true });\n }\n\n const { data: res, error } = await request<{ ok?: boolean; duplicate?: boolean }>(this._ctx, {\n method: \"POST\",\n path: `/v1/ingest?table=${encodeURIComponent(this._table)}`,\n body: data,\n signal: opts?.signal,\n });\n\n if (error) return err(error);\n const result: InsertResult = { ok: res?.ok ?? true };\n if (res?.duplicate != null) result.duplicate = res.duplicate;\n return ok(result);\n }\n\n /** Fetch the schema for this table. */\n async schema(opts?: { signal?: AbortSignal }): Promise<Result<TableSchema>> {\n const { data, error } = await request<TableSchema>(this._ctx, {\n method: \"GET\",\n path: `/v1/schema?table=${encodeURIComponent(this._table)}`,\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Subscribe to live events for this table. */\n stream(opts?: StreamOptions): StreamController<Row> {\n return this._createStream(this._table, opts);\n }\n}\n","import { DLQNamespace } from \"./dlq.js\";\nimport { PipeRef, PipesNamespace } from \"./pipes.js\";\nimport { PolicyNamespace } from \"./policy.js\";\nimport { SchemaNamespace } from \"./schema.js\";\nimport { sql } from \"./sql.js\";\nimport { StreamController } from \"./stream/controller.js\";\nimport { SSETransport } from \"./stream/sse.js\";\nimport { SysNamespace } from \"./sys.js\";\nimport { TableRef } from \"./table.js\";\nimport type { ClientConfig, Database, HttpContext, Result, StreamOptions } from \"./types.js\";\n\ntype TableName<DB> = DB extends Database ? Extract<keyof DB, string> : string;\ntype RowType<DB, T extends string> = DB extends Database\n ? T extends keyof DB\n ? DB[T]\n : Record<string, unknown>\n : Record<string, unknown>;\n\nexport class WaveHouseClient<DB extends Database = Database> {\n /** @internal */\n readonly _ctx: HttpContext;\n\n /** Schema introspection namespace. */\n readonly schema: SchemaNamespace;\n /** Access control policy namespace (admin). */\n readonly policy: PolicyNamespace;\n /** Dead Letter Queue namespace. */\n readonly dlq: DLQNamespace;\n /** System health/readiness namespace. */\n readonly sys: SysNamespace;\n /** Named query pipes admin namespace. */\n readonly pipes: PipesNamespace;\n\n constructor(config: ClientConfig<DB>) {\n this._ctx = {\n baseURL: config.baseURL.replace(/\\/+$/, \"\"),\n auth: config.auth,\n options: {\n maxRetries: config.options?.maxRetries ?? 2,\n },\n };\n\n this.schema = new SchemaNamespace(this._ctx);\n this.policy = new PolicyNamespace(this._ctx);\n this.dlq = new DLQNamespace(this._ctx, (table, opts) => this._createStream(table, opts));\n this.sys = new SysNamespace(this._ctx);\n this.pipes = new PipesNamespace(this._ctx);\n }\n\n /** Get a table reference for building queries, inserts, and streams. */\n from<T extends TableName<DB>>(table: T): TableRef<RowType<DB, T>> {\n return new TableRef<RowType<DB, T>>(this._ctx, table, (t, opts) =>\n this._createStream<RowType<DB, T>>(t, opts),\n );\n }\n\n /** Get a reference to a named query pipe. PromiseLike — `await` it to execute. */\n pipe<Row = Record<string, unknown>>(\n name: string,\n params?: Record<string, unknown>,\n ): PipeRef<Row> {\n return new PipeRef<Row>(this._ctx, name, params, (t, opts) => this._createStream<Row>(t, opts));\n }\n\n /**\n * Execute a raw SQL query against ClickHouse. Requires the admin role (the\n * configured `admin_role`, `\"admin\"` by default; there is no separate\n * `service` role). The endpoint proxies straight to ClickHouse's HTTP\n * interface so any ClickHouse-accepted SQL works; positional `?` param\n * binding is NOT supported — inline literals or use the structured query\n * builder for safe binding. See sql.ts for details.\n */\n sql<Row = Record<string, unknown>>(\n query: string,\n opts?: { signal?: AbortSignal },\n ): Promise<Result<Row[]>> {\n // Migration guard: the second argument used to be a positional-`?`\n // params array. TS callers get a compile-time error from the type\n // signature, but JS callers (or `any`-typed callsites) would silently\n // pass an array as `opts` and only discover the break via downstream\n // SQL errors. Throw a clear runtime error pointing at the migration.\n if (Array.isArray(opts)) {\n throw new Error(\n \"[WaveHouse SDK] client.sql(sql, params) was removed. The /v1/admin/query endpoint does not accept positional `?` params. Inline literals into the SQL, or use the structured query builder (wh.from(table)…) for safe binding from user input.\",\n );\n }\n return sql<Row>(this._ctx, query, opts);\n }\n\n /** @internal Create a stream for the given table. */\n private _createStream<T = Record<string, unknown>>(\n table: string,\n opts?: StreamOptions,\n ): StreamController<T> {\n if (typeof EventSource === \"undefined\") {\n // TODO: fallback method? polling?\n throw new Error(\n \"[WaveHouse SDK] Native EventSource is not available in this environment. \" +\n \"Please provide a global polyfill (e.g., `globalThis.EventSource = require('eventsource')`).\",\n );\n }\n\n const transport = new SSETransport<T>({\n baseURL: this._ctx.baseURL,\n table,\n since: opts?.since,\n auth: this._ctx.auth,\n });\n const controller = new StreamController<T>(transport);\n if (opts?.signal) controller.attachSignal(opts.signal);\n return controller;\n }\n}\n\n/** Create a new WaveHouse client instance. */\nexport function createClient<DB extends Database = Database>(\n config: ClientConfig<DB>,\n): WaveHouseClient<DB> {\n return new WaveHouseClient(config);\n}\n"],"mappings":"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","names":["err","res"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/dlq.ts","../src/pipes.ts","../src/policy.ts","../src/schema.ts","../src/sql.ts","../src/stream/controller.ts","../src/stream/sse.ts","../src/sys.ts","../src/stream/live-query.ts","../src/query-builder.ts","../src/table.ts","../src/client.ts"],"sourcesContent":["// ============================================================================\n// @wavehouse/sdk — Public API\n// ============================================================================\n\n// --- Main entry point ---\nexport { createClient, WaveHouseClient } from \"./client.js\";\nexport { DLQNamespace } from \"./dlq.js\";\nexport { PipeRef, PipesNamespace } from \"./pipes.js\";\nexport { PolicyNamespace } from \"./policy.js\";\nexport { QueryBuilder } from \"./query-builder.js\";\nexport { SchemaNamespace } from \"./schema.js\";\nexport { StreamController } from \"./stream/controller.js\";\nexport { LiveQuery } from \"./stream/live-query.js\";\nexport { SysNamespace } from \"./sys.js\";\n// --- Core classes ---\nexport { TableRef } from \"./table.js\";\n\n// --- Types ---\nexport type {\n Aggregation,\n // Config\n ClientConfig,\n ClientOptions,\n // Schema\n Column,\n // Database & result\n Database,\n // DLQ\n DLQStats,\n FetchOptions,\n // Query\n FilterOp,\n // Ingest\n InsertResult,\n OrderClause,\n ParamDef,\n // Pipes\n Pipe,\n // Policy\n Policy,\n PolicyFilter,\n QueryFilter,\n Result,\n RolePermissions,\n Schemas,\n StreamEvent,\n StreamOptions,\n // Streaming\n StreamStatus,\n StreamSubscriber,\n StructuredQuery,\n TablePolicy,\n TableSchema,\n TimeRange,\n ValidationResult,\n WaveHouseError,\n} from \"./types.js\";\n","import type { Result, WaveHouseError } from \"./types.js\";\n\n/** Create a WaveHouseError from an HTTP response. */\nexport async function parseErrorResponse(res: Response): Promise<WaveHouseError> {\n let body: Record<string, unknown> | undefined;\n try {\n body = (await res.json()) as Record<string, unknown>;\n } catch {\n body = undefined;\n }\n\n const message =\n typeof body?.error === \"string\"\n ? body.error\n : typeof body?.message === \"string\"\n ? body.message\n : res.statusText;\n\n const retryable = res.status === 503 || res.status >= 500;\n return {\n status: res.status,\n code: `HTTP_${res.status}`,\n message,\n details: body,\n retryable,\n };\n}\n\n/** Create a WaveHouseError from a network/fetch error. */\nexport function networkError(cause: unknown): WaveHouseError {\n const message = cause instanceof Error ? cause.message : String(cause);\n return {\n status: 0,\n code: \"NETWORK_ERROR\",\n message,\n retryable: true,\n };\n}\n\n/** Wrap a successful value in a Result. */\nexport function ok<T>(data: T): Result<T> {\n return { ok: true, data, error: null };\n}\n\n/** Wrap a successful paginated value in a Result. */\nexport function okPage<T>(data: T, hasMore: boolean, next?: () => Promise<Result<T>>): Result<T> {\n return { ok: true, data, error: null, hasMore, next };\n}\n\n/** Wrap an error in a Result. */\nexport function err<T = unknown>(error: WaveHouseError): Result<T> {\n return { ok: false, data: null, error };\n}\n","import { networkError, parseErrorResponse } from \"./errors.js\";\nimport type { HttpContext, WaveHouseError } from \"./types.js\";\n\ninterface RequestOptions {\n method: string;\n path: string;\n body?: unknown;\n params?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/** @internal */\nexport interface HttpResult<T> {\n data: T | null;\n error: WaveHouseError | null;\n headers: Headers;\n}\n\n/**\n * Internal fetch wrapper with auth injection, retry, backoff, and Retry-After.\n * @internal\n */\nexport async function request<T>(ctx: HttpContext, opts: RequestOptions): Promise<HttpResult<T>> {\n const url = buildURL(ctx.baseURL, opts.path, opts.params);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n };\n\n if (ctx.auth) {\n const token = await ctx.auth();\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n }\n\n let lastError: WaveHouseError | null = null;\n const maxAttempts = ctx.options.maxRetries + 1;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n const res = await fetch(url, {\n method: opts.method,\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n signal: opts.signal,\n });\n\n if (res.ok) {\n const text = await res.text();\n const data = text ? (JSON.parse(text) as T) : (undefined as T);\n return { data, error: null, headers: res.headers };\n }\n\n const error = await parseErrorResponse(res);\n\n // 503 with Retry-After: wait the specified duration\n if (res.status === 503) {\n const retryAfter = res.headers.get(\"Retry-After\");\n if (retryAfter && attempt < maxAttempts - 1) {\n const delay = parseInt(retryAfter, 10) * 1000 || 30_000;\n await sleep(delay, opts.signal);\n lastError = error;\n continue;\n }\n }\n\n // Retryable server errors (5xx)\n if (error.retryable && attempt < maxAttempts - 1) {\n await sleep(backoff(attempt), opts.signal);\n lastError = error;\n continue;\n }\n\n return { data: null, error, headers: res.headers };\n } catch (e) {\n // AbortError — return immediately, no retry\n if (e instanceof DOMException && e.name === \"AbortError\") {\n return {\n data: null,\n error: { status: 0, code: \"ABORTED\", message: \"Request aborted\", retryable: false },\n headers: new Headers(),\n };\n }\n\n lastError = networkError(e);\n if (attempt < maxAttempts - 1) {\n await sleep(backoff(attempt), opts.signal);\n }\n }\n }\n\n return { data: null, error: lastError!, headers: new Headers() };\n}\n\nfunction buildURL(base: string, path: string, params?: Record<string, string>): string {\n const url = new URL(path, base.endsWith(\"/\") ? base : `${base}/`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n url.searchParams.set(k, v);\n }\n }\n return url.toString();\n}\n\nfunction backoff(attempt: number): number {\n return Math.min(1000 * 2 ** attempt, 30_000);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n return;\n }\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timer);\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n },\n { once: true },\n );\n });\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { StreamController } from \"./stream/controller.js\";\nimport type { DLQStats, HttpContext, Result, StreamOptions } from \"./types.js\";\n\ntype CreateStreamFn = (table: string, opts?: StreamOptions) => StreamController;\n\n/** Namespace for Dead Letter Queue operations. */\nexport class DLQNamespace {\n private readonly _ctx: HttpContext;\n private readonly _createStream: CreateStreamFn;\n\n constructor(ctx: HttpContext, createStream: CreateStreamFn) {\n this._ctx = ctx;\n this._createStream = createStream;\n }\n\n /** Get DLQ statistics (message counts per table). */\n async list(opts?: { signal?: AbortSignal }): Promise<Result<DLQStats>> {\n const { data, error } = await request<DLQStats>(this._ctx, {\n method: \"GET\",\n path: \"/v1/dlq/stats\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Get DLQ stats filtered by table name. */\n async table(name: string, opts?: { signal?: AbortSignal }): Promise<Result<DLQStats>> {\n const { data, error } = await request<DLQStats>(this._ctx, {\n method: \"GET\",\n path: \"/v1/dlq/stats\",\n params: { table: name },\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Subscribe to live DLQ events. */\n stream(opts?: StreamOptions): StreamController {\n return this._createStream(\"dlq\", opts);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { StreamController } from \"./stream/controller.js\";\nimport type { FetchOptions, HttpContext, Pipe, Result, StreamOptions } from \"./types.js\";\n\ntype CreateStreamFn<Row> = (table: string, opts?: StreamOptions) => StreamController<Row>;\n\n/** Reference to a named query pipe — PromiseLike for convenient `await`. */\nexport class PipeRef<Row = Record<string, unknown>> implements PromiseLike<Result<Row[]>> {\n private readonly _ctx: HttpContext;\n private readonly _name: string;\n private readonly _params?: Record<string, unknown>;\n private readonly _createStream: CreateStreamFn<Row>;\n\n constructor(\n ctx: HttpContext,\n name: string,\n params: Record<string, unknown> | undefined,\n createStream: CreateStreamFn<Row>,\n ) {\n this._ctx = ctx;\n this._name = name;\n this._params = params;\n this._createStream = createStream;\n }\n\n /** Execute the pipe and return results. */\n async fetch(opts?: FetchOptions): Promise<Result<Row[]>> {\n const { data, error } = await request<Row[]>(this._ctx, {\n method: \"POST\",\n path: `/v1/pipes/${encodeURIComponent(this._name)}`,\n body: this._params ?? {},\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Subscribe to live events from the pipe's underlying query. */\n stream(opts?: StreamOptions): StreamController<Row> {\n return this._createStream(this._name, opts);\n }\n\n then<TResult1 = Result<Row[]>, TResult2 = never>(\n onfulfilled?: ((value: Result<Row[]>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.fetch().then(onfulfilled, onrejected);\n }\n}\n\n/** Admin namespace for managing named query pipes. */\nexport class PipesNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /** List all registered pipes. */\n async list(opts?: { signal?: AbortSignal }): Promise<Result<Pipe[]>> {\n const { data, error } = await request<Pipe[]>(this._ctx, {\n method: \"GET\",\n path: \"/v1/admin/pipes\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Get a single pipe definition by name. */\n async get(name: string, opts?: { signal?: AbortSignal }): Promise<Result<Pipe>> {\n const { data, error } = await request<Pipe>(this._ctx, {\n method: \"GET\",\n path: `/v1/admin/pipes/${encodeURIComponent(name)}`,\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Create or update a pipe. */\n async set(\n name: string,\n def: Omit<Pipe, \"name\">,\n opts?: { signal?: AbortSignal },\n ): Promise<Result<void>> {\n const { error } = await request<{ ok: boolean }>(this._ctx, {\n method: \"PUT\",\n path: `/v1/admin/pipes/${encodeURIComponent(name)}`,\n body: def,\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n\n /** Delete a pipe by name. */\n async delete(name: string, opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<{ ok: boolean }>(this._ctx, {\n method: \"DELETE\",\n path: `/v1/admin/pipes/${encodeURIComponent(name)}`,\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Policy, Result, ValidationResult } from \"./types.js\";\n\n/** Namespace for access control policy management. Requires the admin role (the configured `admin_role`, `\"admin\"` by default). */\nexport class PolicyNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /** Get the current access control policy. */\n async get(opts?: { signal?: AbortSignal }): Promise<Result<Policy>> {\n const { data, error } = await request<Policy>(this._ctx, {\n method: \"GET\",\n path: \"/v1/admin/policy\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Replace the entire access control policy. */\n async set(policy: Policy, opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<{ ok: boolean }>(this._ctx, {\n method: \"PUT\",\n path: \"/v1/admin/policy\",\n body: policy,\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n\n /** Validate a policy without applying it (dry run). */\n async validate(\n policy: Policy,\n opts?: { signal?: AbortSignal },\n ): Promise<Result<ValidationResult>> {\n const { data, error } = await request<ValidationResult>(this._ctx, {\n method: \"POST\",\n path: \"/v1/admin/policy/validate\",\n body: policy,\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Result, Schemas } from \"./types.js\";\n\n/** Namespace for schema introspection. */\nexport class SchemaNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /** List all table schemas discovered from ClickHouse. */\n async list(opts?: { signal?: AbortSignal }): Promise<Result<Schemas>> {\n // The backend returns TableSchema[] — transform to Record<string, TableSchema>.\n const { data, error } = await request<unknown>(this._ctx, {\n method: \"GET\",\n path: \"/v1/schema\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n\n let schemas: Schemas;\n if (Array.isArray(data)) {\n schemas = {};\n for (const table of data) {\n if (table && typeof table === \"object\" && \"name\" in table) {\n schemas[(table as { name: string }).name] = table as Schemas[string];\n }\n }\n } else {\n schemas = data as Schemas;\n }\n return ok(schemas);\n }\n\n /** Force a schema refresh from ClickHouse system.columns. */\n async refresh(opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<Schemas>(this._ctx, {\n method: \"POST\",\n path: \"/v1/schema/refresh\",\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Result } from \"./types.js\";\n\n/**\n * Execute a raw SQL query against ClickHouse.\n *\n * Backed by `POST /v1/admin/query`, which requires the admin role — the same\n * gate as the rest of `/v1/admin/*`. Callers must hold a JWT whose role is the\n * configured `admin_role` (`\"admin\"` by default); there is no separate\n * `service` role. The JWT middleware always runs, so a request with no token\n * or an invalid one is denied, never granted. Non-admin use cases should use\n * the structured query builder (`wh.from(table)...`) instead.\n *\n * The server proxies the SQL string verbatim to ClickHouse's HTTP interface,\n * so any ClickHouse-accepted statement works — including multi-statement\n * input (`SELECT 1; TRUNCATE t`) and arbitrary DDL/DML/SYSTEM verbs.\n *\n * **JSON-row contract.** This helper returns `Result<Row[]>` and assumes the\n * response is the standard `FORMAT JSON` envelope (or an empty body for\n * no-result mutations — coerced to `[]`). Inline non-JSON `FORMAT` overrides\n * (`SELECT 1 FORMAT CSV` / `FORMAT TSV` / `FORMAT Pretty` / etc.) are NOT\n * compatible with `sql()` — the proxy passes the upstream Content-Type\n * through, and the SDK's JSON decoder throws on a non-JSON body, which the\n * retry layer surfaces as a `NETWORK_ERROR` result (not a structured\n * format-mismatch error). For CSV/TSV exports, hit `/v1/admin/query`\n * directly with `fetch()` and read the body as text.\n *\n * **No parameter binding.** Positional `?` substitution is not supported.\n * The SDK has no way to forward ClickHouse-style named params\n * (`WHERE id = {id:UInt32}` with `param_id=42` on the query string) —\n * the proxy doesn't forward arbitrary query-string params to ClickHouse\n * and the SDK doesn't expose a hook to add them. Inline literals into\n * the SQL string, or — for safe binding from user-supplied input — use\n * the structured query builder (`wh.from(...).select(...).where(...)`).\n */\nexport async function sql<Row = Record<string, unknown>>(\n ctx: HttpContext,\n query: string,\n opts?: { signal?: AbortSignal },\n): Promise<Result<Row[]>> {\n const { data, error } = await request<Row[]>(ctx, {\n method: \"POST\",\n path: \"/v1/admin/query\",\n body: { sql: query },\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n}\n","import type { StreamEvent, StreamStatus, StreamSubscriber, WaveHouseError } from \"../types.js\";\n\n/** @internal Transport abstraction for SSE backend. */\nexport interface StreamTransport<T = Record<string, unknown>> {\n connect(): void;\n disconnect(): void;\n onEvent: ((event: StreamEvent<T>) => void) | null;\n onStatus: ((status: StreamStatus) => void) | null;\n onError: ((error: WaveHouseError) => void) | null;\n}\n\n/**\n * Controls a live event stream. NOT thenable.\n * Use `.subscribe()` for callback-based consumption or `for await` for async iteration.\n */\nexport class StreamController<T = Record<string, unknown>> {\n private _transport: StreamTransport<T>;\n private _subscribers = new Set<StreamSubscriber<T>>();\n private _status: StreamStatus = \"connecting\";\n private _buffer: StreamEvent<T>[] = [];\n private _waiters: { resolve: (value: IteratorResult<StreamEvent<T>>) => void }[] = [];\n private _done = false;\n\n constructor(transport: StreamTransport<T>) {\n this._transport = transport;\n\n this._transport.onEvent = (event) => {\n for (const sub of this._subscribers) {\n sub.next(event);\n }\n // Async iterator support\n const waiter = this._waiters.shift();\n if (waiter) {\n waiter.resolve({ value: event, done: false });\n } else {\n this._buffer.push(event);\n }\n };\n\n this._transport.onStatus = (status) => {\n // Deduplicate: skip if status hasn't changed (e.g. transport fires\n // 'connecting' after StreamController already set it as the initial state).\n if (status === this._status) return;\n this._status = status;\n for (const sub of this._subscribers) {\n sub.status?.(status);\n }\n if (status === \"closed\") {\n this._done = true;\n for (const w of this._waiters) {\n w.resolve({ value: undefined as never, done: true });\n }\n this._waiters = [];\n }\n };\n\n this._transport.onError = (error) => {\n for (const sub of this._subscribers) {\n sub.error?.(error);\n }\n };\n\n this._transport.connect();\n }\n\n /** Current connection status. */\n get status(): StreamStatus {\n return this._status;\n }\n\n /**\n * Returns a promise that resolves when the stream status reaches `'live'`,\n * rejects immediately if the stream is already `'closed'`, or rejects after\n * `timeoutMs` milliseconds (default: 5 000) if it never connects.\n *\n * Safe to call before `.subscribe()` — does not trigger auto-close when\n * the internal waiter is removed.\n *\n * `@example`\n * const stream = client.from('events').stream();\n * const unsub = stream.subscribe({ next: (e) => console.log(e) });\n * await stream.connected(); // waits until the transport is live\n * await client.from('events').insert({ ... });\n */\n connected(timeoutMs = 5_000): Promise<void> {\n if (this._status === \"live\") return Promise.resolve();\n if (this._status === \"closed\") return Promise.reject(new Error(\"Stream is closed\"));\n if (this._done) return Promise.reject(new Error(\"Stream closed before connecting\"));\n\n return new Promise((resolve, reject) => {\n let settled = false;\n\n const timer = setTimeout(() => {\n if (settled) return;\n settled = true;\n this._subscribers.delete(watcher);\n reject(new Error(`Stream did not connect within ${timeoutMs}ms`));\n }, timeoutMs);\n\n // Use a private subscriber directly to avoid the auto-close side-effect\n // that the public subscribe() triggers when subscriber count drops to zero.\n const watcher: StreamSubscriber<T> = {\n next: () => {\n // no-op: we only care about status transitions here\n },\n status: (s) => {\n if (s === \"live\") {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n this._subscribers.delete(watcher);\n resolve();\n } else if (s === \"closed\") {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n this._subscribers.delete(watcher);\n reject(new Error(\"Stream closed before connecting\"));\n }\n },\n };\n\n this._subscribers.add(watcher);\n });\n }\n\n /** Subscribe to stream events via callbacks. Returns an unsubscribe function. */\n subscribe(subscriber: StreamSubscriber<T>): () => void {\n this._subscribers.add(subscriber);\n subscriber.status?.(this._status);\n\n return () => {\n this._subscribers.delete(subscriber);\n if (this._subscribers.size === 0 && this._waiters.length === 0) {\n this.close();\n }\n };\n }\n\n /** Attach an AbortSignal — when aborted, the stream is closed. */\n attachSignal(signal: AbortSignal): void {\n if (signal.aborted) {\n this.close();\n return;\n }\n signal.addEventListener(\"abort\", () => this.close(), { once: true });\n }\n\n /** Close the stream and release resources. */\n close(): void {\n this._transport.disconnect();\n if (this._status !== \"closed\") {\n this._status = \"closed\";\n for (const sub of this._subscribers) {\n sub.status?.(\"closed\");\n }\n }\n this._done = true;\n for (const w of this._waiters) {\n w.resolve({ value: undefined as never, done: true });\n }\n this._waiters = [];\n }\n\n /** Async iterator protocol — enables `for await (const event of stream)`. */\n [Symbol.asyncIterator](): AsyncIterableIterator<StreamEvent<T>> {\n const self = this;\n return {\n next(): Promise<IteratorResult<StreamEvent<T>>> {\n if (self._buffer.length > 0) {\n return Promise.resolve({ value: self._buffer.shift()!, done: false });\n }\n if (self._done) {\n return Promise.resolve({ value: undefined as never, done: true });\n }\n return new Promise((resolve) => {\n self._waiters.push({ resolve });\n });\n },\n return(): Promise<IteratorResult<StreamEvent<T>>> {\n self.close();\n return Promise.resolve({ value: undefined as never, done: true });\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n }\n}\n","import type { StreamEvent, StreamStatus, WaveHouseError } from \"../types.js\";\nimport type { StreamTransport } from \"./controller.js\";\n\nexport interface SSEOptions {\n baseURL: string;\n table: string;\n since?: string;\n auth?: () => Promise<string> | string;\n}\n\n/** Module-level active SSE connection counter. */\nlet activeSSEConnections = 0;\nconst SSE_WARN_THRESHOLD = 5;\n\n/** SSE transport. Native EventSource auto-reconnects. */\nexport class SSETransport<T = Record<string, unknown>> implements StreamTransport<T> {\n private _opts: SSEOptions;\n private _es: EventSource | null = null;\n\n onEvent: ((event: StreamEvent<T>) => void) | null = null;\n onStatus: ((status: StreamStatus) => void) | null = null;\n onError: ((error: WaveHouseError) => void) | null = null;\n\n constructor(opts: SSEOptions) {\n this._opts = opts;\n }\n\n connect(): void {\n if (typeof EventSource === \"undefined\") {\n throw new Error(\n \"[wavehouse] EventSource is not available in this environment. \" +\n \"Please provide a global polyfill (e.g., `globalThis.EventSource = require('eventsource')`).\",\n );\n }\n\n this._doConnect().catch((err) => {\n this.onError?.({\n status: 0,\n code: \"SSE_CONNECT_ERROR\",\n message: err instanceof Error ? err.message : String(err),\n retryable: true,\n });\n });\n }\n\n disconnect(): void {\n if (this._es) {\n this._es.close();\n this._es = null;\n activeSSEConnections = Math.max(0, activeSSEConnections - 1);\n }\n this.onStatus?.(\"closed\");\n }\n\n private async _doConnect(): Promise<void> {\n const url = new URL(\"/v1/stream\", this._opts.baseURL);\n url.searchParams.set(\"table\", this._opts.table);\n if (this._opts.since) {\n url.searchParams.set(\"since\", this._opts.since);\n }\n\n // EventSource can't set request headers, so the JWT goes in ?token=\n // (the server also accepts an Authorization header for non-browser clients)\n if (this._opts.auth) {\n const token = await this._opts.auth();\n if (token) {\n url.searchParams.set(\"token\", token);\n }\n }\n\n activeSSEConnections++;\n if (activeSSEConnections > SSE_WARN_THRESHOLD) {\n console.warn(\n `[wavehouse] ${activeSSEConnections} SSE connections open. ` +\n `Browsers limit HTTP/1.1 to 6 connections per domain.`,\n );\n }\n\n this._es = new EventSource(url.toString());\n\n this._es.onopen = () => {\n this.onStatus?.(\"live\");\n };\n\n this._es.onmessage = (e) => {\n try {\n const msg = JSON.parse(e.data as string) as {\n table_name: string;\n received_timestamp: string;\n data: T;\n };\n const event: StreamEvent<T> = {\n table: msg.table_name,\n timestamp: msg.received_timestamp,\n data: msg.data,\n };\n this.onEvent?.(event);\n } catch {\n console.warn(\"[wavehouse] SSE received malformed message:\", e.data);\n // ignore malformed messages\n }\n };\n\n this._es.onerror = () => {\n if (this._es?.readyState === EventSource.CONNECTING) {\n this.onStatus?.(\"reconnecting\");\n } else if (this._es?.readyState === EventSource.CLOSED) {\n this.onStatus?.(\"closed\");\n } else if (this._es?.readyState === EventSource.OPEN) {\n this.onStatus?.(\"live\");\n } else {\n this.onError?.({\n status: 0,\n code: \"SSE_ERROR\",\n message: \"SSE connection error\",\n retryable: true,\n });\n }\n };\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Result } from \"./types.js\";\n\n/** Namespace for the SDK's content-free server-online check. */\nexport class SysNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /**\n * Liveness ping — resolves with no error when the server is reachable and\n * past boot. Hits the public, content-free `/v1/health` route (200/503, no\n * body), kept intentionally distinct from the `/livez` Kubernetes probe so\n * it stays reachable even in deployments that filter probe paths at the\n * reverse proxy. Use it to check a server is online before sending data, or\n * to pick among servers in a distributed setup.\n */\n async health(opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<void>(this._ctx, {\n method: \"GET\",\n path: \"/v1/health\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok<void>(undefined);\n }\n}\n","import type { QueryFilter, Result, StreamEvent, StreamSubscriber } from \"../types.js\";\nimport type { StreamController } from \"./controller.js\";\n\n/**\n * Stream-first live query orchestrator.\n *\n * 1. Opens a live stream immediately (buffers events).\n * 2. Fetches historical data.\n * 3. Calls `subscriber.initial(result)` with the historical snapshot.\n * 4. Deduplicates buffered events against the fetch result.\n * 5. Flushes remaining buffered events through `subscriber.next()`.\n * 6. Resumes live: pipes stream events directly to `subscriber.next()`.\n */\nexport class LiveQuery<T = Record<string, unknown>> {\n private _stream: StreamController<T>;\n private _subscriber: StreamSubscriber<T>;\n private _buffer: StreamEvent<T>[] = [];\n private _buffering = true;\n private _unsubStream: (() => void) | null = null;\n private _closed = false;\n\n constructor(\n stream: StreamController<T>,\n fetchFn: () => Promise<Result<T[]>>,\n subscriber: StreamSubscriber<T>,\n _filters: QueryFilter[],\n ) {\n this._stream = stream;\n this._subscriber = subscriber;\n\n // Step 1: Subscribe to live events and buffer them.\n this._unsubStream = stream.subscribe({\n next: (event) => {\n if (this._closed) return;\n if (this._buffering) {\n this._buffer.push(event);\n } else {\n subscriber.next(event);\n }\n },\n status: (s) => subscriber.status?.(s),\n error: (e) => subscriber.error?.(e),\n });\n\n // Step 2-5: Fetch historical and flush.\n this._runBackfill(fetchFn);\n }\n\n private async _runBackfill(fetchFn: () => Promise<Result<T[]>>): Promise<void> {\n try {\n const result = await fetchFn();\n\n if (this._closed) return;\n\n // Step 3: Call initial() with the historical snapshot.\n this._subscriber.initial?.(result);\n\n if (result.error) {\n this._buffering = false;\n return;\n }\n\n // Step 4: Deduplicate buffered events against fetched rows.\n // Use received_timestamp as the dedup boundary: only flush events\n // that are newer than the latest row in the fetch result.\n const rows = result.data;\n let lastTimestamp: string | undefined;\n if (rows.length > 0) {\n const lastRow = rows[rows.length - 1] as Record<string, unknown>;\n lastTimestamp = lastRow?.received_timestamp as string | undefined;\n }\n\n // Step 5: Flush buffered events that are newer than the fetch.\n this._buffering = false;\n for (const event of this._buffer) {\n if (this._closed) break;\n if (lastTimestamp && event.timestamp <= lastTimestamp) {\n continue; // already covered by the fetch\n }\n this._subscriber.next(event);\n }\n this._buffer = [];\n } catch {\n // Fetch failed — stop buffering and resume live only.\n this._buffering = false;\n this._buffer = [];\n }\n }\n\n /** Close the live query and the underlying stream. */\n close(): void {\n this._closed = true;\n this._buffering = false;\n this._buffer = [];\n this._unsubStream?.();\n this._stream.close();\n }\n}\n","import { err, okPage } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { StreamTransport } from \"./stream/controller.js\";\nimport { StreamController } from \"./stream/controller.js\";\nimport { LiveQuery } from \"./stream/live-query.js\";\nimport type {\n Aggregation,\n FetchOptions,\n FilterOp,\n HttpContext,\n OrderClause,\n QueryFilter,\n Result,\n StreamOptions,\n StreamSubscriber,\n StructuredQuery,\n TimeRange,\n} from \"./types.js\";\n\n/** SDK operator → backend operator mapping. */\nconst OP_MAP: Record<FilterOp, string> = {\n \"=\": \"eq\",\n \"!=\": \"neq\",\n \">\": \"gt\",\n \">=\": \"gte\",\n \"<\": \"lt\",\n \"<=\": \"lte\",\n in: \"in\",\n like: \"like\",\n not_like: \"not_like\",\n};\n\ninterface QueryState {\n table: string;\n columns: string[];\n aggregations: Aggregation[];\n filters: QueryFilter[];\n groupBy: string[];\n orderBy: OrderClause[];\n limit?: number;\n timeRange?: TimeRange;\n cacheTTL?: number;\n}\n\ntype CreateStreamFn<Row> = (table: string, opts?: StreamOptions) => StreamController<Row>;\n\n/**\n * Immutable, PromiseLike query builder.\n * Every chain method returns a new instance. `await builder` auto-executes `.fetch()`.\n */\nexport class QueryBuilder<Row = Record<string, unknown>> implements PromiseLike<Result<Row[]>> {\n /** @internal */\n private readonly _state: Readonly<QueryState>;\n /** @internal */\n private readonly _ctx: HttpContext;\n /** @internal */\n private readonly _createStream: CreateStreamFn<Row>;\n\n constructor(ctx: HttpContext, state: QueryState, createStream: CreateStreamFn<Row>) {\n this._ctx = ctx;\n this._state = Object.freeze({ ...state });\n this._createStream = createStream;\n }\n\n // --- Builder methods (each returns a new QueryBuilder) ---\n\n select(...columns: string[]): QueryBuilder<Row> {\n return this._clone({ columns: [...this._state.columns, ...columns] });\n }\n\n where(column: string, op: FilterOp, value: unknown): QueryBuilder<Row> {\n const filter: QueryFilter = { column, op: OP_MAP[op], value };\n return this._clone({ filters: [...this._state.filters, filter] });\n }\n\n count(column = \"*\", alias = \"count\"): QueryBuilder<Row> {\n return this._addAgg(\"count\", column, alias);\n }\n\n sum(column: string, alias = `sum_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"sum\", column, alias);\n }\n\n avg(column: string, alias = `avg_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"avg\", column, alias);\n }\n\n min(column: string, alias = `min_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"min\", column, alias);\n }\n\n max(column: string, alias = `max_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"max\", column, alias);\n }\n\n countDistinct(column: string, alias = `count_distinct_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"countDistinct\", column, alias);\n }\n\n aggregate(fn: string, column: string, alias: string): QueryBuilder<Row> {\n return this._addAgg(fn, column, alias);\n }\n\n groupBy(...columns: string[]): QueryBuilder<Row> {\n return this._clone({ groupBy: [...this._state.groupBy, ...columns] });\n }\n\n orderBy(column: string, dir: \"asc\" | \"desc\" = \"asc\"): QueryBuilder<Row> {\n return this._clone({ orderBy: [...this._state.orderBy, { column, dir }] });\n }\n\n limit(n: number): QueryBuilder<Row> {\n return this._clone({ limit: n });\n }\n\n timeRange(column: string, since: string, until?: string): QueryBuilder<Row> {\n return this._clone({ timeRange: { column, since, until } });\n }\n\n cacheTTL(seconds: number): QueryBuilder<Row> {\n return this._clone({ cacheTTL: seconds });\n }\n\n // --- Execution ---\n\n /** Default row limit when none is specified. Matches backend DefaultMaxRows. */\n static readonly DEFAULT_LIMIT = 1000;\n\n async fetch(opts?: FetchOptions): Promise<Result<Row[]>> {\n const effectiveLimit = opts?.limit ?? this._state.limit ?? QueryBuilder.DEFAULT_LIMIT;\n const ast = this._buildAST(effectiveLimit);\n\n const { data, error } = await request<Row[]>(this._ctx, {\n method: \"POST\",\n path: `/v1/query?table=${encodeURIComponent(this._state.table)}`,\n body: ast,\n signal: opts?.signal,\n });\n\n if (error) return err(error);\n\n const rows = data!;\n const hasMore = effectiveLimit != null && rows.length >= effectiveLimit;\n\n // next() needs an order column for its cursor; with no .orderBy() we still\n // report hasMore honestly from the row count but can't offer a next().\n if (hasMore && this._state.orderBy.length > 0) {\n const nextFn = () => this._fetchNext(rows, effectiveLimit!, opts);\n return okPage(rows, true, nextFn);\n }\n\n return okPage(rows, hasMore);\n }\n\n stream(opts?: StreamOptions): StreamController<Row> {\n const raw = this._createStream(this._state.table, opts);\n const filters = this._state.filters;\n const columns = this._state.columns;\n\n // If no filters or column projection, return the raw stream.\n if (filters.length === 0 && columns.length === 0) {\n return raw;\n }\n\n // Wrap with a filtering transport that applies AST predicates client-side.\n return new FilteredStreamController<Row>(raw, filters, columns);\n }\n\n /**\n * Start a live query: fetches historical data, then streams live updates.\n *\n * The subscriber's `initial()` is called once with the fetch result, then\n * `next()` fires for each live event. Events that arrived during the fetch\n * are deduplicated and flushed automatically.\n *\n * Returns a LiveQuery handle with a `.close()` method.\n */\n liveQuery(subscriber: StreamSubscriber<Row>, opts?: StreamOptions): LiveQuery<Row> {\n const stream = this.stream(opts);\n const fetchFn = () => this.fetch();\n return new LiveQuery<Row>(stream, fetchFn, subscriber, this._state.filters);\n }\n\n // --- PromiseLike implementation ---\n\n then<TResult1 = Result<Row[]>, TResult2 = never>(\n onfulfilled?: ((value: Result<Row[]>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.fetch().then(onfulfilled, onrejected);\n }\n\n // --- Private helpers ---\n\n private _clone(overrides: Partial<QueryState>): QueryBuilder<Row> {\n return new QueryBuilder(this._ctx, { ...this._state, ...overrides }, this._createStream);\n }\n\n private _addAgg(fn: string, column: string, alias: string): QueryBuilder<Row> {\n const agg: Aggregation = { fn, column, alias };\n return this._clone({ aggregations: [...this._state.aggregations, agg] });\n }\n\n private _buildAST(effectiveLimit?: number): StructuredQuery {\n const ast: StructuredQuery = {};\n if (this._state.columns.length > 0) ast.columns = this._state.columns;\n if (this._state.aggregations.length > 0) ast.aggregations = this._state.aggregations;\n if (this._state.filters.length > 0) ast.filters = this._state.filters;\n if (this._state.groupBy.length > 0) ast.group_by = this._state.groupBy;\n if (this._state.orderBy.length > 0) ast.order_by = this._state.orderBy;\n if (effectiveLimit != null) ast.limit = effectiveLimit;\n if (this._state.timeRange) ast.time_range = this._state.timeRange;\n return ast;\n }\n\n private async _fetchNext(\n prevRows: Row[],\n _limit: number,\n opts?: FetchOptions,\n ): Promise<Result<Row[]>> {\n // No explicit order → no keyset cursor to build; nothing to page by.\n const cursor = this._state.orderBy[0];\n if (cursor == null) return okPage([] as unknown as Row[], false);\n const { column: orderCol, dir: orderDir } = cursor;\n\n const lastRow = prevRows[prevRows.length - 1] as Record<string, unknown>;\n const lastValue = lastRow?.[orderCol];\n\n if (lastValue === undefined) return okPage([] as unknown as Row[], false);\n\n const cursorOp = orderDir === \"desc\" ? \"lt\" : \"gt\";\n const cursorFilter: QueryFilter = { column: orderCol, op: cursorOp, value: lastValue };\n const nextBuilder = this._clone({\n filters: [...this._state.filters, cursorFilter],\n orderBy: this._state.orderBy,\n });\n\n return nextBuilder.fetch(opts);\n }\n}\n\n// ============================================================================\n// Client-side stream filtering\n// ============================================================================\n\n/**\n * Wraps a StreamController, applying client-side filters and column projection\n * before delivering events to subscribers.\n *\n * Lifecycle: by the time we reach this constructor, `inner` has already been\n * built (and is opening its own SSE connection). The outer transport's\n * `connect()` doesn't open a new connection — it bridges `inner`'s events\n * through a filter into the outer subscriber set. On `disconnect()`, closing\n * `inner` is what actually tears down the SSE socket; the subscription we\n * register on `inner` is left to be garbage-collected with it, which is why\n * we don't bother saving the unsubscribe handle.\n * @internal\n */\nclass FilteredStreamController<T = Record<string, unknown>> extends StreamController<T> {\n constructor(inner: StreamController<T>, filters: QueryFilter[], columns: string[]) {\n const transport: StreamTransport<T> = {\n onEvent: null,\n onStatus: null,\n onError: null,\n connect() {\n inner.subscribe({\n next: (event) => {\n if (!matchesFilters(event.data as Record<string, unknown>, filters)) {\n return;\n }\n const projected =\n columns.length > 0\n ? {\n ...event,\n data: projectColumns(event.data as Record<string, unknown>, columns) as T,\n }\n : event;\n this.onEvent?.(projected);\n },\n status: (s) => this.onStatus?.(s),\n error: (e) => this.onError?.(e),\n });\n },\n disconnect() {\n inner.close();\n },\n };\n super(transport);\n }\n}\n\n/** @internal Evaluate all filters against a data row. All must pass (AND). */\nfunction matchesFilters(row: Record<string, unknown>, filters: QueryFilter[]): boolean {\n for (const f of filters) {\n const val = row[f.column];\n if (!evaluateFilter(val, f.op, f.value)) return false;\n }\n return true;\n}\n\n/** @internal Evaluate a single filter predicate. */\nfunction evaluateFilter(actual: unknown, op: string, expected: unknown): boolean {\n switch (op) {\n case \"eq\":\n return actual === expected;\n case \"neq\":\n return actual !== expected;\n case \"gt\":\n return compareOrdered(actual, expected, (a, b) => a > b);\n case \"gte\":\n return compareOrdered(actual, expected, (a, b) => a >= b);\n case \"lt\":\n return compareOrdered(actual, expected, (a, b) => a < b);\n case \"lte\":\n return compareOrdered(actual, expected, (a, b) => a <= b);\n case \"in\":\n return Array.isArray(expected) && expected.includes(actual);\n case \"like\": {\n if (typeof actual !== \"string\" || typeof expected !== \"string\") return false;\n // Convert SQL LIKE pattern to regex: % → .*, _ → .\n const escaped = expected.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = escaped.replace(/%/g, \".*\").replace(/_/g, \".\");\n return new RegExp(`^${pattern}$`, \"i\").test(actual);\n }\n case \"not_like\": {\n if (typeof actual !== \"string\" || typeof expected !== \"string\") return false;\n const escaped = expected.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = escaped.replace(/%/g, \".*\").replace(/_/g, \".\");\n return !new RegExp(`^${pattern}$`, \"i\").test(actual);\n }\n default:\n return true; // unknown op — pass through\n }\n}\n\n/**\n * @internal Apply an ordered comparison only when both sides are the same\n * comparable primitive (number-vs-number or string-vs-string — strings are\n * lexicographic, which is correct for ISO-8601 timestamps). Mismatched or\n * unsupported types return false instead of relying on JS coercion.\n */\nfunction compareOrdered(\n actual: unknown,\n expected: unknown,\n cmp: (a: number, b: number) => boolean,\n): boolean {\n if (typeof actual === \"number\" && typeof expected === \"number\") {\n return cmp(actual, expected);\n }\n if (typeof actual === \"string\" && typeof expected === \"string\") {\n // `>`/`<` on strings is lexicographic; reuse the same comparator by\n // casting through `as unknown as number` — the runtime operator works\n // identically on strings.\n return cmp(actual as unknown as number, expected as unknown as number);\n }\n return false;\n}\n\n/** @internal Project a row to only the specified columns. */\nfunction projectColumns(row: Record<string, unknown>, columns: string[]): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const col of columns) {\n if (col in row) result[col] = row[col];\n }\n return result;\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport { QueryBuilder } from \"./query-builder.js\";\nimport type { StreamController } from \"./stream/controller.js\";\nimport type {\n FetchOptions,\n HttpContext,\n InsertResult,\n Result,\n StreamOptions,\n TableSchema,\n} from \"./types.js\";\n\ntype CreateStreamFn<Row> = (table: string, opts?: StreamOptions) => StreamController<Row>;\n\n/**\n * Reference to a table. NOT thenable — safe to pass around without triggering requests.\n * Use `.fetch()`, `.select()`, `.insert()`, `.schema()`, or `.stream()` to act on it.\n */\nexport class TableRef<Row = Record<string, unknown>> {\n private readonly _ctx: HttpContext;\n private readonly _table: string;\n private readonly _createStream: CreateStreamFn<Row>;\n\n constructor(ctx: HttpContext, table: string, createStream: CreateStreamFn<Row>) {\n this._ctx = ctx;\n this._table = table;\n this._createStream = createStream;\n }\n\n /** SELECT * shortcut — fetches rows with optional pagination. */\n async fetch(opts?: FetchOptions): Promise<Result<Row[]>> {\n return this.select()\n .limit(opts?.limit ?? 1000)\n .fetch(opts);\n }\n\n /** Start building a typed query. Returns an immutable, PromiseLike QueryBuilder. */\n select(...columns: string[]): QueryBuilder<Row> {\n return new QueryBuilder<Row>(\n this._ctx,\n {\n table: this._table,\n columns,\n aggregations: [],\n filters: [],\n groupBy: [],\n orderBy: [],\n },\n this._createStream,\n );\n }\n\n /** Insert one or more rows into this table. */\n async insert(\n data: Partial<Row> | Partial<Row>[],\n opts?: { signal?: AbortSignal },\n ): Promise<Result<InsertResult>> {\n if (Array.isArray(data)) {\n // TODO: Switch to NDJSON\n // FAST: Fire all HTTP requests concurrently instead of waiting for each one\n const promises = data.map((row) =>\n request<{ ok?: boolean; duplicate?: boolean }>(this._ctx, {\n method: \"POST\",\n path: `/v1/ingest?table=${encodeURIComponent(this._table)}`,\n body: row,\n signal: opts?.signal,\n }),\n );\n\n // TODO: with NDJSON/array version, need to rework how to show errors if only some/one fail\n const results = await Promise.all(promises);\n\n // Check if any of the concurrent requests failed\n for (const res of results) {\n if (res.error) return err(res.error);\n }\n return ok({ ok: true });\n }\n\n const { data: res, error } = await request<{ ok?: boolean; duplicate?: boolean }>(this._ctx, {\n method: \"POST\",\n path: `/v1/ingest?table=${encodeURIComponent(this._table)}`,\n body: data,\n signal: opts?.signal,\n });\n\n if (error) return err(error);\n const result: InsertResult = { ok: res?.ok ?? true };\n if (res?.duplicate != null) result.duplicate = res.duplicate;\n return ok(result);\n }\n\n /** Fetch the schema for this table. */\n async schema(opts?: { signal?: AbortSignal }): Promise<Result<TableSchema>> {\n const { data, error } = await request<TableSchema>(this._ctx, {\n method: \"GET\",\n path: `/v1/schema?table=${encodeURIComponent(this._table)}`,\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Subscribe to live events for this table. */\n stream(opts?: StreamOptions): StreamController<Row> {\n return this._createStream(this._table, opts);\n }\n}\n","import { DLQNamespace } from \"./dlq.js\";\nimport { PipeRef, PipesNamespace } from \"./pipes.js\";\nimport { PolicyNamespace } from \"./policy.js\";\nimport { SchemaNamespace } from \"./schema.js\";\nimport { sql } from \"./sql.js\";\nimport { StreamController } from \"./stream/controller.js\";\nimport { SSETransport } from \"./stream/sse.js\";\nimport { SysNamespace } from \"./sys.js\";\nimport { TableRef } from \"./table.js\";\nimport type { ClientConfig, Database, HttpContext, Result, StreamOptions } from \"./types.js\";\n\ntype TableName<DB> = DB extends Database ? Extract<keyof DB, string> : string;\ntype RowType<DB, T extends string> = DB extends Database\n ? T extends keyof DB\n ? DB[T]\n : Record<string, unknown>\n : Record<string, unknown>;\n\nexport class WaveHouseClient<DB extends Database = Database> {\n /** @internal */\n readonly _ctx: HttpContext;\n\n /** Schema introspection namespace. */\n readonly schema: SchemaNamespace;\n /** Access control policy namespace (admin). */\n readonly policy: PolicyNamespace;\n /** Dead Letter Queue namespace. */\n readonly dlq: DLQNamespace;\n /** System health/readiness namespace. */\n readonly sys: SysNamespace;\n /** Named query pipes admin namespace. */\n readonly pipes: PipesNamespace;\n\n constructor(config: ClientConfig<DB>) {\n this._ctx = {\n baseURL: config.baseURL.replace(/\\/+$/, \"\"),\n auth: config.auth,\n options: {\n maxRetries: config.options?.maxRetries ?? 2,\n },\n };\n\n this.schema = new SchemaNamespace(this._ctx);\n this.policy = new PolicyNamespace(this._ctx);\n this.dlq = new DLQNamespace(this._ctx, (table, opts) => this._createStream(table, opts));\n this.sys = new SysNamespace(this._ctx);\n this.pipes = new PipesNamespace(this._ctx);\n }\n\n /** Get a table reference for building queries, inserts, and streams. */\n from<T extends TableName<DB>>(table: T): TableRef<RowType<DB, T>> {\n return new TableRef<RowType<DB, T>>(this._ctx, table, (t, opts) =>\n this._createStream<RowType<DB, T>>(t, opts),\n );\n }\n\n /** Get a reference to a named query pipe. PromiseLike — `await` it to execute. */\n pipe<Row = Record<string, unknown>>(\n name: string,\n params?: Record<string, unknown>,\n ): PipeRef<Row> {\n return new PipeRef<Row>(this._ctx, name, params, (t, opts) => this._createStream<Row>(t, opts));\n }\n\n /**\n * Execute a raw SQL query against ClickHouse. Requires the admin role (the\n * configured `admin_role`, `\"admin\"` by default; there is no separate\n * `service` role). The endpoint proxies straight to ClickHouse's HTTP\n * interface so any ClickHouse-accepted SQL works; positional `?` param\n * binding is NOT supported — inline literals or use the structured query\n * builder for safe binding. See sql.ts for details.\n */\n sql<Row = Record<string, unknown>>(\n query: string,\n opts?: { signal?: AbortSignal },\n ): Promise<Result<Row[]>> {\n // Migration guard: the second argument used to be a positional-`?`\n // params array. TS callers get a compile-time error from the type\n // signature, but JS callers (or `any`-typed callsites) would silently\n // pass an array as `opts` and only discover the break via downstream\n // SQL errors. Throw a clear runtime error pointing at the migration.\n if (Array.isArray(opts)) {\n throw new Error(\n \"[WaveHouse SDK] client.sql(sql, params) was removed. The /v1/admin/query endpoint does not accept positional `?` params. Inline literals into the SQL, or use the structured query builder (wh.from(table)…) for safe binding from user input.\",\n );\n }\n return sql<Row>(this._ctx, query, opts);\n }\n\n /** @internal Create a stream for the given table. */\n private _createStream<T = Record<string, unknown>>(\n table: string,\n opts?: StreamOptions,\n ): StreamController<T> {\n if (typeof EventSource === \"undefined\") {\n // TODO: fallback method? polling?\n throw new Error(\n \"[WaveHouse SDK] Native EventSource is not available in this environment. \" +\n \"Please provide a global polyfill (e.g., `globalThis.EventSource = require('eventsource')`).\",\n );\n }\n\n const transport = new SSETransport<T>({\n baseURL: this._ctx.baseURL,\n table,\n since: opts?.since,\n auth: this._ctx.auth,\n });\n const controller = new StreamController<T>(transport);\n if (opts?.signal) controller.attachSignal(opts.signal);\n return controller;\n }\n}\n\n/** Create a new WaveHouse client instance. */\nexport function createClient<DB extends Database = Database>(\n config: ClientConfig<DB>,\n): WaveHouseClient<DB> {\n return new WaveHouseClient(config);\n}\n"],"mappings":"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","names":["err","res"]}
package/dist/index.js CHANGED
@@ -745,11 +745,11 @@ var QueryBuilder = class _QueryBuilder {
745
745
  if (error) return err(error);
746
746
  const rows = data;
747
747
  const hasMore = effectiveLimit != null && rows.length >= effectiveLimit;
748
- if (hasMore) {
748
+ if (hasMore && this._state.orderBy.length > 0) {
749
749
  const nextFn = () => this._fetchNext(rows, effectiveLimit, opts);
750
750
  return okPage(rows, true, nextFn);
751
751
  }
752
- return okPage(rows, false);
752
+ return okPage(rows, hasMore);
753
753
  }
754
754
  stream(opts) {
755
755
  const raw = this._createStream(this._state.table, opts);
@@ -792,27 +792,23 @@ var QueryBuilder = class _QueryBuilder {
792
792
  if (this._state.aggregations.length > 0) ast.aggregations = this._state.aggregations;
793
793
  if (this._state.filters.length > 0) ast.filters = this._state.filters;
794
794
  if (this._state.groupBy.length > 0) ast.group_by = this._state.groupBy;
795
- if (this._state.orderBy.length > 0) {
796
- ast.order_by = this._state.orderBy;
797
- } else if (effectiveLimit != null && this._state.aggregations.length === 0) {
798
- ast.order_by = [{ column: "received_timestamp", dir: "desc" }];
799
- }
795
+ if (this._state.orderBy.length > 0) ast.order_by = this._state.orderBy;
800
796
  if (effectiveLimit != null) ast.limit = effectiveLimit;
801
797
  if (this._state.timeRange) ast.time_range = this._state.timeRange;
802
798
  return ast;
803
799
  }
804
800
  async _fetchNext(prevRows, _limit, opts) {
805
- const orderCol = this._state.orderBy[0]?.column ?? "received_timestamp";
806
- const orderDir = this._state.orderBy[0]?.dir ?? "desc";
801
+ const cursor = this._state.orderBy[0];
802
+ if (cursor == null) return okPage([], false);
803
+ const { column: orderCol, dir: orderDir } = cursor;
807
804
  const lastRow = prevRows[prevRows.length - 1];
808
805
  const lastValue = lastRow?.[orderCol];
809
806
  if (lastValue === void 0) return okPage([], false);
810
807
  const cursorOp = orderDir === "desc" ? "lt" : "gt";
811
808
  const cursorFilter = { column: orderCol, op: cursorOp, value: lastValue };
812
- const orderBy = this._state.orderBy.length > 0 ? this._state.orderBy : [{ column: orderCol, dir: orderDir }];
813
809
  const nextBuilder = this._clone({
814
810
  filters: [...this._state.filters, cursorFilter],
815
- orderBy
811
+ orderBy: this._state.orderBy
816
812
  });
817
813
  return nextBuilder.fetch(opts);
818
814
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/dlq.ts","../src/pipes.ts","../src/policy.ts","../src/schema.ts","../src/sql.ts","../src/stream/controller.ts","../src/stream/sse.ts","../src/sys.ts","../src/stream/live-query.ts","../src/query-builder.ts","../src/table.ts","../src/client.ts"],"sourcesContent":["import type { Result, WaveHouseError } from \"./types.js\";\n\n/** Create a WaveHouseError from an HTTP response. */\nexport async function parseErrorResponse(res: Response): Promise<WaveHouseError> {\n let body: Record<string, unknown> | undefined;\n try {\n body = (await res.json()) as Record<string, unknown>;\n } catch {\n body = undefined;\n }\n\n const message =\n typeof body?.error === \"string\"\n ? body.error\n : typeof body?.message === \"string\"\n ? body.message\n : res.statusText;\n\n const retryable = res.status === 503 || res.status >= 500;\n return {\n status: res.status,\n code: `HTTP_${res.status}`,\n message,\n details: body,\n retryable,\n };\n}\n\n/** Create a WaveHouseError from a network/fetch error. */\nexport function networkError(cause: unknown): WaveHouseError {\n const message = cause instanceof Error ? cause.message : String(cause);\n return {\n status: 0,\n code: \"NETWORK_ERROR\",\n message,\n retryable: true,\n };\n}\n\n/** Wrap a successful value in a Result. */\nexport function ok<T>(data: T): Result<T> {\n return { ok: true, data, error: null };\n}\n\n/** Wrap a successful paginated value in a Result. */\nexport function okPage<T>(data: T, hasMore: boolean, next?: () => Promise<Result<T>>): Result<T> {\n return { ok: true, data, error: null, hasMore, next };\n}\n\n/** Wrap an error in a Result. */\nexport function err<T = unknown>(error: WaveHouseError): Result<T> {\n return { ok: false, data: null, error };\n}\n","import { networkError, parseErrorResponse } from \"./errors.js\";\nimport type { HttpContext, WaveHouseError } from \"./types.js\";\n\ninterface RequestOptions {\n method: string;\n path: string;\n body?: unknown;\n params?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/** @internal */\nexport interface HttpResult<T> {\n data: T | null;\n error: WaveHouseError | null;\n headers: Headers;\n}\n\n/**\n * Internal fetch wrapper with auth injection, retry, backoff, and Retry-After.\n * @internal\n */\nexport async function request<T>(ctx: HttpContext, opts: RequestOptions): Promise<HttpResult<T>> {\n const url = buildURL(ctx.baseURL, opts.path, opts.params);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n };\n\n if (ctx.auth) {\n const token = await ctx.auth();\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n }\n\n let lastError: WaveHouseError | null = null;\n const maxAttempts = ctx.options.maxRetries + 1;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n const res = await fetch(url, {\n method: opts.method,\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n signal: opts.signal,\n });\n\n if (res.ok) {\n const text = await res.text();\n const data = text ? (JSON.parse(text) as T) : (undefined as T);\n return { data, error: null, headers: res.headers };\n }\n\n const error = await parseErrorResponse(res);\n\n // 503 with Retry-After: wait the specified duration\n if (res.status === 503) {\n const retryAfter = res.headers.get(\"Retry-After\");\n if (retryAfter && attempt < maxAttempts - 1) {\n const delay = parseInt(retryAfter, 10) * 1000 || 30_000;\n await sleep(delay, opts.signal);\n lastError = error;\n continue;\n }\n }\n\n // Retryable server errors (5xx)\n if (error.retryable && attempt < maxAttempts - 1) {\n await sleep(backoff(attempt), opts.signal);\n lastError = error;\n continue;\n }\n\n return { data: null, error, headers: res.headers };\n } catch (e) {\n // AbortError — return immediately, no retry\n if (e instanceof DOMException && e.name === \"AbortError\") {\n return {\n data: null,\n error: { status: 0, code: \"ABORTED\", message: \"Request aborted\", retryable: false },\n headers: new Headers(),\n };\n }\n\n lastError = networkError(e);\n if (attempt < maxAttempts - 1) {\n await sleep(backoff(attempt), opts.signal);\n }\n }\n }\n\n return { data: null, error: lastError!, headers: new Headers() };\n}\n\nfunction buildURL(base: string, path: string, params?: Record<string, string>): string {\n const url = new URL(path, base.endsWith(\"/\") ? base : `${base}/`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n url.searchParams.set(k, v);\n }\n }\n return url.toString();\n}\n\nfunction backoff(attempt: number): number {\n return Math.min(1000 * 2 ** attempt, 30_000);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n return;\n }\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timer);\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n },\n { once: true },\n );\n });\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { StreamController } from \"./stream/controller.js\";\nimport type { DLQStats, HttpContext, Result, StreamOptions } from \"./types.js\";\n\ntype CreateStreamFn = (table: string, opts?: StreamOptions) => StreamController;\n\n/** Namespace for Dead Letter Queue operations. */\nexport class DLQNamespace {\n private readonly _ctx: HttpContext;\n private readonly _createStream: CreateStreamFn;\n\n constructor(ctx: HttpContext, createStream: CreateStreamFn) {\n this._ctx = ctx;\n this._createStream = createStream;\n }\n\n /** Get DLQ statistics (message counts per table). */\n async list(opts?: { signal?: AbortSignal }): Promise<Result<DLQStats>> {\n const { data, error } = await request<DLQStats>(this._ctx, {\n method: \"GET\",\n path: \"/v1/dlq/stats\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Get DLQ stats filtered by table name. */\n async table(name: string, opts?: { signal?: AbortSignal }): Promise<Result<DLQStats>> {\n const { data, error } = await request<DLQStats>(this._ctx, {\n method: \"GET\",\n path: \"/v1/dlq/stats\",\n params: { table: name },\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Subscribe to live DLQ events. */\n stream(opts?: StreamOptions): StreamController {\n return this._createStream(\"dlq\", opts);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { StreamController } from \"./stream/controller.js\";\nimport type { FetchOptions, HttpContext, Pipe, Result, StreamOptions } from \"./types.js\";\n\ntype CreateStreamFn<Row> = (table: string, opts?: StreamOptions) => StreamController<Row>;\n\n/** Reference to a named query pipe — PromiseLike for convenient `await`. */\nexport class PipeRef<Row = Record<string, unknown>> implements PromiseLike<Result<Row[]>> {\n private readonly _ctx: HttpContext;\n private readonly _name: string;\n private readonly _params?: Record<string, unknown>;\n private readonly _createStream: CreateStreamFn<Row>;\n\n constructor(\n ctx: HttpContext,\n name: string,\n params: Record<string, unknown> | undefined,\n createStream: CreateStreamFn<Row>,\n ) {\n this._ctx = ctx;\n this._name = name;\n this._params = params;\n this._createStream = createStream;\n }\n\n /** Execute the pipe and return results. */\n async fetch(opts?: FetchOptions): Promise<Result<Row[]>> {\n const { data, error } = await request<Row[]>(this._ctx, {\n method: \"POST\",\n path: `/v1/pipes/${encodeURIComponent(this._name)}`,\n body: this._params ?? {},\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Subscribe to live events from the pipe's underlying query. */\n stream(opts?: StreamOptions): StreamController<Row> {\n return this._createStream(this._name, opts);\n }\n\n then<TResult1 = Result<Row[]>, TResult2 = never>(\n onfulfilled?: ((value: Result<Row[]>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.fetch().then(onfulfilled, onrejected);\n }\n}\n\n/** Admin namespace for managing named query pipes. */\nexport class PipesNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /** List all registered pipes. */\n async list(opts?: { signal?: AbortSignal }): Promise<Result<Pipe[]>> {\n const { data, error } = await request<Pipe[]>(this._ctx, {\n method: \"GET\",\n path: \"/v1/admin/pipes\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Get a single pipe definition by name. */\n async get(name: string, opts?: { signal?: AbortSignal }): Promise<Result<Pipe>> {\n const { data, error } = await request<Pipe>(this._ctx, {\n method: \"GET\",\n path: `/v1/admin/pipes/${encodeURIComponent(name)}`,\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Create or update a pipe. */\n async set(\n name: string,\n def: Omit<Pipe, \"name\">,\n opts?: { signal?: AbortSignal },\n ): Promise<Result<void>> {\n const { error } = await request<{ ok: boolean }>(this._ctx, {\n method: \"PUT\",\n path: `/v1/admin/pipes/${encodeURIComponent(name)}`,\n body: def,\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n\n /** Delete a pipe by name. */\n async delete(name: string, opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<{ ok: boolean }>(this._ctx, {\n method: \"DELETE\",\n path: `/v1/admin/pipes/${encodeURIComponent(name)}`,\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Policy, Result, ValidationResult } from \"./types.js\";\n\n/** Namespace for access control policy management. Requires the admin role (the configured `admin_role`, `\"admin\"` by default). */\nexport class PolicyNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /** Get the current access control policy. */\n async get(opts?: { signal?: AbortSignal }): Promise<Result<Policy>> {\n const { data, error } = await request<Policy>(this._ctx, {\n method: \"GET\",\n path: \"/v1/admin/policy\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Replace the entire access control policy. */\n async set(policy: Policy, opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<{ ok: boolean }>(this._ctx, {\n method: \"PUT\",\n path: \"/v1/admin/policy\",\n body: policy,\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n\n /** Validate a policy without applying it (dry run). */\n async validate(\n policy: Policy,\n opts?: { signal?: AbortSignal },\n ): Promise<Result<ValidationResult>> {\n const { data, error } = await request<ValidationResult>(this._ctx, {\n method: \"POST\",\n path: \"/v1/admin/policy/validate\",\n body: policy,\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Result, Schemas } from \"./types.js\";\n\n/** Namespace for schema introspection. */\nexport class SchemaNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /** List all table schemas discovered from ClickHouse. */\n async list(opts?: { signal?: AbortSignal }): Promise<Result<Schemas>> {\n // The backend returns TableSchema[] — transform to Record<string, TableSchema>.\n const { data, error } = await request<unknown>(this._ctx, {\n method: \"GET\",\n path: \"/v1/schema\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n\n let schemas: Schemas;\n if (Array.isArray(data)) {\n schemas = {};\n for (const table of data) {\n if (table && typeof table === \"object\" && \"name\" in table) {\n schemas[(table as { name: string }).name] = table as Schemas[string];\n }\n }\n } else {\n schemas = data as Schemas;\n }\n return ok(schemas);\n }\n\n /** Force a schema refresh from ClickHouse system.columns. */\n async refresh(opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<Schemas>(this._ctx, {\n method: \"POST\",\n path: \"/v1/schema/refresh\",\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Result } from \"./types.js\";\n\n/**\n * Execute a raw SQL query against ClickHouse.\n *\n * Backed by `POST /v1/admin/query`, which requires the admin role — the same\n * gate as the rest of `/v1/admin/*`. Callers must hold a JWT whose role is the\n * configured `admin_role` (`\"admin\"` by default); there is no separate\n * `service` role. The JWT middleware always runs, so a request with no token\n * or an invalid one is denied, never granted. Non-admin use cases should use\n * the structured query builder (`wh.from(table)...`) instead.\n *\n * The server proxies the SQL string verbatim to ClickHouse's HTTP interface,\n * so any ClickHouse-accepted statement works — including multi-statement\n * input (`SELECT 1; TRUNCATE t`) and arbitrary DDL/DML/SYSTEM verbs.\n *\n * **JSON-row contract.** This helper returns `Result<Row[]>` and assumes the\n * response is the standard `FORMAT JSON` envelope (or an empty body for\n * no-result mutations — coerced to `[]`). Inline non-JSON `FORMAT` overrides\n * (`SELECT 1 FORMAT CSV` / `FORMAT TSV` / `FORMAT Pretty` / etc.) are NOT\n * compatible with `sql()` — the proxy passes the upstream Content-Type\n * through, and the SDK's JSON decoder throws on a non-JSON body, which the\n * retry layer surfaces as a `NETWORK_ERROR` result (not a structured\n * format-mismatch error). For CSV/TSV exports, hit `/v1/admin/query`\n * directly with `fetch()` and read the body as text.\n *\n * **No parameter binding.** Positional `?` substitution is not supported.\n * The SDK has no way to forward ClickHouse-style named params\n * (`WHERE id = {id:UInt32}` with `param_id=42` on the query string) —\n * the proxy doesn't forward arbitrary query-string params to ClickHouse\n * and the SDK doesn't expose a hook to add them. Inline literals into\n * the SQL string, or — for safe binding from user-supplied input — use\n * the structured query builder (`wh.from(...).select(...).where(...)`).\n */\nexport async function sql<Row = Record<string, unknown>>(\n ctx: HttpContext,\n query: string,\n opts?: { signal?: AbortSignal },\n): Promise<Result<Row[]>> {\n const { data, error } = await request<Row[]>(ctx, {\n method: \"POST\",\n path: \"/v1/admin/query\",\n body: { sql: query },\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n}\n","import type { StreamEvent, StreamStatus, StreamSubscriber, WaveHouseError } from \"../types.js\";\n\n/** @internal Transport abstraction for SSE backend. */\nexport interface StreamTransport<T = Record<string, unknown>> {\n connect(): void;\n disconnect(): void;\n onEvent: ((event: StreamEvent<T>) => void) | null;\n onStatus: ((status: StreamStatus) => void) | null;\n onError: ((error: WaveHouseError) => void) | null;\n}\n\n/**\n * Controls a live event stream. NOT thenable.\n * Use `.subscribe()` for callback-based consumption or `for await` for async iteration.\n */\nexport class StreamController<T = Record<string, unknown>> {\n private _transport: StreamTransport<T>;\n private _subscribers = new Set<StreamSubscriber<T>>();\n private _status: StreamStatus = \"connecting\";\n private _buffer: StreamEvent<T>[] = [];\n private _waiters: { resolve: (value: IteratorResult<StreamEvent<T>>) => void }[] = [];\n private _done = false;\n\n constructor(transport: StreamTransport<T>) {\n this._transport = transport;\n\n this._transport.onEvent = (event) => {\n for (const sub of this._subscribers) {\n sub.next(event);\n }\n // Async iterator support\n const waiter = this._waiters.shift();\n if (waiter) {\n waiter.resolve({ value: event, done: false });\n } else {\n this._buffer.push(event);\n }\n };\n\n this._transport.onStatus = (status) => {\n // Deduplicate: skip if status hasn't changed (e.g. transport fires\n // 'connecting' after StreamController already set it as the initial state).\n if (status === this._status) return;\n this._status = status;\n for (const sub of this._subscribers) {\n sub.status?.(status);\n }\n if (status === \"closed\") {\n this._done = true;\n for (const w of this._waiters) {\n w.resolve({ value: undefined as never, done: true });\n }\n this._waiters = [];\n }\n };\n\n this._transport.onError = (error) => {\n for (const sub of this._subscribers) {\n sub.error?.(error);\n }\n };\n\n this._transport.connect();\n }\n\n /** Current connection status. */\n get status(): StreamStatus {\n return this._status;\n }\n\n /**\n * Returns a promise that resolves when the stream status reaches `'live'`,\n * rejects immediately if the stream is already `'closed'`, or rejects after\n * `timeoutMs` milliseconds (default: 5 000) if it never connects.\n *\n * Safe to call before `.subscribe()` — does not trigger auto-close when\n * the internal waiter is removed.\n *\n * `@example`\n * const stream = client.from('events').stream();\n * const unsub = stream.subscribe({ next: (e) => console.log(e) });\n * await stream.connected(); // waits until the transport is live\n * await client.from('events').insert({ ... });\n */\n connected(timeoutMs = 5_000): Promise<void> {\n if (this._status === \"live\") return Promise.resolve();\n if (this._status === \"closed\") return Promise.reject(new Error(\"Stream is closed\"));\n if (this._done) return Promise.reject(new Error(\"Stream closed before connecting\"));\n\n return new Promise((resolve, reject) => {\n let settled = false;\n\n const timer = setTimeout(() => {\n if (settled) return;\n settled = true;\n this._subscribers.delete(watcher);\n reject(new Error(`Stream did not connect within ${timeoutMs}ms`));\n }, timeoutMs);\n\n // Use a private subscriber directly to avoid the auto-close side-effect\n // that the public subscribe() triggers when subscriber count drops to zero.\n const watcher: StreamSubscriber<T> = {\n next: () => {\n // no-op: we only care about status transitions here\n },\n status: (s) => {\n if (s === \"live\") {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n this._subscribers.delete(watcher);\n resolve();\n } else if (s === \"closed\") {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n this._subscribers.delete(watcher);\n reject(new Error(\"Stream closed before connecting\"));\n }\n },\n };\n\n this._subscribers.add(watcher);\n });\n }\n\n /** Subscribe to stream events via callbacks. Returns an unsubscribe function. */\n subscribe(subscriber: StreamSubscriber<T>): () => void {\n this._subscribers.add(subscriber);\n subscriber.status?.(this._status);\n\n return () => {\n this._subscribers.delete(subscriber);\n if (this._subscribers.size === 0 && this._waiters.length === 0) {\n this.close();\n }\n };\n }\n\n /** Attach an AbortSignal — when aborted, the stream is closed. */\n attachSignal(signal: AbortSignal): void {\n if (signal.aborted) {\n this.close();\n return;\n }\n signal.addEventListener(\"abort\", () => this.close(), { once: true });\n }\n\n /** Close the stream and release resources. */\n close(): void {\n this._transport.disconnect();\n if (this._status !== \"closed\") {\n this._status = \"closed\";\n for (const sub of this._subscribers) {\n sub.status?.(\"closed\");\n }\n }\n this._done = true;\n for (const w of this._waiters) {\n w.resolve({ value: undefined as never, done: true });\n }\n this._waiters = [];\n }\n\n /** Async iterator protocol — enables `for await (const event of stream)`. */\n [Symbol.asyncIterator](): AsyncIterableIterator<StreamEvent<T>> {\n const self = this;\n return {\n next(): Promise<IteratorResult<StreamEvent<T>>> {\n if (self._buffer.length > 0) {\n return Promise.resolve({ value: self._buffer.shift()!, done: false });\n }\n if (self._done) {\n return Promise.resolve({ value: undefined as never, done: true });\n }\n return new Promise((resolve) => {\n self._waiters.push({ resolve });\n });\n },\n return(): Promise<IteratorResult<StreamEvent<T>>> {\n self.close();\n return Promise.resolve({ value: undefined as never, done: true });\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n }\n}\n","import type { StreamEvent, StreamStatus, WaveHouseError } from \"../types.js\";\nimport type { StreamTransport } from \"./controller.js\";\n\nexport interface SSEOptions {\n baseURL: string;\n table: string;\n since?: string;\n auth?: () => Promise<string> | string;\n}\n\n/** Module-level active SSE connection counter. */\nlet activeSSEConnections = 0;\nconst SSE_WARN_THRESHOLD = 5;\n\n/** SSE transport. Native EventSource auto-reconnects. */\nexport class SSETransport<T = Record<string, unknown>> implements StreamTransport<T> {\n private _opts: SSEOptions;\n private _es: EventSource | null = null;\n\n onEvent: ((event: StreamEvent<T>) => void) | null = null;\n onStatus: ((status: StreamStatus) => void) | null = null;\n onError: ((error: WaveHouseError) => void) | null = null;\n\n constructor(opts: SSEOptions) {\n this._opts = opts;\n }\n\n connect(): void {\n if (typeof EventSource === \"undefined\") {\n throw new Error(\n \"[wavehouse] EventSource is not available in this environment. \" +\n \"Please provide a global polyfill (e.g., `globalThis.EventSource = require('eventsource')`).\",\n );\n }\n\n this._doConnect().catch((err) => {\n this.onError?.({\n status: 0,\n code: \"SSE_CONNECT_ERROR\",\n message: err instanceof Error ? err.message : String(err),\n retryable: true,\n });\n });\n }\n\n disconnect(): void {\n if (this._es) {\n this._es.close();\n this._es = null;\n activeSSEConnections = Math.max(0, activeSSEConnections - 1);\n }\n this.onStatus?.(\"closed\");\n }\n\n private async _doConnect(): Promise<void> {\n const url = new URL(\"/v1/stream\", this._opts.baseURL);\n url.searchParams.set(\"table\", this._opts.table);\n if (this._opts.since) {\n url.searchParams.set(\"since\", this._opts.since);\n }\n\n // EventSource can't set request headers, so the JWT goes in ?token=\n // (the server also accepts an Authorization header for non-browser clients)\n if (this._opts.auth) {\n const token = await this._opts.auth();\n if (token) {\n url.searchParams.set(\"token\", token);\n }\n }\n\n activeSSEConnections++;\n if (activeSSEConnections > SSE_WARN_THRESHOLD) {\n console.warn(\n `[wavehouse] ${activeSSEConnections} SSE connections open. ` +\n `Browsers limit HTTP/1.1 to 6 connections per domain.`,\n );\n }\n\n this._es = new EventSource(url.toString());\n\n this._es.onopen = () => {\n this.onStatus?.(\"live\");\n };\n\n this._es.onmessage = (e) => {\n try {\n const msg = JSON.parse(e.data as string) as {\n table_name: string;\n received_timestamp: string;\n data: T;\n };\n const event: StreamEvent<T> = {\n table: msg.table_name,\n timestamp: msg.received_timestamp,\n data: msg.data,\n };\n this.onEvent?.(event);\n } catch {\n console.warn(\"[wavehouse] SSE received malformed message:\", e.data);\n // ignore malformed messages\n }\n };\n\n this._es.onerror = () => {\n if (this._es?.readyState === EventSource.CONNECTING) {\n this.onStatus?.(\"reconnecting\");\n } else if (this._es?.readyState === EventSource.CLOSED) {\n this.onStatus?.(\"closed\");\n } else if (this._es?.readyState === EventSource.OPEN) {\n this.onStatus?.(\"live\");\n } else {\n this.onError?.({\n status: 0,\n code: \"SSE_ERROR\",\n message: \"SSE connection error\",\n retryable: true,\n });\n }\n };\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Result } from \"./types.js\";\n\n/** Namespace for the SDK's content-free server-online check. */\nexport class SysNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /**\n * Liveness ping — resolves with no error when the server is reachable and\n * past boot. Hits the public, content-free `/v1/health` route (200/503, no\n * body), kept intentionally distinct from the `/livez` Kubernetes probe so\n * it stays reachable even in deployments that filter probe paths at the\n * reverse proxy. Use it to check a server is online before sending data, or\n * to pick among servers in a distributed setup.\n */\n async health(opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<void>(this._ctx, {\n method: \"GET\",\n path: \"/v1/health\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok<void>(undefined);\n }\n}\n","import type { QueryFilter, Result, StreamEvent, StreamSubscriber } from \"../types.js\";\nimport type { StreamController } from \"./controller.js\";\n\n/**\n * Stream-first live query orchestrator.\n *\n * 1. Opens a live stream immediately (buffers events).\n * 2. Fetches historical data.\n * 3. Calls `subscriber.initial(result)` with the historical snapshot.\n * 4. Deduplicates buffered events against the fetch result.\n * 5. Flushes remaining buffered events through `subscriber.next()`.\n * 6. Resumes live: pipes stream events directly to `subscriber.next()`.\n */\nexport class LiveQuery<T = Record<string, unknown>> {\n private _stream: StreamController<T>;\n private _subscriber: StreamSubscriber<T>;\n private _buffer: StreamEvent<T>[] = [];\n private _buffering = true;\n private _unsubStream: (() => void) | null = null;\n private _closed = false;\n\n constructor(\n stream: StreamController<T>,\n fetchFn: () => Promise<Result<T[]>>,\n subscriber: StreamSubscriber<T>,\n _filters: QueryFilter[],\n ) {\n this._stream = stream;\n this._subscriber = subscriber;\n\n // Step 1: Subscribe to live events and buffer them.\n this._unsubStream = stream.subscribe({\n next: (event) => {\n if (this._closed) return;\n if (this._buffering) {\n this._buffer.push(event);\n } else {\n subscriber.next(event);\n }\n },\n status: (s) => subscriber.status?.(s),\n error: (e) => subscriber.error?.(e),\n });\n\n // Step 2-5: Fetch historical and flush.\n this._runBackfill(fetchFn);\n }\n\n private async _runBackfill(fetchFn: () => Promise<Result<T[]>>): Promise<void> {\n try {\n const result = await fetchFn();\n\n if (this._closed) return;\n\n // Step 3: Call initial() with the historical snapshot.\n this._subscriber.initial?.(result);\n\n if (result.error) {\n this._buffering = false;\n return;\n }\n\n // Step 4: Deduplicate buffered events against fetched rows.\n // Use received_timestamp as the dedup boundary: only flush events\n // that are newer than the latest row in the fetch result.\n const rows = result.data;\n let lastTimestamp: string | undefined;\n if (rows.length > 0) {\n const lastRow = rows[rows.length - 1] as Record<string, unknown>;\n lastTimestamp = lastRow?.received_timestamp as string | undefined;\n }\n\n // Step 5: Flush buffered events that are newer than the fetch.\n this._buffering = false;\n for (const event of this._buffer) {\n if (this._closed) break;\n if (lastTimestamp && event.timestamp <= lastTimestamp) {\n continue; // already covered by the fetch\n }\n this._subscriber.next(event);\n }\n this._buffer = [];\n } catch {\n // Fetch failed — stop buffering and resume live only.\n this._buffering = false;\n this._buffer = [];\n }\n }\n\n /** Close the live query and the underlying stream. */\n close(): void {\n this._closed = true;\n this._buffering = false;\n this._buffer = [];\n this._unsubStream?.();\n this._stream.close();\n }\n}\n","import { err, okPage } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { StreamTransport } from \"./stream/controller.js\";\nimport { StreamController } from \"./stream/controller.js\";\nimport { LiveQuery } from \"./stream/live-query.js\";\nimport type {\n Aggregation,\n FetchOptions,\n FilterOp,\n HttpContext,\n OrderClause,\n QueryFilter,\n Result,\n StreamOptions,\n StreamSubscriber,\n StructuredQuery,\n TimeRange,\n} from \"./types.js\";\n\n/** SDK operator → backend operator mapping. */\nconst OP_MAP: Record<FilterOp, string> = {\n \"=\": \"eq\",\n \"!=\": \"neq\",\n \">\": \"gt\",\n \">=\": \"gte\",\n \"<\": \"lt\",\n \"<=\": \"lte\",\n in: \"in\",\n like: \"like\",\n not_like: \"not_like\",\n};\n\ninterface QueryState {\n table: string;\n columns: string[];\n aggregations: Aggregation[];\n filters: QueryFilter[];\n groupBy: string[];\n orderBy: OrderClause[];\n limit?: number;\n timeRange?: TimeRange;\n cacheTTL?: number;\n}\n\ntype CreateStreamFn<Row> = (table: string, opts?: StreamOptions) => StreamController<Row>;\n\n/**\n * Immutable, PromiseLike query builder.\n * Every chain method returns a new instance. `await builder` auto-executes `.fetch()`.\n */\nexport class QueryBuilder<Row = Record<string, unknown>> implements PromiseLike<Result<Row[]>> {\n /** @internal */\n private readonly _state: Readonly<QueryState>;\n /** @internal */\n private readonly _ctx: HttpContext;\n /** @internal */\n private readonly _createStream: CreateStreamFn<Row>;\n\n constructor(ctx: HttpContext, state: QueryState, createStream: CreateStreamFn<Row>) {\n this._ctx = ctx;\n this._state = Object.freeze({ ...state });\n this._createStream = createStream;\n }\n\n // --- Builder methods (each returns a new QueryBuilder) ---\n\n select(...columns: string[]): QueryBuilder<Row> {\n return this._clone({ columns: [...this._state.columns, ...columns] });\n }\n\n where(column: string, op: FilterOp, value: unknown): QueryBuilder<Row> {\n const filter: QueryFilter = { column, op: OP_MAP[op], value };\n return this._clone({ filters: [...this._state.filters, filter] });\n }\n\n count(column = \"*\", alias = \"count\"): QueryBuilder<Row> {\n return this._addAgg(\"count\", column, alias);\n }\n\n sum(column: string, alias = `sum_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"sum\", column, alias);\n }\n\n avg(column: string, alias = `avg_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"avg\", column, alias);\n }\n\n min(column: string, alias = `min_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"min\", column, alias);\n }\n\n max(column: string, alias = `max_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"max\", column, alias);\n }\n\n countDistinct(column: string, alias = `count_distinct_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"countDistinct\", column, alias);\n }\n\n aggregate(fn: string, column: string, alias: string): QueryBuilder<Row> {\n return this._addAgg(fn, column, alias);\n }\n\n groupBy(...columns: string[]): QueryBuilder<Row> {\n return this._clone({ groupBy: [...this._state.groupBy, ...columns] });\n }\n\n orderBy(column: string, dir: \"asc\" | \"desc\" = \"asc\"): QueryBuilder<Row> {\n return this._clone({ orderBy: [...this._state.orderBy, { column, dir }] });\n }\n\n limit(n: number): QueryBuilder<Row> {\n return this._clone({ limit: n });\n }\n\n timeRange(column: string, since: string, until?: string): QueryBuilder<Row> {\n return this._clone({ timeRange: { column, since, until } });\n }\n\n cacheTTL(seconds: number): QueryBuilder<Row> {\n return this._clone({ cacheTTL: seconds });\n }\n\n // --- Execution ---\n\n /** Default row limit when none is specified. Matches backend DefaultMaxRows. */\n static readonly DEFAULT_LIMIT = 1000;\n\n async fetch(opts?: FetchOptions): Promise<Result<Row[]>> {\n const effectiveLimit = opts?.limit ?? this._state.limit ?? QueryBuilder.DEFAULT_LIMIT;\n const ast = this._buildAST(effectiveLimit);\n\n const { data, error } = await request<Row[]>(this._ctx, {\n method: \"POST\",\n path: `/v1/query?table=${encodeURIComponent(this._state.table)}`,\n body: ast,\n signal: opts?.signal,\n });\n\n if (error) return err(error);\n\n const rows = data!;\n const hasMore = effectiveLimit != null && rows.length >= effectiveLimit;\n\n if (hasMore) {\n const nextFn = () => this._fetchNext(rows, effectiveLimit!, opts);\n return okPage(rows, true, nextFn);\n }\n\n return okPage(rows, false);\n }\n\n stream(opts?: StreamOptions): StreamController<Row> {\n const raw = this._createStream(this._state.table, opts);\n const filters = this._state.filters;\n const columns = this._state.columns;\n\n // If no filters or column projection, return the raw stream.\n if (filters.length === 0 && columns.length === 0) {\n return raw;\n }\n\n // Wrap with a filtering transport that applies AST predicates client-side.\n return new FilteredStreamController<Row>(raw, filters, columns);\n }\n\n /**\n * Start a live query: fetches historical data, then streams live updates.\n *\n * The subscriber's `initial()` is called once with the fetch result, then\n * `next()` fires for each live event. Events that arrived during the fetch\n * are deduplicated and flushed automatically.\n *\n * Returns a LiveQuery handle with a `.close()` method.\n */\n liveQuery(subscriber: StreamSubscriber<Row>, opts?: StreamOptions): LiveQuery<Row> {\n const stream = this.stream(opts);\n const fetchFn = () => this.fetch();\n return new LiveQuery<Row>(stream, fetchFn, subscriber, this._state.filters);\n }\n\n // --- PromiseLike implementation ---\n\n then<TResult1 = Result<Row[]>, TResult2 = never>(\n onfulfilled?: ((value: Result<Row[]>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.fetch().then(onfulfilled, onrejected);\n }\n\n // --- Private helpers ---\n\n private _clone(overrides: Partial<QueryState>): QueryBuilder<Row> {\n return new QueryBuilder(this._ctx, { ...this._state, ...overrides }, this._createStream);\n }\n\n private _addAgg(fn: string, column: string, alias: string): QueryBuilder<Row> {\n const agg: Aggregation = { fn, column, alias };\n return this._clone({ aggregations: [...this._state.aggregations, agg] });\n }\n\n private _buildAST(effectiveLimit?: number): StructuredQuery {\n const ast: StructuredQuery = {};\n if (this._state.columns.length > 0) ast.columns = this._state.columns;\n if (this._state.aggregations.length > 0) ast.aggregations = this._state.aggregations;\n if (this._state.filters.length > 0) ast.filters = this._state.filters;\n if (this._state.groupBy.length > 0) ast.group_by = this._state.groupBy;\n if (this._state.orderBy.length > 0) {\n ast.order_by = this._state.orderBy;\n } else if (effectiveLimit != null && this._state.aggregations.length === 0) {\n // Default ordering for deterministic cursor pagination.\n ast.order_by = [{ column: \"received_timestamp\", dir: \"desc\" }];\n }\n if (effectiveLimit != null) ast.limit = effectiveLimit;\n if (this._state.timeRange) ast.time_range = this._state.timeRange;\n return ast;\n }\n\n private async _fetchNext(\n prevRows: Row[],\n _limit: number,\n opts?: FetchOptions,\n ): Promise<Result<Row[]>> {\n const orderCol = this._state.orderBy[0]?.column ?? \"received_timestamp\";\n const orderDir = this._state.orderBy[0]?.dir ?? \"desc\";\n const lastRow = prevRows[prevRows.length - 1] as Record<string, unknown>;\n const lastValue = lastRow?.[orderCol];\n\n if (lastValue === undefined) return okPage([] as unknown as Row[], false);\n\n const cursorOp = orderDir === \"desc\" ? \"lt\" : \"gt\";\n const cursorFilter: QueryFilter = { column: orderCol, op: cursorOp, value: lastValue };\n // Ensure the next page uses the same order the cursor assumes.\n const orderBy: OrderClause[] =\n this._state.orderBy.length > 0 ? this._state.orderBy : [{ column: orderCol, dir: orderDir }];\n const nextBuilder = this._clone({\n filters: [...this._state.filters, cursorFilter],\n orderBy,\n });\n\n return nextBuilder.fetch(opts);\n }\n}\n\n// ============================================================================\n// Client-side stream filtering\n// ============================================================================\n\n/**\n * Wraps a StreamController, applying client-side filters and column projection\n * before delivering events to subscribers.\n *\n * Lifecycle: by the time we reach this constructor, `inner` has already been\n * built (and is opening its own SSE connection). The outer transport's\n * `connect()` doesn't open a new connection — it bridges `inner`'s events\n * through a filter into the outer subscriber set. On `disconnect()`, closing\n * `inner` is what actually tears down the SSE socket; the subscription we\n * register on `inner` is left to be garbage-collected with it, which is why\n * we don't bother saving the unsubscribe handle.\n * @internal\n */\nclass FilteredStreamController<T = Record<string, unknown>> extends StreamController<T> {\n constructor(inner: StreamController<T>, filters: QueryFilter[], columns: string[]) {\n const transport: StreamTransport<T> = {\n onEvent: null,\n onStatus: null,\n onError: null,\n connect() {\n inner.subscribe({\n next: (event) => {\n if (!matchesFilters(event.data as Record<string, unknown>, filters)) {\n return;\n }\n const projected =\n columns.length > 0\n ? {\n ...event,\n data: projectColumns(event.data as Record<string, unknown>, columns) as T,\n }\n : event;\n this.onEvent?.(projected);\n },\n status: (s) => this.onStatus?.(s),\n error: (e) => this.onError?.(e),\n });\n },\n disconnect() {\n inner.close();\n },\n };\n super(transport);\n }\n}\n\n/** @internal Evaluate all filters against a data row. All must pass (AND). */\nfunction matchesFilters(row: Record<string, unknown>, filters: QueryFilter[]): boolean {\n for (const f of filters) {\n const val = row[f.column];\n if (!evaluateFilter(val, f.op, f.value)) return false;\n }\n return true;\n}\n\n/** @internal Evaluate a single filter predicate. */\nfunction evaluateFilter(actual: unknown, op: string, expected: unknown): boolean {\n switch (op) {\n case \"eq\":\n return actual === expected;\n case \"neq\":\n return actual !== expected;\n case \"gt\":\n return compareOrdered(actual, expected, (a, b) => a > b);\n case \"gte\":\n return compareOrdered(actual, expected, (a, b) => a >= b);\n case \"lt\":\n return compareOrdered(actual, expected, (a, b) => a < b);\n case \"lte\":\n return compareOrdered(actual, expected, (a, b) => a <= b);\n case \"in\":\n return Array.isArray(expected) && expected.includes(actual);\n case \"like\": {\n if (typeof actual !== \"string\" || typeof expected !== \"string\") return false;\n // Convert SQL LIKE pattern to regex: % → .*, _ → .\n const escaped = expected.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = escaped.replace(/%/g, \".*\").replace(/_/g, \".\");\n return new RegExp(`^${pattern}$`, \"i\").test(actual);\n }\n case \"not_like\": {\n if (typeof actual !== \"string\" || typeof expected !== \"string\") return false;\n const escaped = expected.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = escaped.replace(/%/g, \".*\").replace(/_/g, \".\");\n return !new RegExp(`^${pattern}$`, \"i\").test(actual);\n }\n default:\n return true; // unknown op — pass through\n }\n}\n\n/**\n * @internal Apply an ordered comparison only when both sides are the same\n * comparable primitive (number-vs-number or string-vs-string — strings are\n * lexicographic, which is correct for ISO-8601 timestamps). Mismatched or\n * unsupported types return false instead of relying on JS coercion.\n */\nfunction compareOrdered(\n actual: unknown,\n expected: unknown,\n cmp: (a: number, b: number) => boolean,\n): boolean {\n if (typeof actual === \"number\" && typeof expected === \"number\") {\n return cmp(actual, expected);\n }\n if (typeof actual === \"string\" && typeof expected === \"string\") {\n // `>`/`<` on strings is lexicographic; reuse the same comparator by\n // casting through `as unknown as number` — the runtime operator works\n // identically on strings.\n return cmp(actual as unknown as number, expected as unknown as number);\n }\n return false;\n}\n\n/** @internal Project a row to only the specified columns. */\nfunction projectColumns(row: Record<string, unknown>, columns: string[]): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const col of columns) {\n if (col in row) result[col] = row[col];\n }\n return result;\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport { QueryBuilder } from \"./query-builder.js\";\nimport type { StreamController } from \"./stream/controller.js\";\nimport type {\n FetchOptions,\n HttpContext,\n InsertResult,\n Result,\n StreamOptions,\n TableSchema,\n} from \"./types.js\";\n\ntype CreateStreamFn<Row> = (table: string, opts?: StreamOptions) => StreamController<Row>;\n\n/**\n * Reference to a table. NOT thenable — safe to pass around without triggering requests.\n * Use `.fetch()`, `.select()`, `.insert()`, `.schema()`, or `.stream()` to act on it.\n */\nexport class TableRef<Row = Record<string, unknown>> {\n private readonly _ctx: HttpContext;\n private readonly _table: string;\n private readonly _createStream: CreateStreamFn<Row>;\n\n constructor(ctx: HttpContext, table: string, createStream: CreateStreamFn<Row>) {\n this._ctx = ctx;\n this._table = table;\n this._createStream = createStream;\n }\n\n /** SELECT * shortcut — fetches rows with optional pagination. */\n async fetch(opts?: FetchOptions): Promise<Result<Row[]>> {\n return this.select()\n .limit(opts?.limit ?? 1000)\n .fetch(opts);\n }\n\n /** Start building a typed query. Returns an immutable, PromiseLike QueryBuilder. */\n select(...columns: string[]): QueryBuilder<Row> {\n return new QueryBuilder<Row>(\n this._ctx,\n {\n table: this._table,\n columns,\n aggregations: [],\n filters: [],\n groupBy: [],\n orderBy: [],\n },\n this._createStream,\n );\n }\n\n /** Insert one or more rows into this table. */\n async insert(\n data: Partial<Row> | Partial<Row>[],\n opts?: { signal?: AbortSignal },\n ): Promise<Result<InsertResult>> {\n if (Array.isArray(data)) {\n // TODO: Switch to NDJSON\n // FAST: Fire all HTTP requests concurrently instead of waiting for each one\n const promises = data.map((row) =>\n request<{ ok?: boolean; duplicate?: boolean }>(this._ctx, {\n method: \"POST\",\n path: `/v1/ingest?table=${encodeURIComponent(this._table)}`,\n body: row,\n signal: opts?.signal,\n }),\n );\n\n // TODO: with NDJSON/array version, need to rework how to show errors if only some/one fail\n const results = await Promise.all(promises);\n\n // Check if any of the concurrent requests failed\n for (const res of results) {\n if (res.error) return err(res.error);\n }\n return ok({ ok: true });\n }\n\n const { data: res, error } = await request<{ ok?: boolean; duplicate?: boolean }>(this._ctx, {\n method: \"POST\",\n path: `/v1/ingest?table=${encodeURIComponent(this._table)}`,\n body: data,\n signal: opts?.signal,\n });\n\n if (error) return err(error);\n const result: InsertResult = { ok: res?.ok ?? true };\n if (res?.duplicate != null) result.duplicate = res.duplicate;\n return ok(result);\n }\n\n /** Fetch the schema for this table. */\n async schema(opts?: { signal?: AbortSignal }): Promise<Result<TableSchema>> {\n const { data, error } = await request<TableSchema>(this._ctx, {\n method: \"GET\",\n path: `/v1/schema?table=${encodeURIComponent(this._table)}`,\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Subscribe to live events for this table. */\n stream(opts?: StreamOptions): StreamController<Row> {\n return this._createStream(this._table, opts);\n }\n}\n","import { DLQNamespace } from \"./dlq.js\";\nimport { PipeRef, PipesNamespace } from \"./pipes.js\";\nimport { PolicyNamespace } from \"./policy.js\";\nimport { SchemaNamespace } from \"./schema.js\";\nimport { sql } from \"./sql.js\";\nimport { StreamController } from \"./stream/controller.js\";\nimport { SSETransport } from \"./stream/sse.js\";\nimport { SysNamespace } from \"./sys.js\";\nimport { TableRef } from \"./table.js\";\nimport type { ClientConfig, Database, HttpContext, Result, StreamOptions } from \"./types.js\";\n\ntype TableName<DB> = DB extends Database ? Extract<keyof DB, string> : string;\ntype RowType<DB, T extends string> = DB extends Database\n ? T extends keyof DB\n ? DB[T]\n : Record<string, unknown>\n : Record<string, unknown>;\n\nexport class WaveHouseClient<DB extends Database = Database> {\n /** @internal */\n readonly _ctx: HttpContext;\n\n /** Schema introspection namespace. */\n readonly schema: SchemaNamespace;\n /** Access control policy namespace (admin). */\n readonly policy: PolicyNamespace;\n /** Dead Letter Queue namespace. */\n readonly dlq: DLQNamespace;\n /** System health/readiness namespace. */\n readonly sys: SysNamespace;\n /** Named query pipes admin namespace. */\n readonly pipes: PipesNamespace;\n\n constructor(config: ClientConfig<DB>) {\n this._ctx = {\n baseURL: config.baseURL.replace(/\\/+$/, \"\"),\n auth: config.auth,\n options: {\n maxRetries: config.options?.maxRetries ?? 2,\n },\n };\n\n this.schema = new SchemaNamespace(this._ctx);\n this.policy = new PolicyNamespace(this._ctx);\n this.dlq = new DLQNamespace(this._ctx, (table, opts) => this._createStream(table, opts));\n this.sys = new SysNamespace(this._ctx);\n this.pipes = new PipesNamespace(this._ctx);\n }\n\n /** Get a table reference for building queries, inserts, and streams. */\n from<T extends TableName<DB>>(table: T): TableRef<RowType<DB, T>> {\n return new TableRef<RowType<DB, T>>(this._ctx, table, (t, opts) =>\n this._createStream<RowType<DB, T>>(t, opts),\n );\n }\n\n /** Get a reference to a named query pipe. PromiseLike — `await` it to execute. */\n pipe<Row = Record<string, unknown>>(\n name: string,\n params?: Record<string, unknown>,\n ): PipeRef<Row> {\n return new PipeRef<Row>(this._ctx, name, params, (t, opts) => this._createStream<Row>(t, opts));\n }\n\n /**\n * Execute a raw SQL query against ClickHouse. Requires the admin role (the\n * configured `admin_role`, `\"admin\"` by default; there is no separate\n * `service` role). The endpoint proxies straight to ClickHouse's HTTP\n * interface so any ClickHouse-accepted SQL works; positional `?` param\n * binding is NOT supported — inline literals or use the structured query\n * builder for safe binding. See sql.ts for details.\n */\n sql<Row = Record<string, unknown>>(\n query: string,\n opts?: { signal?: AbortSignal },\n ): Promise<Result<Row[]>> {\n // Migration guard: the second argument used to be a positional-`?`\n // params array. TS callers get a compile-time error from the type\n // signature, but JS callers (or `any`-typed callsites) would silently\n // pass an array as `opts` and only discover the break via downstream\n // SQL errors. Throw a clear runtime error pointing at the migration.\n if (Array.isArray(opts)) {\n throw new Error(\n \"[WaveHouse SDK] client.sql(sql, params) was removed. The /v1/admin/query endpoint does not accept positional `?` params. Inline literals into the SQL, or use the structured query builder (wh.from(table)…) for safe binding from user input.\",\n );\n }\n return sql<Row>(this._ctx, query, opts);\n }\n\n /** @internal Create a stream for the given table. */\n private _createStream<T = Record<string, unknown>>(\n table: string,\n opts?: StreamOptions,\n ): StreamController<T> {\n if (typeof EventSource === \"undefined\") {\n // TODO: fallback method? polling?\n throw new Error(\n \"[WaveHouse SDK] Native EventSource is not available in this environment. \" +\n \"Please provide a global polyfill (e.g., `globalThis.EventSource = require('eventsource')`).\",\n );\n }\n\n const transport = new SSETransport<T>({\n baseURL: this._ctx.baseURL,\n table,\n since: opts?.since,\n auth: this._ctx.auth,\n });\n const controller = new StreamController<T>(transport);\n if (opts?.signal) controller.attachSignal(opts.signal);\n return controller;\n }\n}\n\n/** Create a new WaveHouse client instance. */\nexport function createClient<DB extends Database = Database>(\n config: ClientConfig<DB>,\n): WaveHouseClient<DB> {\n return new WaveHouseClient(config);\n}\n"],"mappings":"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","names":["err","res"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/dlq.ts","../src/pipes.ts","../src/policy.ts","../src/schema.ts","../src/sql.ts","../src/stream/controller.ts","../src/stream/sse.ts","../src/sys.ts","../src/stream/live-query.ts","../src/query-builder.ts","../src/table.ts","../src/client.ts"],"sourcesContent":["import type { Result, WaveHouseError } from \"./types.js\";\n\n/** Create a WaveHouseError from an HTTP response. */\nexport async function parseErrorResponse(res: Response): Promise<WaveHouseError> {\n let body: Record<string, unknown> | undefined;\n try {\n body = (await res.json()) as Record<string, unknown>;\n } catch {\n body = undefined;\n }\n\n const message =\n typeof body?.error === \"string\"\n ? body.error\n : typeof body?.message === \"string\"\n ? body.message\n : res.statusText;\n\n const retryable = res.status === 503 || res.status >= 500;\n return {\n status: res.status,\n code: `HTTP_${res.status}`,\n message,\n details: body,\n retryable,\n };\n}\n\n/** Create a WaveHouseError from a network/fetch error. */\nexport function networkError(cause: unknown): WaveHouseError {\n const message = cause instanceof Error ? cause.message : String(cause);\n return {\n status: 0,\n code: \"NETWORK_ERROR\",\n message,\n retryable: true,\n };\n}\n\n/** Wrap a successful value in a Result. */\nexport function ok<T>(data: T): Result<T> {\n return { ok: true, data, error: null };\n}\n\n/** Wrap a successful paginated value in a Result. */\nexport function okPage<T>(data: T, hasMore: boolean, next?: () => Promise<Result<T>>): Result<T> {\n return { ok: true, data, error: null, hasMore, next };\n}\n\n/** Wrap an error in a Result. */\nexport function err<T = unknown>(error: WaveHouseError): Result<T> {\n return { ok: false, data: null, error };\n}\n","import { networkError, parseErrorResponse } from \"./errors.js\";\nimport type { HttpContext, WaveHouseError } from \"./types.js\";\n\ninterface RequestOptions {\n method: string;\n path: string;\n body?: unknown;\n params?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/** @internal */\nexport interface HttpResult<T> {\n data: T | null;\n error: WaveHouseError | null;\n headers: Headers;\n}\n\n/**\n * Internal fetch wrapper with auth injection, retry, backoff, and Retry-After.\n * @internal\n */\nexport async function request<T>(ctx: HttpContext, opts: RequestOptions): Promise<HttpResult<T>> {\n const url = buildURL(ctx.baseURL, opts.path, opts.params);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n };\n\n if (ctx.auth) {\n const token = await ctx.auth();\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n }\n\n let lastError: WaveHouseError | null = null;\n const maxAttempts = ctx.options.maxRetries + 1;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n const res = await fetch(url, {\n method: opts.method,\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n signal: opts.signal,\n });\n\n if (res.ok) {\n const text = await res.text();\n const data = text ? (JSON.parse(text) as T) : (undefined as T);\n return { data, error: null, headers: res.headers };\n }\n\n const error = await parseErrorResponse(res);\n\n // 503 with Retry-After: wait the specified duration\n if (res.status === 503) {\n const retryAfter = res.headers.get(\"Retry-After\");\n if (retryAfter && attempt < maxAttempts - 1) {\n const delay = parseInt(retryAfter, 10) * 1000 || 30_000;\n await sleep(delay, opts.signal);\n lastError = error;\n continue;\n }\n }\n\n // Retryable server errors (5xx)\n if (error.retryable && attempt < maxAttempts - 1) {\n await sleep(backoff(attempt), opts.signal);\n lastError = error;\n continue;\n }\n\n return { data: null, error, headers: res.headers };\n } catch (e) {\n // AbortError — return immediately, no retry\n if (e instanceof DOMException && e.name === \"AbortError\") {\n return {\n data: null,\n error: { status: 0, code: \"ABORTED\", message: \"Request aborted\", retryable: false },\n headers: new Headers(),\n };\n }\n\n lastError = networkError(e);\n if (attempt < maxAttempts - 1) {\n await sleep(backoff(attempt), opts.signal);\n }\n }\n }\n\n return { data: null, error: lastError!, headers: new Headers() };\n}\n\nfunction buildURL(base: string, path: string, params?: Record<string, string>): string {\n const url = new URL(path, base.endsWith(\"/\") ? base : `${base}/`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n url.searchParams.set(k, v);\n }\n }\n return url.toString();\n}\n\nfunction backoff(attempt: number): number {\n return Math.min(1000 * 2 ** attempt, 30_000);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n return;\n }\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timer);\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n },\n { once: true },\n );\n });\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { StreamController } from \"./stream/controller.js\";\nimport type { DLQStats, HttpContext, Result, StreamOptions } from \"./types.js\";\n\ntype CreateStreamFn = (table: string, opts?: StreamOptions) => StreamController;\n\n/** Namespace for Dead Letter Queue operations. */\nexport class DLQNamespace {\n private readonly _ctx: HttpContext;\n private readonly _createStream: CreateStreamFn;\n\n constructor(ctx: HttpContext, createStream: CreateStreamFn) {\n this._ctx = ctx;\n this._createStream = createStream;\n }\n\n /** Get DLQ statistics (message counts per table). */\n async list(opts?: { signal?: AbortSignal }): Promise<Result<DLQStats>> {\n const { data, error } = await request<DLQStats>(this._ctx, {\n method: \"GET\",\n path: \"/v1/dlq/stats\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Get DLQ stats filtered by table name. */\n async table(name: string, opts?: { signal?: AbortSignal }): Promise<Result<DLQStats>> {\n const { data, error } = await request<DLQStats>(this._ctx, {\n method: \"GET\",\n path: \"/v1/dlq/stats\",\n params: { table: name },\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Subscribe to live DLQ events. */\n stream(opts?: StreamOptions): StreamController {\n return this._createStream(\"dlq\", opts);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { StreamController } from \"./stream/controller.js\";\nimport type { FetchOptions, HttpContext, Pipe, Result, StreamOptions } from \"./types.js\";\n\ntype CreateStreamFn<Row> = (table: string, opts?: StreamOptions) => StreamController<Row>;\n\n/** Reference to a named query pipe — PromiseLike for convenient `await`. */\nexport class PipeRef<Row = Record<string, unknown>> implements PromiseLike<Result<Row[]>> {\n private readonly _ctx: HttpContext;\n private readonly _name: string;\n private readonly _params?: Record<string, unknown>;\n private readonly _createStream: CreateStreamFn<Row>;\n\n constructor(\n ctx: HttpContext,\n name: string,\n params: Record<string, unknown> | undefined,\n createStream: CreateStreamFn<Row>,\n ) {\n this._ctx = ctx;\n this._name = name;\n this._params = params;\n this._createStream = createStream;\n }\n\n /** Execute the pipe and return results. */\n async fetch(opts?: FetchOptions): Promise<Result<Row[]>> {\n const { data, error } = await request<Row[]>(this._ctx, {\n method: \"POST\",\n path: `/v1/pipes/${encodeURIComponent(this._name)}`,\n body: this._params ?? {},\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Subscribe to live events from the pipe's underlying query. */\n stream(opts?: StreamOptions): StreamController<Row> {\n return this._createStream(this._name, opts);\n }\n\n then<TResult1 = Result<Row[]>, TResult2 = never>(\n onfulfilled?: ((value: Result<Row[]>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.fetch().then(onfulfilled, onrejected);\n }\n}\n\n/** Admin namespace for managing named query pipes. */\nexport class PipesNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /** List all registered pipes. */\n async list(opts?: { signal?: AbortSignal }): Promise<Result<Pipe[]>> {\n const { data, error } = await request<Pipe[]>(this._ctx, {\n method: \"GET\",\n path: \"/v1/admin/pipes\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Get a single pipe definition by name. */\n async get(name: string, opts?: { signal?: AbortSignal }): Promise<Result<Pipe>> {\n const { data, error } = await request<Pipe>(this._ctx, {\n method: \"GET\",\n path: `/v1/admin/pipes/${encodeURIComponent(name)}`,\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Create or update a pipe. */\n async set(\n name: string,\n def: Omit<Pipe, \"name\">,\n opts?: { signal?: AbortSignal },\n ): Promise<Result<void>> {\n const { error } = await request<{ ok: boolean }>(this._ctx, {\n method: \"PUT\",\n path: `/v1/admin/pipes/${encodeURIComponent(name)}`,\n body: def,\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n\n /** Delete a pipe by name. */\n async delete(name: string, opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<{ ok: boolean }>(this._ctx, {\n method: \"DELETE\",\n path: `/v1/admin/pipes/${encodeURIComponent(name)}`,\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Policy, Result, ValidationResult } from \"./types.js\";\n\n/** Namespace for access control policy management. Requires the admin role (the configured `admin_role`, `\"admin\"` by default). */\nexport class PolicyNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /** Get the current access control policy. */\n async get(opts?: { signal?: AbortSignal }): Promise<Result<Policy>> {\n const { data, error } = await request<Policy>(this._ctx, {\n method: \"GET\",\n path: \"/v1/admin/policy\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Replace the entire access control policy. */\n async set(policy: Policy, opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<{ ok: boolean }>(this._ctx, {\n method: \"PUT\",\n path: \"/v1/admin/policy\",\n body: policy,\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n\n /** Validate a policy without applying it (dry run). */\n async validate(\n policy: Policy,\n opts?: { signal?: AbortSignal },\n ): Promise<Result<ValidationResult>> {\n const { data, error } = await request<ValidationResult>(this._ctx, {\n method: \"POST\",\n path: \"/v1/admin/policy/validate\",\n body: policy,\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Result, Schemas } from \"./types.js\";\n\n/** Namespace for schema introspection. */\nexport class SchemaNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /** List all table schemas discovered from ClickHouse. */\n async list(opts?: { signal?: AbortSignal }): Promise<Result<Schemas>> {\n // The backend returns TableSchema[] — transform to Record<string, TableSchema>.\n const { data, error } = await request<unknown>(this._ctx, {\n method: \"GET\",\n path: \"/v1/schema\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n\n let schemas: Schemas;\n if (Array.isArray(data)) {\n schemas = {};\n for (const table of data) {\n if (table && typeof table === \"object\" && \"name\" in table) {\n schemas[(table as { name: string }).name] = table as Schemas[string];\n }\n }\n } else {\n schemas = data as Schemas;\n }\n return ok(schemas);\n }\n\n /** Force a schema refresh from ClickHouse system.columns. */\n async refresh(opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<Schemas>(this._ctx, {\n method: \"POST\",\n path: \"/v1/schema/refresh\",\n signal: opts?.signal,\n });\n if (error) return err<void>(error);\n return ok(undefined as undefined);\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Result } from \"./types.js\";\n\n/**\n * Execute a raw SQL query against ClickHouse.\n *\n * Backed by `POST /v1/admin/query`, which requires the admin role — the same\n * gate as the rest of `/v1/admin/*`. Callers must hold a JWT whose role is the\n * configured `admin_role` (`\"admin\"` by default); there is no separate\n * `service` role. The JWT middleware always runs, so a request with no token\n * or an invalid one is denied, never granted. Non-admin use cases should use\n * the structured query builder (`wh.from(table)...`) instead.\n *\n * The server proxies the SQL string verbatim to ClickHouse's HTTP interface,\n * so any ClickHouse-accepted statement works — including multi-statement\n * input (`SELECT 1; TRUNCATE t`) and arbitrary DDL/DML/SYSTEM verbs.\n *\n * **JSON-row contract.** This helper returns `Result<Row[]>` and assumes the\n * response is the standard `FORMAT JSON` envelope (or an empty body for\n * no-result mutations — coerced to `[]`). Inline non-JSON `FORMAT` overrides\n * (`SELECT 1 FORMAT CSV` / `FORMAT TSV` / `FORMAT Pretty` / etc.) are NOT\n * compatible with `sql()` — the proxy passes the upstream Content-Type\n * through, and the SDK's JSON decoder throws on a non-JSON body, which the\n * retry layer surfaces as a `NETWORK_ERROR` result (not a structured\n * format-mismatch error). For CSV/TSV exports, hit `/v1/admin/query`\n * directly with `fetch()` and read the body as text.\n *\n * **No parameter binding.** Positional `?` substitution is not supported.\n * The SDK has no way to forward ClickHouse-style named params\n * (`WHERE id = {id:UInt32}` with `param_id=42` on the query string) —\n * the proxy doesn't forward arbitrary query-string params to ClickHouse\n * and the SDK doesn't expose a hook to add them. Inline literals into\n * the SQL string, or — for safe binding from user-supplied input — use\n * the structured query builder (`wh.from(...).select(...).where(...)`).\n */\nexport async function sql<Row = Record<string, unknown>>(\n ctx: HttpContext,\n query: string,\n opts?: { signal?: AbortSignal },\n): Promise<Result<Row[]>> {\n const { data, error } = await request<Row[]>(ctx, {\n method: \"POST\",\n path: \"/v1/admin/query\",\n body: { sql: query },\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n}\n","import type { StreamEvent, StreamStatus, StreamSubscriber, WaveHouseError } from \"../types.js\";\n\n/** @internal Transport abstraction for SSE backend. */\nexport interface StreamTransport<T = Record<string, unknown>> {\n connect(): void;\n disconnect(): void;\n onEvent: ((event: StreamEvent<T>) => void) | null;\n onStatus: ((status: StreamStatus) => void) | null;\n onError: ((error: WaveHouseError) => void) | null;\n}\n\n/**\n * Controls a live event stream. NOT thenable.\n * Use `.subscribe()` for callback-based consumption or `for await` for async iteration.\n */\nexport class StreamController<T = Record<string, unknown>> {\n private _transport: StreamTransport<T>;\n private _subscribers = new Set<StreamSubscriber<T>>();\n private _status: StreamStatus = \"connecting\";\n private _buffer: StreamEvent<T>[] = [];\n private _waiters: { resolve: (value: IteratorResult<StreamEvent<T>>) => void }[] = [];\n private _done = false;\n\n constructor(transport: StreamTransport<T>) {\n this._transport = transport;\n\n this._transport.onEvent = (event) => {\n for (const sub of this._subscribers) {\n sub.next(event);\n }\n // Async iterator support\n const waiter = this._waiters.shift();\n if (waiter) {\n waiter.resolve({ value: event, done: false });\n } else {\n this._buffer.push(event);\n }\n };\n\n this._transport.onStatus = (status) => {\n // Deduplicate: skip if status hasn't changed (e.g. transport fires\n // 'connecting' after StreamController already set it as the initial state).\n if (status === this._status) return;\n this._status = status;\n for (const sub of this._subscribers) {\n sub.status?.(status);\n }\n if (status === \"closed\") {\n this._done = true;\n for (const w of this._waiters) {\n w.resolve({ value: undefined as never, done: true });\n }\n this._waiters = [];\n }\n };\n\n this._transport.onError = (error) => {\n for (const sub of this._subscribers) {\n sub.error?.(error);\n }\n };\n\n this._transport.connect();\n }\n\n /** Current connection status. */\n get status(): StreamStatus {\n return this._status;\n }\n\n /**\n * Returns a promise that resolves when the stream status reaches `'live'`,\n * rejects immediately if the stream is already `'closed'`, or rejects after\n * `timeoutMs` milliseconds (default: 5 000) if it never connects.\n *\n * Safe to call before `.subscribe()` — does not trigger auto-close when\n * the internal waiter is removed.\n *\n * `@example`\n * const stream = client.from('events').stream();\n * const unsub = stream.subscribe({ next: (e) => console.log(e) });\n * await stream.connected(); // waits until the transport is live\n * await client.from('events').insert({ ... });\n */\n connected(timeoutMs = 5_000): Promise<void> {\n if (this._status === \"live\") return Promise.resolve();\n if (this._status === \"closed\") return Promise.reject(new Error(\"Stream is closed\"));\n if (this._done) return Promise.reject(new Error(\"Stream closed before connecting\"));\n\n return new Promise((resolve, reject) => {\n let settled = false;\n\n const timer = setTimeout(() => {\n if (settled) return;\n settled = true;\n this._subscribers.delete(watcher);\n reject(new Error(`Stream did not connect within ${timeoutMs}ms`));\n }, timeoutMs);\n\n // Use a private subscriber directly to avoid the auto-close side-effect\n // that the public subscribe() triggers when subscriber count drops to zero.\n const watcher: StreamSubscriber<T> = {\n next: () => {\n // no-op: we only care about status transitions here\n },\n status: (s) => {\n if (s === \"live\") {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n this._subscribers.delete(watcher);\n resolve();\n } else if (s === \"closed\") {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n this._subscribers.delete(watcher);\n reject(new Error(\"Stream closed before connecting\"));\n }\n },\n };\n\n this._subscribers.add(watcher);\n });\n }\n\n /** Subscribe to stream events via callbacks. Returns an unsubscribe function. */\n subscribe(subscriber: StreamSubscriber<T>): () => void {\n this._subscribers.add(subscriber);\n subscriber.status?.(this._status);\n\n return () => {\n this._subscribers.delete(subscriber);\n if (this._subscribers.size === 0 && this._waiters.length === 0) {\n this.close();\n }\n };\n }\n\n /** Attach an AbortSignal — when aborted, the stream is closed. */\n attachSignal(signal: AbortSignal): void {\n if (signal.aborted) {\n this.close();\n return;\n }\n signal.addEventListener(\"abort\", () => this.close(), { once: true });\n }\n\n /** Close the stream and release resources. */\n close(): void {\n this._transport.disconnect();\n if (this._status !== \"closed\") {\n this._status = \"closed\";\n for (const sub of this._subscribers) {\n sub.status?.(\"closed\");\n }\n }\n this._done = true;\n for (const w of this._waiters) {\n w.resolve({ value: undefined as never, done: true });\n }\n this._waiters = [];\n }\n\n /** Async iterator protocol — enables `for await (const event of stream)`. */\n [Symbol.asyncIterator](): AsyncIterableIterator<StreamEvent<T>> {\n const self = this;\n return {\n next(): Promise<IteratorResult<StreamEvent<T>>> {\n if (self._buffer.length > 0) {\n return Promise.resolve({ value: self._buffer.shift()!, done: false });\n }\n if (self._done) {\n return Promise.resolve({ value: undefined as never, done: true });\n }\n return new Promise((resolve) => {\n self._waiters.push({ resolve });\n });\n },\n return(): Promise<IteratorResult<StreamEvent<T>>> {\n self.close();\n return Promise.resolve({ value: undefined as never, done: true });\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n }\n}\n","import type { StreamEvent, StreamStatus, WaveHouseError } from \"../types.js\";\nimport type { StreamTransport } from \"./controller.js\";\n\nexport interface SSEOptions {\n baseURL: string;\n table: string;\n since?: string;\n auth?: () => Promise<string> | string;\n}\n\n/** Module-level active SSE connection counter. */\nlet activeSSEConnections = 0;\nconst SSE_WARN_THRESHOLD = 5;\n\n/** SSE transport. Native EventSource auto-reconnects. */\nexport class SSETransport<T = Record<string, unknown>> implements StreamTransport<T> {\n private _opts: SSEOptions;\n private _es: EventSource | null = null;\n\n onEvent: ((event: StreamEvent<T>) => void) | null = null;\n onStatus: ((status: StreamStatus) => void) | null = null;\n onError: ((error: WaveHouseError) => void) | null = null;\n\n constructor(opts: SSEOptions) {\n this._opts = opts;\n }\n\n connect(): void {\n if (typeof EventSource === \"undefined\") {\n throw new Error(\n \"[wavehouse] EventSource is not available in this environment. \" +\n \"Please provide a global polyfill (e.g., `globalThis.EventSource = require('eventsource')`).\",\n );\n }\n\n this._doConnect().catch((err) => {\n this.onError?.({\n status: 0,\n code: \"SSE_CONNECT_ERROR\",\n message: err instanceof Error ? err.message : String(err),\n retryable: true,\n });\n });\n }\n\n disconnect(): void {\n if (this._es) {\n this._es.close();\n this._es = null;\n activeSSEConnections = Math.max(0, activeSSEConnections - 1);\n }\n this.onStatus?.(\"closed\");\n }\n\n private async _doConnect(): Promise<void> {\n const url = new URL(\"/v1/stream\", this._opts.baseURL);\n url.searchParams.set(\"table\", this._opts.table);\n if (this._opts.since) {\n url.searchParams.set(\"since\", this._opts.since);\n }\n\n // EventSource can't set request headers, so the JWT goes in ?token=\n // (the server also accepts an Authorization header for non-browser clients)\n if (this._opts.auth) {\n const token = await this._opts.auth();\n if (token) {\n url.searchParams.set(\"token\", token);\n }\n }\n\n activeSSEConnections++;\n if (activeSSEConnections > SSE_WARN_THRESHOLD) {\n console.warn(\n `[wavehouse] ${activeSSEConnections} SSE connections open. ` +\n `Browsers limit HTTP/1.1 to 6 connections per domain.`,\n );\n }\n\n this._es = new EventSource(url.toString());\n\n this._es.onopen = () => {\n this.onStatus?.(\"live\");\n };\n\n this._es.onmessage = (e) => {\n try {\n const msg = JSON.parse(e.data as string) as {\n table_name: string;\n received_timestamp: string;\n data: T;\n };\n const event: StreamEvent<T> = {\n table: msg.table_name,\n timestamp: msg.received_timestamp,\n data: msg.data,\n };\n this.onEvent?.(event);\n } catch {\n console.warn(\"[wavehouse] SSE received malformed message:\", e.data);\n // ignore malformed messages\n }\n };\n\n this._es.onerror = () => {\n if (this._es?.readyState === EventSource.CONNECTING) {\n this.onStatus?.(\"reconnecting\");\n } else if (this._es?.readyState === EventSource.CLOSED) {\n this.onStatus?.(\"closed\");\n } else if (this._es?.readyState === EventSource.OPEN) {\n this.onStatus?.(\"live\");\n } else {\n this.onError?.({\n status: 0,\n code: \"SSE_ERROR\",\n message: \"SSE connection error\",\n retryable: true,\n });\n }\n };\n }\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { HttpContext, Result } from \"./types.js\";\n\n/** Namespace for the SDK's content-free server-online check. */\nexport class SysNamespace {\n private readonly _ctx: HttpContext;\n\n constructor(ctx: HttpContext) {\n this._ctx = ctx;\n }\n\n /**\n * Liveness ping — resolves with no error when the server is reachable and\n * past boot. Hits the public, content-free `/v1/health` route (200/503, no\n * body), kept intentionally distinct from the `/livez` Kubernetes probe so\n * it stays reachable even in deployments that filter probe paths at the\n * reverse proxy. Use it to check a server is online before sending data, or\n * to pick among servers in a distributed setup.\n */\n async health(opts?: { signal?: AbortSignal }): Promise<Result<void>> {\n const { error } = await request<void>(this._ctx, {\n method: \"GET\",\n path: \"/v1/health\",\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok<void>(undefined);\n }\n}\n","import type { QueryFilter, Result, StreamEvent, StreamSubscriber } from \"../types.js\";\nimport type { StreamController } from \"./controller.js\";\n\n/**\n * Stream-first live query orchestrator.\n *\n * 1. Opens a live stream immediately (buffers events).\n * 2. Fetches historical data.\n * 3. Calls `subscriber.initial(result)` with the historical snapshot.\n * 4. Deduplicates buffered events against the fetch result.\n * 5. Flushes remaining buffered events through `subscriber.next()`.\n * 6. Resumes live: pipes stream events directly to `subscriber.next()`.\n */\nexport class LiveQuery<T = Record<string, unknown>> {\n private _stream: StreamController<T>;\n private _subscriber: StreamSubscriber<T>;\n private _buffer: StreamEvent<T>[] = [];\n private _buffering = true;\n private _unsubStream: (() => void) | null = null;\n private _closed = false;\n\n constructor(\n stream: StreamController<T>,\n fetchFn: () => Promise<Result<T[]>>,\n subscriber: StreamSubscriber<T>,\n _filters: QueryFilter[],\n ) {\n this._stream = stream;\n this._subscriber = subscriber;\n\n // Step 1: Subscribe to live events and buffer them.\n this._unsubStream = stream.subscribe({\n next: (event) => {\n if (this._closed) return;\n if (this._buffering) {\n this._buffer.push(event);\n } else {\n subscriber.next(event);\n }\n },\n status: (s) => subscriber.status?.(s),\n error: (e) => subscriber.error?.(e),\n });\n\n // Step 2-5: Fetch historical and flush.\n this._runBackfill(fetchFn);\n }\n\n private async _runBackfill(fetchFn: () => Promise<Result<T[]>>): Promise<void> {\n try {\n const result = await fetchFn();\n\n if (this._closed) return;\n\n // Step 3: Call initial() with the historical snapshot.\n this._subscriber.initial?.(result);\n\n if (result.error) {\n this._buffering = false;\n return;\n }\n\n // Step 4: Deduplicate buffered events against fetched rows.\n // Use received_timestamp as the dedup boundary: only flush events\n // that are newer than the latest row in the fetch result.\n const rows = result.data;\n let lastTimestamp: string | undefined;\n if (rows.length > 0) {\n const lastRow = rows[rows.length - 1] as Record<string, unknown>;\n lastTimestamp = lastRow?.received_timestamp as string | undefined;\n }\n\n // Step 5: Flush buffered events that are newer than the fetch.\n this._buffering = false;\n for (const event of this._buffer) {\n if (this._closed) break;\n if (lastTimestamp && event.timestamp <= lastTimestamp) {\n continue; // already covered by the fetch\n }\n this._subscriber.next(event);\n }\n this._buffer = [];\n } catch {\n // Fetch failed — stop buffering and resume live only.\n this._buffering = false;\n this._buffer = [];\n }\n }\n\n /** Close the live query and the underlying stream. */\n close(): void {\n this._closed = true;\n this._buffering = false;\n this._buffer = [];\n this._unsubStream?.();\n this._stream.close();\n }\n}\n","import { err, okPage } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport type { StreamTransport } from \"./stream/controller.js\";\nimport { StreamController } from \"./stream/controller.js\";\nimport { LiveQuery } from \"./stream/live-query.js\";\nimport type {\n Aggregation,\n FetchOptions,\n FilterOp,\n HttpContext,\n OrderClause,\n QueryFilter,\n Result,\n StreamOptions,\n StreamSubscriber,\n StructuredQuery,\n TimeRange,\n} from \"./types.js\";\n\n/** SDK operator → backend operator mapping. */\nconst OP_MAP: Record<FilterOp, string> = {\n \"=\": \"eq\",\n \"!=\": \"neq\",\n \">\": \"gt\",\n \">=\": \"gte\",\n \"<\": \"lt\",\n \"<=\": \"lte\",\n in: \"in\",\n like: \"like\",\n not_like: \"not_like\",\n};\n\ninterface QueryState {\n table: string;\n columns: string[];\n aggregations: Aggregation[];\n filters: QueryFilter[];\n groupBy: string[];\n orderBy: OrderClause[];\n limit?: number;\n timeRange?: TimeRange;\n cacheTTL?: number;\n}\n\ntype CreateStreamFn<Row> = (table: string, opts?: StreamOptions) => StreamController<Row>;\n\n/**\n * Immutable, PromiseLike query builder.\n * Every chain method returns a new instance. `await builder` auto-executes `.fetch()`.\n */\nexport class QueryBuilder<Row = Record<string, unknown>> implements PromiseLike<Result<Row[]>> {\n /** @internal */\n private readonly _state: Readonly<QueryState>;\n /** @internal */\n private readonly _ctx: HttpContext;\n /** @internal */\n private readonly _createStream: CreateStreamFn<Row>;\n\n constructor(ctx: HttpContext, state: QueryState, createStream: CreateStreamFn<Row>) {\n this._ctx = ctx;\n this._state = Object.freeze({ ...state });\n this._createStream = createStream;\n }\n\n // --- Builder methods (each returns a new QueryBuilder) ---\n\n select(...columns: string[]): QueryBuilder<Row> {\n return this._clone({ columns: [...this._state.columns, ...columns] });\n }\n\n where(column: string, op: FilterOp, value: unknown): QueryBuilder<Row> {\n const filter: QueryFilter = { column, op: OP_MAP[op], value };\n return this._clone({ filters: [...this._state.filters, filter] });\n }\n\n count(column = \"*\", alias = \"count\"): QueryBuilder<Row> {\n return this._addAgg(\"count\", column, alias);\n }\n\n sum(column: string, alias = `sum_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"sum\", column, alias);\n }\n\n avg(column: string, alias = `avg_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"avg\", column, alias);\n }\n\n min(column: string, alias = `min_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"min\", column, alias);\n }\n\n max(column: string, alias = `max_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"max\", column, alias);\n }\n\n countDistinct(column: string, alias = `count_distinct_${column}`): QueryBuilder<Row> {\n return this._addAgg(\"countDistinct\", column, alias);\n }\n\n aggregate(fn: string, column: string, alias: string): QueryBuilder<Row> {\n return this._addAgg(fn, column, alias);\n }\n\n groupBy(...columns: string[]): QueryBuilder<Row> {\n return this._clone({ groupBy: [...this._state.groupBy, ...columns] });\n }\n\n orderBy(column: string, dir: \"asc\" | \"desc\" = \"asc\"): QueryBuilder<Row> {\n return this._clone({ orderBy: [...this._state.orderBy, { column, dir }] });\n }\n\n limit(n: number): QueryBuilder<Row> {\n return this._clone({ limit: n });\n }\n\n timeRange(column: string, since: string, until?: string): QueryBuilder<Row> {\n return this._clone({ timeRange: { column, since, until } });\n }\n\n cacheTTL(seconds: number): QueryBuilder<Row> {\n return this._clone({ cacheTTL: seconds });\n }\n\n // --- Execution ---\n\n /** Default row limit when none is specified. Matches backend DefaultMaxRows. */\n static readonly DEFAULT_LIMIT = 1000;\n\n async fetch(opts?: FetchOptions): Promise<Result<Row[]>> {\n const effectiveLimit = opts?.limit ?? this._state.limit ?? QueryBuilder.DEFAULT_LIMIT;\n const ast = this._buildAST(effectiveLimit);\n\n const { data, error } = await request<Row[]>(this._ctx, {\n method: \"POST\",\n path: `/v1/query?table=${encodeURIComponent(this._state.table)}`,\n body: ast,\n signal: opts?.signal,\n });\n\n if (error) return err(error);\n\n const rows = data!;\n const hasMore = effectiveLimit != null && rows.length >= effectiveLimit;\n\n // next() needs an order column for its cursor; with no .orderBy() we still\n // report hasMore honestly from the row count but can't offer a next().\n if (hasMore && this._state.orderBy.length > 0) {\n const nextFn = () => this._fetchNext(rows, effectiveLimit!, opts);\n return okPage(rows, true, nextFn);\n }\n\n return okPage(rows, hasMore);\n }\n\n stream(opts?: StreamOptions): StreamController<Row> {\n const raw = this._createStream(this._state.table, opts);\n const filters = this._state.filters;\n const columns = this._state.columns;\n\n // If no filters or column projection, return the raw stream.\n if (filters.length === 0 && columns.length === 0) {\n return raw;\n }\n\n // Wrap with a filtering transport that applies AST predicates client-side.\n return new FilteredStreamController<Row>(raw, filters, columns);\n }\n\n /**\n * Start a live query: fetches historical data, then streams live updates.\n *\n * The subscriber's `initial()` is called once with the fetch result, then\n * `next()` fires for each live event. Events that arrived during the fetch\n * are deduplicated and flushed automatically.\n *\n * Returns a LiveQuery handle with a `.close()` method.\n */\n liveQuery(subscriber: StreamSubscriber<Row>, opts?: StreamOptions): LiveQuery<Row> {\n const stream = this.stream(opts);\n const fetchFn = () => this.fetch();\n return new LiveQuery<Row>(stream, fetchFn, subscriber, this._state.filters);\n }\n\n // --- PromiseLike implementation ---\n\n then<TResult1 = Result<Row[]>, TResult2 = never>(\n onfulfilled?: ((value: Result<Row[]>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.fetch().then(onfulfilled, onrejected);\n }\n\n // --- Private helpers ---\n\n private _clone(overrides: Partial<QueryState>): QueryBuilder<Row> {\n return new QueryBuilder(this._ctx, { ...this._state, ...overrides }, this._createStream);\n }\n\n private _addAgg(fn: string, column: string, alias: string): QueryBuilder<Row> {\n const agg: Aggregation = { fn, column, alias };\n return this._clone({ aggregations: [...this._state.aggregations, agg] });\n }\n\n private _buildAST(effectiveLimit?: number): StructuredQuery {\n const ast: StructuredQuery = {};\n if (this._state.columns.length > 0) ast.columns = this._state.columns;\n if (this._state.aggregations.length > 0) ast.aggregations = this._state.aggregations;\n if (this._state.filters.length > 0) ast.filters = this._state.filters;\n if (this._state.groupBy.length > 0) ast.group_by = this._state.groupBy;\n if (this._state.orderBy.length > 0) ast.order_by = this._state.orderBy;\n if (effectiveLimit != null) ast.limit = effectiveLimit;\n if (this._state.timeRange) ast.time_range = this._state.timeRange;\n return ast;\n }\n\n private async _fetchNext(\n prevRows: Row[],\n _limit: number,\n opts?: FetchOptions,\n ): Promise<Result<Row[]>> {\n // No explicit order → no keyset cursor to build; nothing to page by.\n const cursor = this._state.orderBy[0];\n if (cursor == null) return okPage([] as unknown as Row[], false);\n const { column: orderCol, dir: orderDir } = cursor;\n\n const lastRow = prevRows[prevRows.length - 1] as Record<string, unknown>;\n const lastValue = lastRow?.[orderCol];\n\n if (lastValue === undefined) return okPage([] as unknown as Row[], false);\n\n const cursorOp = orderDir === \"desc\" ? \"lt\" : \"gt\";\n const cursorFilter: QueryFilter = { column: orderCol, op: cursorOp, value: lastValue };\n const nextBuilder = this._clone({\n filters: [...this._state.filters, cursorFilter],\n orderBy: this._state.orderBy,\n });\n\n return nextBuilder.fetch(opts);\n }\n}\n\n// ============================================================================\n// Client-side stream filtering\n// ============================================================================\n\n/**\n * Wraps a StreamController, applying client-side filters and column projection\n * before delivering events to subscribers.\n *\n * Lifecycle: by the time we reach this constructor, `inner` has already been\n * built (and is opening its own SSE connection). The outer transport's\n * `connect()` doesn't open a new connection — it bridges `inner`'s events\n * through a filter into the outer subscriber set. On `disconnect()`, closing\n * `inner` is what actually tears down the SSE socket; the subscription we\n * register on `inner` is left to be garbage-collected with it, which is why\n * we don't bother saving the unsubscribe handle.\n * @internal\n */\nclass FilteredStreamController<T = Record<string, unknown>> extends StreamController<T> {\n constructor(inner: StreamController<T>, filters: QueryFilter[], columns: string[]) {\n const transport: StreamTransport<T> = {\n onEvent: null,\n onStatus: null,\n onError: null,\n connect() {\n inner.subscribe({\n next: (event) => {\n if (!matchesFilters(event.data as Record<string, unknown>, filters)) {\n return;\n }\n const projected =\n columns.length > 0\n ? {\n ...event,\n data: projectColumns(event.data as Record<string, unknown>, columns) as T,\n }\n : event;\n this.onEvent?.(projected);\n },\n status: (s) => this.onStatus?.(s),\n error: (e) => this.onError?.(e),\n });\n },\n disconnect() {\n inner.close();\n },\n };\n super(transport);\n }\n}\n\n/** @internal Evaluate all filters against a data row. All must pass (AND). */\nfunction matchesFilters(row: Record<string, unknown>, filters: QueryFilter[]): boolean {\n for (const f of filters) {\n const val = row[f.column];\n if (!evaluateFilter(val, f.op, f.value)) return false;\n }\n return true;\n}\n\n/** @internal Evaluate a single filter predicate. */\nfunction evaluateFilter(actual: unknown, op: string, expected: unknown): boolean {\n switch (op) {\n case \"eq\":\n return actual === expected;\n case \"neq\":\n return actual !== expected;\n case \"gt\":\n return compareOrdered(actual, expected, (a, b) => a > b);\n case \"gte\":\n return compareOrdered(actual, expected, (a, b) => a >= b);\n case \"lt\":\n return compareOrdered(actual, expected, (a, b) => a < b);\n case \"lte\":\n return compareOrdered(actual, expected, (a, b) => a <= b);\n case \"in\":\n return Array.isArray(expected) && expected.includes(actual);\n case \"like\": {\n if (typeof actual !== \"string\" || typeof expected !== \"string\") return false;\n // Convert SQL LIKE pattern to regex: % → .*, _ → .\n const escaped = expected.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = escaped.replace(/%/g, \".*\").replace(/_/g, \".\");\n return new RegExp(`^${pattern}$`, \"i\").test(actual);\n }\n case \"not_like\": {\n if (typeof actual !== \"string\" || typeof expected !== \"string\") return false;\n const escaped = expected.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = escaped.replace(/%/g, \".*\").replace(/_/g, \".\");\n return !new RegExp(`^${pattern}$`, \"i\").test(actual);\n }\n default:\n return true; // unknown op — pass through\n }\n}\n\n/**\n * @internal Apply an ordered comparison only when both sides are the same\n * comparable primitive (number-vs-number or string-vs-string — strings are\n * lexicographic, which is correct for ISO-8601 timestamps). Mismatched or\n * unsupported types return false instead of relying on JS coercion.\n */\nfunction compareOrdered(\n actual: unknown,\n expected: unknown,\n cmp: (a: number, b: number) => boolean,\n): boolean {\n if (typeof actual === \"number\" && typeof expected === \"number\") {\n return cmp(actual, expected);\n }\n if (typeof actual === \"string\" && typeof expected === \"string\") {\n // `>`/`<` on strings is lexicographic; reuse the same comparator by\n // casting through `as unknown as number` — the runtime operator works\n // identically on strings.\n return cmp(actual as unknown as number, expected as unknown as number);\n }\n return false;\n}\n\n/** @internal Project a row to only the specified columns. */\nfunction projectColumns(row: Record<string, unknown>, columns: string[]): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const col of columns) {\n if (col in row) result[col] = row[col];\n }\n return result;\n}\n","import { err, ok } from \"./errors.js\";\nimport { request } from \"./http.js\";\nimport { QueryBuilder } from \"./query-builder.js\";\nimport type { StreamController } from \"./stream/controller.js\";\nimport type {\n FetchOptions,\n HttpContext,\n InsertResult,\n Result,\n StreamOptions,\n TableSchema,\n} from \"./types.js\";\n\ntype CreateStreamFn<Row> = (table: string, opts?: StreamOptions) => StreamController<Row>;\n\n/**\n * Reference to a table. NOT thenable — safe to pass around without triggering requests.\n * Use `.fetch()`, `.select()`, `.insert()`, `.schema()`, or `.stream()` to act on it.\n */\nexport class TableRef<Row = Record<string, unknown>> {\n private readonly _ctx: HttpContext;\n private readonly _table: string;\n private readonly _createStream: CreateStreamFn<Row>;\n\n constructor(ctx: HttpContext, table: string, createStream: CreateStreamFn<Row>) {\n this._ctx = ctx;\n this._table = table;\n this._createStream = createStream;\n }\n\n /** SELECT * shortcut — fetches rows with optional pagination. */\n async fetch(opts?: FetchOptions): Promise<Result<Row[]>> {\n return this.select()\n .limit(opts?.limit ?? 1000)\n .fetch(opts);\n }\n\n /** Start building a typed query. Returns an immutable, PromiseLike QueryBuilder. */\n select(...columns: string[]): QueryBuilder<Row> {\n return new QueryBuilder<Row>(\n this._ctx,\n {\n table: this._table,\n columns,\n aggregations: [],\n filters: [],\n groupBy: [],\n orderBy: [],\n },\n this._createStream,\n );\n }\n\n /** Insert one or more rows into this table. */\n async insert(\n data: Partial<Row> | Partial<Row>[],\n opts?: { signal?: AbortSignal },\n ): Promise<Result<InsertResult>> {\n if (Array.isArray(data)) {\n // TODO: Switch to NDJSON\n // FAST: Fire all HTTP requests concurrently instead of waiting for each one\n const promises = data.map((row) =>\n request<{ ok?: boolean; duplicate?: boolean }>(this._ctx, {\n method: \"POST\",\n path: `/v1/ingest?table=${encodeURIComponent(this._table)}`,\n body: row,\n signal: opts?.signal,\n }),\n );\n\n // TODO: with NDJSON/array version, need to rework how to show errors if only some/one fail\n const results = await Promise.all(promises);\n\n // Check if any of the concurrent requests failed\n for (const res of results) {\n if (res.error) return err(res.error);\n }\n return ok({ ok: true });\n }\n\n const { data: res, error } = await request<{ ok?: boolean; duplicate?: boolean }>(this._ctx, {\n method: \"POST\",\n path: `/v1/ingest?table=${encodeURIComponent(this._table)}`,\n body: data,\n signal: opts?.signal,\n });\n\n if (error) return err(error);\n const result: InsertResult = { ok: res?.ok ?? true };\n if (res?.duplicate != null) result.duplicate = res.duplicate;\n return ok(result);\n }\n\n /** Fetch the schema for this table. */\n async schema(opts?: { signal?: AbortSignal }): Promise<Result<TableSchema>> {\n const { data, error } = await request<TableSchema>(this._ctx, {\n method: \"GET\",\n path: `/v1/schema?table=${encodeURIComponent(this._table)}`,\n signal: opts?.signal,\n });\n if (error) return err(error);\n return ok(data!);\n }\n\n /** Subscribe to live events for this table. */\n stream(opts?: StreamOptions): StreamController<Row> {\n return this._createStream(this._table, opts);\n }\n}\n","import { DLQNamespace } from \"./dlq.js\";\nimport { PipeRef, PipesNamespace } from \"./pipes.js\";\nimport { PolicyNamespace } from \"./policy.js\";\nimport { SchemaNamespace } from \"./schema.js\";\nimport { sql } from \"./sql.js\";\nimport { StreamController } from \"./stream/controller.js\";\nimport { SSETransport } from \"./stream/sse.js\";\nimport { SysNamespace } from \"./sys.js\";\nimport { TableRef } from \"./table.js\";\nimport type { ClientConfig, Database, HttpContext, Result, StreamOptions } from \"./types.js\";\n\ntype TableName<DB> = DB extends Database ? Extract<keyof DB, string> : string;\ntype RowType<DB, T extends string> = DB extends Database\n ? T extends keyof DB\n ? DB[T]\n : Record<string, unknown>\n : Record<string, unknown>;\n\nexport class WaveHouseClient<DB extends Database = Database> {\n /** @internal */\n readonly _ctx: HttpContext;\n\n /** Schema introspection namespace. */\n readonly schema: SchemaNamespace;\n /** Access control policy namespace (admin). */\n readonly policy: PolicyNamespace;\n /** Dead Letter Queue namespace. */\n readonly dlq: DLQNamespace;\n /** System health/readiness namespace. */\n readonly sys: SysNamespace;\n /** Named query pipes admin namespace. */\n readonly pipes: PipesNamespace;\n\n constructor(config: ClientConfig<DB>) {\n this._ctx = {\n baseURL: config.baseURL.replace(/\\/+$/, \"\"),\n auth: config.auth,\n options: {\n maxRetries: config.options?.maxRetries ?? 2,\n },\n };\n\n this.schema = new SchemaNamespace(this._ctx);\n this.policy = new PolicyNamespace(this._ctx);\n this.dlq = new DLQNamespace(this._ctx, (table, opts) => this._createStream(table, opts));\n this.sys = new SysNamespace(this._ctx);\n this.pipes = new PipesNamespace(this._ctx);\n }\n\n /** Get a table reference for building queries, inserts, and streams. */\n from<T extends TableName<DB>>(table: T): TableRef<RowType<DB, T>> {\n return new TableRef<RowType<DB, T>>(this._ctx, table, (t, opts) =>\n this._createStream<RowType<DB, T>>(t, opts),\n );\n }\n\n /** Get a reference to a named query pipe. PromiseLike — `await` it to execute. */\n pipe<Row = Record<string, unknown>>(\n name: string,\n params?: Record<string, unknown>,\n ): PipeRef<Row> {\n return new PipeRef<Row>(this._ctx, name, params, (t, opts) => this._createStream<Row>(t, opts));\n }\n\n /**\n * Execute a raw SQL query against ClickHouse. Requires the admin role (the\n * configured `admin_role`, `\"admin\"` by default; there is no separate\n * `service` role). The endpoint proxies straight to ClickHouse's HTTP\n * interface so any ClickHouse-accepted SQL works; positional `?` param\n * binding is NOT supported — inline literals or use the structured query\n * builder for safe binding. See sql.ts for details.\n */\n sql<Row = Record<string, unknown>>(\n query: string,\n opts?: { signal?: AbortSignal },\n ): Promise<Result<Row[]>> {\n // Migration guard: the second argument used to be a positional-`?`\n // params array. TS callers get a compile-time error from the type\n // signature, but JS callers (or `any`-typed callsites) would silently\n // pass an array as `opts` and only discover the break via downstream\n // SQL errors. Throw a clear runtime error pointing at the migration.\n if (Array.isArray(opts)) {\n throw new Error(\n \"[WaveHouse SDK] client.sql(sql, params) was removed. The /v1/admin/query endpoint does not accept positional `?` params. Inline literals into the SQL, or use the structured query builder (wh.from(table)…) for safe binding from user input.\",\n );\n }\n return sql<Row>(this._ctx, query, opts);\n }\n\n /** @internal Create a stream for the given table. */\n private _createStream<T = Record<string, unknown>>(\n table: string,\n opts?: StreamOptions,\n ): StreamController<T> {\n if (typeof EventSource === \"undefined\") {\n // TODO: fallback method? polling?\n throw new Error(\n \"[WaveHouse SDK] Native EventSource is not available in this environment. \" +\n \"Please provide a global polyfill (e.g., `globalThis.EventSource = require('eventsource')`).\",\n );\n }\n\n const transport = new SSETransport<T>({\n baseURL: this._ctx.baseURL,\n table,\n since: opts?.since,\n auth: this._ctx.auth,\n });\n const controller = new StreamController<T>(transport);\n if (opts?.signal) controller.attachSignal(opts.signal);\n return controller;\n }\n}\n\n/** Create a new WaveHouse client instance. */\nexport function createClient<DB extends Database = Database>(\n config: ClientConfig<DB>,\n): WaveHouseClient<DB> {\n return new WaveHouseClient(config);\n}\n"],"mappings":"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","names":["err","res"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wavehouse/sdk",
3
- "version": "0.0.0-dev.0f8826c",
3
+ "version": "0.0.0-dev.h825a5d7fa405",
4
4
  "description": "TypeScript SDK for WaveHouse — schema-aware real-time API gateway for ClickHouse",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",