@wavehouse/sdk 0.1.1 → 0.2.0

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/dist/index.d.cts CHANGED
@@ -241,7 +241,22 @@ interface Column {
241
241
  name: string;
242
242
  type: string;
243
243
  is_nullable: boolean;
244
+ /** Whether the column declares any default at all — see `default_kind`. */
244
245
  has_default: boolean;
246
+ /**
247
+ * How the default is declared, when there is one: `DEFAULT`, `MATERIALIZED`,
248
+ * `ALIAS` or `EPHEMERAL`. Omitted when the column declares none.
249
+ *
250
+ * `MATERIALIZED` and `ALIAS` columns are computed by ClickHouse and cannot be
251
+ * inserted — a record naming one is rejected — so they never appear in an
252
+ * ingest envelope or an SSE `schema` frame, though they are still reported
253
+ * here and are still queryable.
254
+ */
255
+ default_kind?: string;
256
+ /** 1-based ordinal in the table's declaration order — the order `columns` itself is in. Always present. */
257
+ position: number;
258
+ /** The column's DEFAULT expression, absent when it declares none. */
259
+ default_expression?: string;
245
260
  }
246
261
  interface TableSchema {
247
262
  name: string;
@@ -301,15 +316,21 @@ interface Policy {
301
316
  admin_role?: string;
302
317
  tables: Record<string, TablePolicy>;
303
318
  }
304
- interface TablePolicy {
305
- select?: Record<string, RolePermissions>;
306
- insert?: Record<string, RolePermissions>;
307
- }
319
+ /**
320
+ * Access control for one table, keyed by role name. A role appears once per
321
+ * table and states what it may do; omit `select` to deny reads, omit `insert`
322
+ * to deny writes.
323
+ */
324
+ type TablePolicy = Record<string, RolePermissions>;
308
325
  interface RolePermissions {
326
+ select?: SelectPermissions;
327
+ insert?: InsertPermissions;
328
+ }
329
+ /** A role's read grant on a table. */
330
+ interface SelectPermissions {
309
331
  allow_columns?: string[];
310
332
  deny_columns?: string[];
311
333
  filter?: Record<string, PolicyFilter>;
312
- check?: Record<string, PolicyFilter>;
313
334
  allowed_aggregations?: string[];
314
335
  denied_aggregations?: string[];
315
336
  /** Caps the query result LIMIT. 0 = no limit. */
@@ -329,6 +350,12 @@ interface RolePermissions {
329
350
  */
330
351
  max_memory_usage?: number | string;
331
352
  }
353
+ /** A role's write grant on a table. */
354
+ interface InsertPermissions {
355
+ allow_columns?: string[];
356
+ deny_columns?: string[];
357
+ check?: Record<string, PolicyFilter>;
358
+ }
332
359
  interface PolicyFilter {
333
360
  _eq?: string;
334
361
  _neq?: string;
@@ -336,8 +363,31 @@ interface PolicyFilter {
336
363
  _lt?: string;
337
364
  _in?: string;
338
365
  }
339
- interface ValidationResult {
340
- valid: boolean;
366
+ /** One validation finding from the server's settings directory. */
367
+ interface SettingsFinding {
368
+ severity: "error" | "warning";
369
+ /**
370
+ * Settings file the finding is about; absent for directory-level findings.
371
+ * In a directory of tenant folders it leads with the folder
372
+ * (`acme/policies.json`).
373
+ */
374
+ file?: string;
375
+ /** Dotted JSON path within the file; absent for whole-file findings. */
376
+ path?: string;
377
+ message: string;
378
+ }
379
+ /** Body of POST /v1/ops/settings/reload. */
380
+ interface SettingsReloadResult {
381
+ /**
382
+ * Whether everything the reload covered was adopted; false leaves the
383
+ * previous settings in effect. Over a directory of tenant folders false can
384
+ * mean adopted in part: the tenants with an error among their `findings`
385
+ * were not adopted and are no longer served, and the rest were — `findings`
386
+ * carries every folder's warnings too.
387
+ */
388
+ adopted: boolean;
389
+ /** Every finding from the validation pass (warnings included on success). */
390
+ findings: SettingsFinding[];
341
391
  }
342
392
  /**
343
393
  * Options for a single call, passed to `.fetch()`.
@@ -365,6 +415,24 @@ interface PipeRequestOptions {
365
415
  /** Not supported on pipes — pass `limit` as a pipe parameter instead. */
366
416
  limit?: never;
367
417
  }
418
+ /**
419
+ * Options for a call to one of the admin routes that address a tenant:
420
+ * `wh.pipes.list()`, `wh.pipes.get()`, `wh.settings.reload()`,
421
+ * `wh.schema.list()`, `wh.schema.refresh()`, `wh.from(t).schema()`,
422
+ * `wh.dlq.list()`, `wh.dlq.table()` and `wh.sql()`.
423
+ */
424
+ interface OpsRequestOptions {
425
+ signal?: AbortSignal;
426
+ /**
427
+ * The tenant the call addresses, sent as `?tenant=`. The admin routes ignore
428
+ * the `X-Tenant-ID` header, so `options.headers` cannot select one. Omitted,
429
+ * the reads, the refresh and `sql()` serve the default tenant (`0`) and
430
+ * `reload()` reloads every tenant. An id the server does not accept — the
431
+ * empty string included — is a `400`, never a silent fallback to the
432
+ * default.
433
+ */
434
+ tenant?: string;
435
+ }
368
436
  interface StreamOptions {
369
437
  since?: string;
370
438
  signal?: AbortSignal;
@@ -434,14 +502,13 @@ declare class DLQNamespace {
434
502
  private readonly _ctx;
435
503
  private readonly _createStream;
436
504
  constructor(ctx: HttpContext, createStream: CreateStreamFn$3);
437
- /** Get DLQ statistics (message counts per table). */
438
- list(opts?: {
439
- signal?: AbortSignal;
440
- }): Promise<Result<DLQStats>>;
441
- /** Get DLQ stats filtered by table name. */
442
- table(name: string, opts?: {
443
- signal?: AbortSignal;
444
- }): Promise<Result<DLQStats>>;
505
+ /**
506
+ * Get DLQ statistics (message counts per table) — of `opts.tenant`, the
507
+ * default tenant without it. A tenant with no dead-letter queue is a `404`.
508
+ */
509
+ list(opts?: OpsRequestOptions): Promise<Result<DLQStats>>;
510
+ /** Get DLQ stats filtered by table name — of `opts.tenant`, the default tenant without it. */
511
+ table(name: string, opts?: OpsRequestOptions): Promise<Result<DLQStats>>;
445
512
  /** Subscribe to live DLQ events. */
446
513
  stream(opts?: StreamOptions): StreamController;
447
514
  }
@@ -467,58 +534,63 @@ declare class PipeRef<Row = Record<string, unknown>> implements PromiseLike<Resu
467
534
  stream(opts?: StreamOptions): StreamController<Row>;
468
535
  then<TResult1 = Result<Row[]>, TResult2 = never>(onfulfilled?: ((value: Result<Row[]>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
469
536
  }
470
- /** Admin namespace for managing named query pipes. */
537
+ /**
538
+ * Admin namespace for reading named query pipes.
539
+ *
540
+ * Pipes are defined in the server's settings directory (`pipes.json`, with
541
+ * every `allowed_roles` entry declared in `roles.json`); the files are the only
542
+ * way to define or change a pipe. Edit the files and the server re-adopts them on change, on
543
+ * SIGHUP, or on `wh.settings.reload()` (POST /v1/ops/settings/reload).
544
+ */
471
545
  declare class PipesNamespace {
472
546
  private readonly _ctx;
473
547
  constructor(ctx: HttpContext);
474
- /** List all registered pipes. */
475
- list(opts?: {
476
- signal?: AbortSignal;
477
- }): Promise<Result<Pipe[]>>;
478
- /** Get a single pipe definition by name. */
479
- get(name: string, opts?: {
480
- signal?: AbortSignal;
481
- }): Promise<Result<Pipe>>;
482
- /** Create or update a pipe. */
483
- set(name: string, def: Omit<Pipe, "name">, opts?: {
484
- signal?: AbortSignal;
485
- }): Promise<Result<void>>;
486
- /** Delete a pipe by name. */
487
- delete(name: string, opts?: {
488
- signal?: AbortSignal;
489
- }): Promise<Result<void>>;
548
+ /** List all registered pipes — of `opts.tenant`, the default tenant without it. */
549
+ list(opts?: OpsRequestOptions): Promise<Result<Pipe[]>>;
550
+ /** Get a single pipe definition by name — of `opts.tenant`, the default tenant without it. */
551
+ get(name: string, opts?: OpsRequestOptions): Promise<Result<Pipe>>;
490
552
  }
491
553
 
492
- /** Namespace for access control policy management. Requires the admin role (the configured `admin_role`, `"admin"` by default). */
493
- declare class PolicyNamespace {
554
+ /** Namespace for schema introspection. */
555
+ declare class SchemaNamespace {
494
556
  private readonly _ctx;
495
557
  constructor(ctx: HttpContext);
496
- /** Get the current access control policy. */
497
- get(opts?: {
498
- signal?: AbortSignal;
499
- }): Promise<Result<Policy>>;
500
- /** Replace the entire access control policy. */
501
- set(policy: Policy, opts?: {
502
- signal?: AbortSignal;
503
- }): Promise<Result<void>>;
504
- /** Validate a policy without applying it (dry run). */
505
- validate(policy: Policy, opts?: {
506
- signal?: AbortSignal;
507
- }): Promise<Result<ValidationResult>>;
558
+ /**
559
+ * List all table schemas discovered from ClickHouse — `opts.tenant`'s, the
560
+ * default tenant's without it. A `503` with `Retry-After` is a tenant whose
561
+ * first discovery has not succeeded yet.
562
+ */
563
+ list(opts?: OpsRequestOptions): Promise<Result<Schemas>>;
564
+ /**
565
+ * Force a schema refresh from ClickHouse system.columns — of `opts.tenant`,
566
+ * the default tenant without it.
567
+ */
568
+ refresh(opts?: OpsRequestOptions): Promise<Result<void>>;
508
569
  }
509
570
 
510
- /** Namespace for schema introspection. */
511
- declare class SchemaNamespace {
571
+ /**
572
+ * Namespace for the server's hot-reloadable settings directory. Requires the
573
+ * admin role (the configured `admin_role`, `"admin"` by default).
574
+ *
575
+ * Policy (`policies.json`), roles (`roles.json`), and pipes (`pipes.json`)
576
+ * are defined in that directory; files are the only write path. The server
577
+ * re-adopts them on file change and on SIGHUP, and `reload()` triggers the
578
+ * same path on demand.
579
+ */
580
+ declare class SettingsNamespace {
512
581
  private readonly _ctx;
513
582
  constructor(ctx: HttpContext);
514
- /** List all table schemas discovered from ClickHouse. */
515
- list(opts?: {
516
- signal?: AbortSignal;
517
- }): Promise<Result<Schemas>>;
518
- /** Force a schema refresh from ClickHouse system.columns. */
519
- refresh(opts?: {
520
- signal?: AbortSignal;
521
- }): Promise<Result<void>>;
583
+ /**
584
+ * Re-validate and adopt the settings directory (POST /v1/ops/settings/reload).
585
+ * Resolves with `{ adopted: true, findings }` when adopted (warnings
586
+ * included); a rejected directory is a 422 error whose `details` carries the
587
+ * same `{ adopted: false, findings }` body, and the previous settings stay
588
+ * in effect.
589
+ *
590
+ * `opts.tenant` reloads that tenant's folder alone; without it the whole
591
+ * directory is reloaded.
592
+ */
593
+ reload(opts?: OpsRequestOptions): Promise<Result<SettingsReloadResult>>;
522
594
  }
523
595
 
524
596
  /** Namespace for the SDK's content-free server-online check. */
@@ -663,8 +735,10 @@ declare class TableRef<Row = Record<string, unknown>> {
663
735
  * rest of the batch — per-record outcomes come back in the result
664
736
  * (`failed` / `results`), and `ok` is true only when every record succeeded.
665
737
  *
666
- * The array path sends one request regardless of size; bounded-concurrency
667
- * chunking of very large arrays is tracked separately (#196). For NDJSON you
738
+ * The array path sends one request regardless of size, so it is bound by the
739
+ * server's 16 MiB request-body cap (an over-cap array is a `413` with nothing
740
+ * ingested); bounded-concurrency chunking of very large arrays is tracked
741
+ * separately (#196). For NDJSON you
668
742
  * already have (a file or stream), use {@link insertNDJSON}.
669
743
  */
670
744
  insert(data: Partial<Row> | Partial<Row>[], opts?: {
@@ -676,9 +750,11 @@ declare class TableRef<Row = Record<string, unknown>> {
676
750
  * file or a stream produced by another system. For in-memory rows, prefer
677
751
  * {@link insert}.
678
752
  *
679
- * Non-string sources are read fully into memory before sending (the server
680
- * streams the parse). Returns the same per-record batch summary as an array
681
- * `insert`.
753
+ * Non-string sources are read fully into memory before sending. The server
754
+ * buffers the whole body too, so the request-body cap applies to NDJSON
755
+ * exactly as to any other shape — an upload over it is a `413` with nothing
756
+ * ingested, and must be split across several calls. Returns the same
757
+ * per-record batch summary as an array `insert`.
682
758
  */
683
759
  insertNDJSON(source: NDJSONSource, opts?: {
684
760
  signal?: AbortSignal;
@@ -690,10 +766,8 @@ declare class TableRef<Row = Record<string, unknown>> {
690
766
  * as the success arm with `ok = failed === 0`.
691
767
  */
692
768
  private _sendNDJSON;
693
- /** Fetch the schema for this table. */
694
- schema(opts?: {
695
- signal?: AbortSignal;
696
- }): Promise<Result<TableSchema>>;
769
+ /** Fetch the schema for this table — under `opts.tenant`, the default tenant without it. */
770
+ schema(opts?: OpsRequestOptions): Promise<Result<TableSchema>>;
697
771
  /** Subscribe to live events for this table. */
698
772
  stream(opts?: StreamOptions): StreamController<Row>;
699
773
  }
@@ -705,14 +779,14 @@ declare class WaveHouseClient<DB extends Database = Database> {
705
779
  readonly _ctx: HttpContext;
706
780
  /** Schema introspection namespace. */
707
781
  readonly schema: SchemaNamespace;
708
- /** Access control policy namespace (admin). */
709
- readonly policy: PolicyNamespace;
710
782
  /** Dead Letter Queue namespace. */
711
783
  readonly dlq: DLQNamespace;
712
784
  /** System health/readiness namespace. */
713
785
  readonly sys: SysNamespace;
714
786
  /** Named query pipes admin namespace. */
715
787
  readonly pipes: PipesNamespace;
788
+ /** Settings directory namespace (admin). */
789
+ readonly settings: SettingsNamespace;
716
790
  constructor(config: ClientConfig<DB>);
717
791
  /** Get a table reference for building queries, inserts, and streams. */
718
792
  from<T extends TableName<DB>>(table: T): TableRef<RowType<DB, T>>;
@@ -724,15 +798,15 @@ declare class WaveHouseClient<DB extends Database = Database> {
724
798
  * `service` role). The endpoint proxies straight to ClickHouse's HTTP
725
799
  * interface so any ClickHouse-accepted SQL works; positional `?` param
726
800
  * binding is NOT supported — inline literals or use the structured query
727
- * builder for safe binding. See sql.ts for details.
801
+ * builder for safe binding. See sql.ts for details. `opts.tenant` names the
802
+ * tenant whose ClickHouse the SQL runs against, the default tenant without
803
+ * it.
728
804
  */
729
- sql<Row = Record<string, unknown>>(query: string, opts?: {
730
- signal?: AbortSignal;
731
- }): Promise<Result<Row[]>>;
805
+ sql<Row = Record<string, unknown>>(query: string, opts?: OpsRequestOptions): Promise<Result<Row[]>>;
732
806
  /** @internal Create a stream for the given table. */
733
807
  private _createStream;
734
808
  }
735
809
  /** Create a new WaveHouse client instance. */
736
810
  declare function createClient<DB extends Database = Database>(config: ClientConfig<DB>): WaveHouseClient<DB>;
737
811
 
738
- export { type Aggregation, type ClientConfig, type ClientOptions, type Column, DLQNamespace, type DLQStats, type Database, type FetchLike, type FilterOp, type InsertRecordResult, type InsertResult, LiveQuery, type NDJSONSource, type OrderClause, type ParamDef, type Pipe, PipeRef, type PipeRequestOptions, PipesNamespace, type Policy, type PolicyFilter, PolicyNamespace, QueryBuilder, type QueryFilter, type RequestOptions, type Result, type RolePermissions, SchemaNamespace, type Schemas, StreamController, type StreamEvent, type StreamOptions, type StreamStatus, type StreamSubscriber, type StructuredQuery, SysNamespace, type TablePolicy, TableRef, type TableSchema, type TimeRange, type ValidationResult, WaveHouseClient, type WaveHouseError, createClient };
812
+ export { type Aggregation, type ClientConfig, type ClientOptions, type Column, DLQNamespace, type DLQStats, type Database, type FetchLike, type FilterOp, type InsertPermissions, type InsertRecordResult, type InsertResult, LiveQuery, type NDJSONSource, type OpsRequestOptions, type OrderClause, type ParamDef, type Pipe, PipeRef, type PipeRequestOptions, PipesNamespace, type Policy, type PolicyFilter, QueryBuilder, type QueryFilter, type RequestOptions, type Result, type RolePermissions, SchemaNamespace, type Schemas, type SelectPermissions, type SettingsFinding, SettingsNamespace, type SettingsReloadResult, StreamController, type StreamEvent, type StreamOptions, type StreamStatus, type StreamSubscriber, type StructuredQuery, SysNamespace, type TablePolicy, TableRef, type TableSchema, type TimeRange, WaveHouseClient, type WaveHouseError, createClient };
package/dist/index.d.ts CHANGED
@@ -241,7 +241,22 @@ interface Column {
241
241
  name: string;
242
242
  type: string;
243
243
  is_nullable: boolean;
244
+ /** Whether the column declares any default at all — see `default_kind`. */
244
245
  has_default: boolean;
246
+ /**
247
+ * How the default is declared, when there is one: `DEFAULT`, `MATERIALIZED`,
248
+ * `ALIAS` or `EPHEMERAL`. Omitted when the column declares none.
249
+ *
250
+ * `MATERIALIZED` and `ALIAS` columns are computed by ClickHouse and cannot be
251
+ * inserted — a record naming one is rejected — so they never appear in an
252
+ * ingest envelope or an SSE `schema` frame, though they are still reported
253
+ * here and are still queryable.
254
+ */
255
+ default_kind?: string;
256
+ /** 1-based ordinal in the table's declaration order — the order `columns` itself is in. Always present. */
257
+ position: number;
258
+ /** The column's DEFAULT expression, absent when it declares none. */
259
+ default_expression?: string;
245
260
  }
246
261
  interface TableSchema {
247
262
  name: string;
@@ -301,15 +316,21 @@ interface Policy {
301
316
  admin_role?: string;
302
317
  tables: Record<string, TablePolicy>;
303
318
  }
304
- interface TablePolicy {
305
- select?: Record<string, RolePermissions>;
306
- insert?: Record<string, RolePermissions>;
307
- }
319
+ /**
320
+ * Access control for one table, keyed by role name. A role appears once per
321
+ * table and states what it may do; omit `select` to deny reads, omit `insert`
322
+ * to deny writes.
323
+ */
324
+ type TablePolicy = Record<string, RolePermissions>;
308
325
  interface RolePermissions {
326
+ select?: SelectPermissions;
327
+ insert?: InsertPermissions;
328
+ }
329
+ /** A role's read grant on a table. */
330
+ interface SelectPermissions {
309
331
  allow_columns?: string[];
310
332
  deny_columns?: string[];
311
333
  filter?: Record<string, PolicyFilter>;
312
- check?: Record<string, PolicyFilter>;
313
334
  allowed_aggregations?: string[];
314
335
  denied_aggregations?: string[];
315
336
  /** Caps the query result LIMIT. 0 = no limit. */
@@ -329,6 +350,12 @@ interface RolePermissions {
329
350
  */
330
351
  max_memory_usage?: number | string;
331
352
  }
353
+ /** A role's write grant on a table. */
354
+ interface InsertPermissions {
355
+ allow_columns?: string[];
356
+ deny_columns?: string[];
357
+ check?: Record<string, PolicyFilter>;
358
+ }
332
359
  interface PolicyFilter {
333
360
  _eq?: string;
334
361
  _neq?: string;
@@ -336,8 +363,31 @@ interface PolicyFilter {
336
363
  _lt?: string;
337
364
  _in?: string;
338
365
  }
339
- interface ValidationResult {
340
- valid: boolean;
366
+ /** One validation finding from the server's settings directory. */
367
+ interface SettingsFinding {
368
+ severity: "error" | "warning";
369
+ /**
370
+ * Settings file the finding is about; absent for directory-level findings.
371
+ * In a directory of tenant folders it leads with the folder
372
+ * (`acme/policies.json`).
373
+ */
374
+ file?: string;
375
+ /** Dotted JSON path within the file; absent for whole-file findings. */
376
+ path?: string;
377
+ message: string;
378
+ }
379
+ /** Body of POST /v1/ops/settings/reload. */
380
+ interface SettingsReloadResult {
381
+ /**
382
+ * Whether everything the reload covered was adopted; false leaves the
383
+ * previous settings in effect. Over a directory of tenant folders false can
384
+ * mean adopted in part: the tenants with an error among their `findings`
385
+ * were not adopted and are no longer served, and the rest were — `findings`
386
+ * carries every folder's warnings too.
387
+ */
388
+ adopted: boolean;
389
+ /** Every finding from the validation pass (warnings included on success). */
390
+ findings: SettingsFinding[];
341
391
  }
342
392
  /**
343
393
  * Options for a single call, passed to `.fetch()`.
@@ -365,6 +415,24 @@ interface PipeRequestOptions {
365
415
  /** Not supported on pipes — pass `limit` as a pipe parameter instead. */
366
416
  limit?: never;
367
417
  }
418
+ /**
419
+ * Options for a call to one of the admin routes that address a tenant:
420
+ * `wh.pipes.list()`, `wh.pipes.get()`, `wh.settings.reload()`,
421
+ * `wh.schema.list()`, `wh.schema.refresh()`, `wh.from(t).schema()`,
422
+ * `wh.dlq.list()`, `wh.dlq.table()` and `wh.sql()`.
423
+ */
424
+ interface OpsRequestOptions {
425
+ signal?: AbortSignal;
426
+ /**
427
+ * The tenant the call addresses, sent as `?tenant=`. The admin routes ignore
428
+ * the `X-Tenant-ID` header, so `options.headers` cannot select one. Omitted,
429
+ * the reads, the refresh and `sql()` serve the default tenant (`0`) and
430
+ * `reload()` reloads every tenant. An id the server does not accept — the
431
+ * empty string included — is a `400`, never a silent fallback to the
432
+ * default.
433
+ */
434
+ tenant?: string;
435
+ }
368
436
  interface StreamOptions {
369
437
  since?: string;
370
438
  signal?: AbortSignal;
@@ -434,14 +502,13 @@ declare class DLQNamespace {
434
502
  private readonly _ctx;
435
503
  private readonly _createStream;
436
504
  constructor(ctx: HttpContext, createStream: CreateStreamFn$3);
437
- /** Get DLQ statistics (message counts per table). */
438
- list(opts?: {
439
- signal?: AbortSignal;
440
- }): Promise<Result<DLQStats>>;
441
- /** Get DLQ stats filtered by table name. */
442
- table(name: string, opts?: {
443
- signal?: AbortSignal;
444
- }): Promise<Result<DLQStats>>;
505
+ /**
506
+ * Get DLQ statistics (message counts per table) — of `opts.tenant`, the
507
+ * default tenant without it. A tenant with no dead-letter queue is a `404`.
508
+ */
509
+ list(opts?: OpsRequestOptions): Promise<Result<DLQStats>>;
510
+ /** Get DLQ stats filtered by table name — of `opts.tenant`, the default tenant without it. */
511
+ table(name: string, opts?: OpsRequestOptions): Promise<Result<DLQStats>>;
445
512
  /** Subscribe to live DLQ events. */
446
513
  stream(opts?: StreamOptions): StreamController;
447
514
  }
@@ -467,58 +534,63 @@ declare class PipeRef<Row = Record<string, unknown>> implements PromiseLike<Resu
467
534
  stream(opts?: StreamOptions): StreamController<Row>;
468
535
  then<TResult1 = Result<Row[]>, TResult2 = never>(onfulfilled?: ((value: Result<Row[]>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
469
536
  }
470
- /** Admin namespace for managing named query pipes. */
537
+ /**
538
+ * Admin namespace for reading named query pipes.
539
+ *
540
+ * Pipes are defined in the server's settings directory (`pipes.json`, with
541
+ * every `allowed_roles` entry declared in `roles.json`); the files are the only
542
+ * way to define or change a pipe. Edit the files and the server re-adopts them on change, on
543
+ * SIGHUP, or on `wh.settings.reload()` (POST /v1/ops/settings/reload).
544
+ */
471
545
  declare class PipesNamespace {
472
546
  private readonly _ctx;
473
547
  constructor(ctx: HttpContext);
474
- /** List all registered pipes. */
475
- list(opts?: {
476
- signal?: AbortSignal;
477
- }): Promise<Result<Pipe[]>>;
478
- /** Get a single pipe definition by name. */
479
- get(name: string, opts?: {
480
- signal?: AbortSignal;
481
- }): Promise<Result<Pipe>>;
482
- /** Create or update a pipe. */
483
- set(name: string, def: Omit<Pipe, "name">, opts?: {
484
- signal?: AbortSignal;
485
- }): Promise<Result<void>>;
486
- /** Delete a pipe by name. */
487
- delete(name: string, opts?: {
488
- signal?: AbortSignal;
489
- }): Promise<Result<void>>;
548
+ /** List all registered pipes — of `opts.tenant`, the default tenant without it. */
549
+ list(opts?: OpsRequestOptions): Promise<Result<Pipe[]>>;
550
+ /** Get a single pipe definition by name — of `opts.tenant`, the default tenant without it. */
551
+ get(name: string, opts?: OpsRequestOptions): Promise<Result<Pipe>>;
490
552
  }
491
553
 
492
- /** Namespace for access control policy management. Requires the admin role (the configured `admin_role`, `"admin"` by default). */
493
- declare class PolicyNamespace {
554
+ /** Namespace for schema introspection. */
555
+ declare class SchemaNamespace {
494
556
  private readonly _ctx;
495
557
  constructor(ctx: HttpContext);
496
- /** Get the current access control policy. */
497
- get(opts?: {
498
- signal?: AbortSignal;
499
- }): Promise<Result<Policy>>;
500
- /** Replace the entire access control policy. */
501
- set(policy: Policy, opts?: {
502
- signal?: AbortSignal;
503
- }): Promise<Result<void>>;
504
- /** Validate a policy without applying it (dry run). */
505
- validate(policy: Policy, opts?: {
506
- signal?: AbortSignal;
507
- }): Promise<Result<ValidationResult>>;
558
+ /**
559
+ * List all table schemas discovered from ClickHouse — `opts.tenant`'s, the
560
+ * default tenant's without it. A `503` with `Retry-After` is a tenant whose
561
+ * first discovery has not succeeded yet.
562
+ */
563
+ list(opts?: OpsRequestOptions): Promise<Result<Schemas>>;
564
+ /**
565
+ * Force a schema refresh from ClickHouse system.columns — of `opts.tenant`,
566
+ * the default tenant without it.
567
+ */
568
+ refresh(opts?: OpsRequestOptions): Promise<Result<void>>;
508
569
  }
509
570
 
510
- /** Namespace for schema introspection. */
511
- declare class SchemaNamespace {
571
+ /**
572
+ * Namespace for the server's hot-reloadable settings directory. Requires the
573
+ * admin role (the configured `admin_role`, `"admin"` by default).
574
+ *
575
+ * Policy (`policies.json`), roles (`roles.json`), and pipes (`pipes.json`)
576
+ * are defined in that directory; files are the only write path. The server
577
+ * re-adopts them on file change and on SIGHUP, and `reload()` triggers the
578
+ * same path on demand.
579
+ */
580
+ declare class SettingsNamespace {
512
581
  private readonly _ctx;
513
582
  constructor(ctx: HttpContext);
514
- /** List all table schemas discovered from ClickHouse. */
515
- list(opts?: {
516
- signal?: AbortSignal;
517
- }): Promise<Result<Schemas>>;
518
- /** Force a schema refresh from ClickHouse system.columns. */
519
- refresh(opts?: {
520
- signal?: AbortSignal;
521
- }): Promise<Result<void>>;
583
+ /**
584
+ * Re-validate and adopt the settings directory (POST /v1/ops/settings/reload).
585
+ * Resolves with `{ adopted: true, findings }` when adopted (warnings
586
+ * included); a rejected directory is a 422 error whose `details` carries the
587
+ * same `{ adopted: false, findings }` body, and the previous settings stay
588
+ * in effect.
589
+ *
590
+ * `opts.tenant` reloads that tenant's folder alone; without it the whole
591
+ * directory is reloaded.
592
+ */
593
+ reload(opts?: OpsRequestOptions): Promise<Result<SettingsReloadResult>>;
522
594
  }
523
595
 
524
596
  /** Namespace for the SDK's content-free server-online check. */
@@ -663,8 +735,10 @@ declare class TableRef<Row = Record<string, unknown>> {
663
735
  * rest of the batch — per-record outcomes come back in the result
664
736
  * (`failed` / `results`), and `ok` is true only when every record succeeded.
665
737
  *
666
- * The array path sends one request regardless of size; bounded-concurrency
667
- * chunking of very large arrays is tracked separately (#196). For NDJSON you
738
+ * The array path sends one request regardless of size, so it is bound by the
739
+ * server's 16 MiB request-body cap (an over-cap array is a `413` with nothing
740
+ * ingested); bounded-concurrency chunking of very large arrays is tracked
741
+ * separately (#196). For NDJSON you
668
742
  * already have (a file or stream), use {@link insertNDJSON}.
669
743
  */
670
744
  insert(data: Partial<Row> | Partial<Row>[], opts?: {
@@ -676,9 +750,11 @@ declare class TableRef<Row = Record<string, unknown>> {
676
750
  * file or a stream produced by another system. For in-memory rows, prefer
677
751
  * {@link insert}.
678
752
  *
679
- * Non-string sources are read fully into memory before sending (the server
680
- * streams the parse). Returns the same per-record batch summary as an array
681
- * `insert`.
753
+ * Non-string sources are read fully into memory before sending. The server
754
+ * buffers the whole body too, so the request-body cap applies to NDJSON
755
+ * exactly as to any other shape — an upload over it is a `413` with nothing
756
+ * ingested, and must be split across several calls. Returns the same
757
+ * per-record batch summary as an array `insert`.
682
758
  */
683
759
  insertNDJSON(source: NDJSONSource, opts?: {
684
760
  signal?: AbortSignal;
@@ -690,10 +766,8 @@ declare class TableRef<Row = Record<string, unknown>> {
690
766
  * as the success arm with `ok = failed === 0`.
691
767
  */
692
768
  private _sendNDJSON;
693
- /** Fetch the schema for this table. */
694
- schema(opts?: {
695
- signal?: AbortSignal;
696
- }): Promise<Result<TableSchema>>;
769
+ /** Fetch the schema for this table — under `opts.tenant`, the default tenant without it. */
770
+ schema(opts?: OpsRequestOptions): Promise<Result<TableSchema>>;
697
771
  /** Subscribe to live events for this table. */
698
772
  stream(opts?: StreamOptions): StreamController<Row>;
699
773
  }
@@ -705,14 +779,14 @@ declare class WaveHouseClient<DB extends Database = Database> {
705
779
  readonly _ctx: HttpContext;
706
780
  /** Schema introspection namespace. */
707
781
  readonly schema: SchemaNamespace;
708
- /** Access control policy namespace (admin). */
709
- readonly policy: PolicyNamespace;
710
782
  /** Dead Letter Queue namespace. */
711
783
  readonly dlq: DLQNamespace;
712
784
  /** System health/readiness namespace. */
713
785
  readonly sys: SysNamespace;
714
786
  /** Named query pipes admin namespace. */
715
787
  readonly pipes: PipesNamespace;
788
+ /** Settings directory namespace (admin). */
789
+ readonly settings: SettingsNamespace;
716
790
  constructor(config: ClientConfig<DB>);
717
791
  /** Get a table reference for building queries, inserts, and streams. */
718
792
  from<T extends TableName<DB>>(table: T): TableRef<RowType<DB, T>>;
@@ -724,15 +798,15 @@ declare class WaveHouseClient<DB extends Database = Database> {
724
798
  * `service` role). The endpoint proxies straight to ClickHouse's HTTP
725
799
  * interface so any ClickHouse-accepted SQL works; positional `?` param
726
800
  * binding is NOT supported — inline literals or use the structured query
727
- * builder for safe binding. See sql.ts for details.
801
+ * builder for safe binding. See sql.ts for details. `opts.tenant` names the
802
+ * tenant whose ClickHouse the SQL runs against, the default tenant without
803
+ * it.
728
804
  */
729
- sql<Row = Record<string, unknown>>(query: string, opts?: {
730
- signal?: AbortSignal;
731
- }): Promise<Result<Row[]>>;
805
+ sql<Row = Record<string, unknown>>(query: string, opts?: OpsRequestOptions): Promise<Result<Row[]>>;
732
806
  /** @internal Create a stream for the given table. */
733
807
  private _createStream;
734
808
  }
735
809
  /** Create a new WaveHouse client instance. */
736
810
  declare function createClient<DB extends Database = Database>(config: ClientConfig<DB>): WaveHouseClient<DB>;
737
811
 
738
- export { type Aggregation, type ClientConfig, type ClientOptions, type Column, DLQNamespace, type DLQStats, type Database, type FetchLike, type FilterOp, type InsertRecordResult, type InsertResult, LiveQuery, type NDJSONSource, type OrderClause, type ParamDef, type Pipe, PipeRef, type PipeRequestOptions, PipesNamespace, type Policy, type PolicyFilter, PolicyNamespace, QueryBuilder, type QueryFilter, type RequestOptions, type Result, type RolePermissions, SchemaNamespace, type Schemas, StreamController, type StreamEvent, type StreamOptions, type StreamStatus, type StreamSubscriber, type StructuredQuery, SysNamespace, type TablePolicy, TableRef, type TableSchema, type TimeRange, type ValidationResult, WaveHouseClient, type WaveHouseError, createClient };
812
+ export { type Aggregation, type ClientConfig, type ClientOptions, type Column, DLQNamespace, type DLQStats, type Database, type FetchLike, type FilterOp, type InsertPermissions, type InsertRecordResult, type InsertResult, LiveQuery, type NDJSONSource, type OpsRequestOptions, type OrderClause, type ParamDef, type Pipe, PipeRef, type PipeRequestOptions, PipesNamespace, type Policy, type PolicyFilter, QueryBuilder, type QueryFilter, type RequestOptions, type Result, type RolePermissions, SchemaNamespace, type Schemas, type SelectPermissions, type SettingsFinding, SettingsNamespace, type SettingsReloadResult, StreamController, type StreamEvent, type StreamOptions, type StreamStatus, type StreamSubscriber, type StructuredQuery, SysNamespace, type TablePolicy, TableRef, type TableSchema, type TimeRange, WaveHouseClient, type WaveHouseError, createClient };