type AuthConfig = { type: 'none'; } | { type: 'bearer'; token: string; } | { type: 'header'; name: string; value: string; } | { type: 'custom'; getHeaders: () => Record | Promise>; }; interface NamespaceIdentifier { namespace: string[]; } interface NamespaceMetadata { properties: Record; } interface TableIdentifier { namespace: string[]; name: string; } /** * Primitive types in Iceberg - all represented as strings. * Parameterized types use string format: decimal(precision,scale) and fixed[length] * * Note: The OpenAPI spec defines PrimitiveType as `type: string`, so any string is valid. * We include known types for autocomplete, plus a catch-all for flexibility. */ type PrimitiveType = 'boolean' | 'int' | 'long' | 'float' | 'double' | 'string' | 'timestamp' | 'date' | 'time' | 'timestamptz' | 'uuid' | 'binary' | `decimal(${number},${number})` | `fixed[${number}]` | (string & {}); /** * Parse a decimal type string into its components. * Handles any whitespace formatting (e.g., "decimal(10,2)", "decimal(10, 2)", "decimal( 10 , 2 )"). * * @param type - The type string to parse * @returns Object with precision and scale, or null if not a valid decimal type */ declare function parseDecimalType(type: string): { precision: number; scale: number; } | null; /** * Parse a fixed type string into its length. * Handles any whitespace formatting (e.g., "fixed[16]", "fixed[ 16 ]"). * * @param type - The type string to parse * @returns Object with length, or null if not a valid fixed type */ declare function parseFixedType(type: string): { length: number; } | null; /** * Check if a type string is a decimal type. */ declare function isDecimalType(type: string): boolean; /** * Check if a type string is a fixed type. */ declare function isFixedType(type: string): boolean; /** * Compare two Iceberg type strings for equality, ignoring whitespace differences. * This is useful when comparing types from user input vs catalog responses, * as catalogs may normalize whitespace differently. * * @param a - First type string * @param b - Second type string * @returns true if the types are equivalent */ declare function typesEqual(a: string, b: string): boolean; /** * Struct type - a nested structure containing fields. * Used for nested records within a field. */ interface StructType { type: 'struct'; fields: StructField[]; } /** * List type - an array of elements. */ interface ListType { type: 'list'; 'element-id': number; element: IcebergType; 'element-required': boolean; } /** * Map type - a key-value mapping. */ interface MapType { type: 'map'; 'key-id': number; key: IcebergType; 'value-id': number; value: IcebergType; 'value-required': boolean; } /** * Union of all Iceberg types. * Can be a primitive type (string) or a complex type (struct, list, map). */ type IcebergType = PrimitiveType | StructType | ListType | MapType; /** * Primitive type values for default values. * Represents the possible values for initial-default and write-default. */ type PrimitiveTypeValue = boolean | number | string; /** * A field within a struct (used in nested StructType). */ interface StructField { id: number; name: string; type: IcebergType; required: boolean; doc?: string; 'initial-default'?: PrimitiveTypeValue; 'write-default'?: PrimitiveTypeValue; } /** * A field within a table schema (top-level). * Equivalent to StructField but kept for backwards compatibility. */ interface TableField { id: number; name: string; type: IcebergType; required: boolean; doc?: string; 'initial-default'?: PrimitiveTypeValue; 'write-default'?: PrimitiveTypeValue; } interface TableSchema { type: 'struct'; fields: TableField[]; 'schema-id'?: number; 'identifier-field-ids'?: number[]; } interface PartitionField { 'source-id': number; 'field-id'?: number; name: string; transform: string; } interface PartitionSpec { 'spec-id'?: number; fields: PartitionField[]; } interface SortField { 'source-id': number; transform: string; direction: 'asc' | 'desc'; 'null-order': 'nulls-first' | 'nulls-last'; } interface SortOrder { 'order-id': number; fields: SortField[]; } interface SnapshotReference { type: 'tag' | 'branch'; 'snapshot-id': number; 'max-ref-age-ms'?: number; 'max-snapshot-age-ms'?: number; 'min-snapshots-to-keep'?: number; } interface Snapshot { 'snapshot-id': number; 'parent-snapshot-id'?: number; 'sequence-number'?: number; 'timestamp-ms': number; 'manifest-list': string; summary: { operation: 'append' | 'replace' | 'overwrite' | 'delete'; [key: string]: string; }; 'schema-id'?: number; 'first-row-id'?: number; 'added-rows'?: number; } interface BlobMetadata { type: string; 'snapshot-id': number; 'sequence-number': number; fields: number[]; properties?: Record; } interface StatisticsFile { 'snapshot-id': number; 'statistics-path': string; 'file-size-in-bytes': number; 'file-footer-size-in-bytes': number; 'blob-metadata': BlobMetadata[]; } interface PartitionStatisticsFile { 'snapshot-id': number; 'statistics-path': string; 'file-size-in-bytes': number; } interface EncryptedKey { 'key-id': string; 'encrypted-key-metadata': string; 'encrypted-by-id'?: string; properties?: Record; } interface CreateTableRequest { name: string; schema: TableSchema; location?: string; 'partition-spec'?: PartitionSpec; 'write-order'?: SortOrder; properties?: Record; 'stage-create'?: boolean; } interface RegisterTableRequest { name: string; 'metadata-location': string; overwrite?: boolean; } interface RenameTableRequest { source: TableIdentifier; destination: TableIdentifier; } /** * Spec-aligned table commit request shape: requirements + updates arrays. * Used by `updateTable` / `commitTable`. * * Both `requirements` and `updates` are required by the spec — pass an empty * array if there are no preconditions to assert. */ interface CommitTableRequest { identifier?: TableIdentifier; requirements: TableRequirement[]; updates: TableUpdate[]; } /** * @deprecated Use `CommitTableRequest` (with `updates` and optional `requirements`) instead. * This alias is kept for callers migrating from 0.x; new code should use the spec-aligned shape. */ type UpdateTableRequest = CommitTableRequest; interface AssignUUIDUpdate { action: 'assign-uuid'; uuid: string; } interface UpgradeFormatVersionUpdate { action: 'upgrade-format-version'; 'format-version': number; } interface AddSchemaUpdate { action: 'add-schema'; schema: TableSchema; /** @deprecated server-managed; included for backward compat with older catalogs */ 'last-column-id'?: number; } interface SetCurrentSchemaUpdate { action: 'set-current-schema'; 'schema-id': number; } interface AddPartitionSpecUpdate { action: 'add-spec'; spec: PartitionSpec; } interface SetDefaultSpecUpdate { action: 'set-default-spec'; 'spec-id': number; } interface AddSortOrderUpdate { action: 'add-sort-order'; 'sort-order': SortOrder; } interface SetDefaultSortOrderUpdate { action: 'set-default-sort-order'; 'sort-order-id': number; } interface AddSnapshotUpdate { action: 'add-snapshot'; snapshot: Snapshot; } interface SetSnapshotRefUpdate extends SnapshotReference { action: 'set-snapshot-ref'; 'ref-name': string; } interface RemoveSnapshotsUpdate { action: 'remove-snapshots'; 'snapshot-ids': number[]; } interface RemoveSnapshotRefUpdate { action: 'remove-snapshot-ref'; 'ref-name': string; } interface SetLocationUpdate { action: 'set-location'; location: string; } interface SetPropertiesUpdate { action: 'set-properties'; updates: Record; } interface RemovePropertiesUpdate { action: 'remove-properties'; removals: string[]; } interface SetStatisticsUpdate { action: 'set-statistics'; statistics: StatisticsFile; /** @deprecated derive from `statistics.snapshot-id` */ 'snapshot-id'?: number; } interface RemoveStatisticsUpdate { action: 'remove-statistics'; 'snapshot-id': number; } interface SetPartitionStatisticsUpdate { action: 'set-partition-statistics'; 'partition-statistics': PartitionStatisticsFile; } interface RemovePartitionStatisticsUpdate { action: 'remove-partition-statistics'; 'snapshot-id': number; } interface RemovePartitionSpecsUpdate { action: 'remove-partition-specs'; 'spec-ids': number[]; } interface RemoveSchemasUpdate { action: 'remove-schemas'; 'schema-ids': number[]; } interface AddEncryptionKeyUpdate { action: 'add-encryption-key'; 'encryption-key': EncryptedKey; } interface RemoveEncryptionKeyUpdate { action: 'remove-encryption-key'; 'key-id': string; } type TableUpdate = AssignUUIDUpdate | UpgradeFormatVersionUpdate | AddSchemaUpdate | SetCurrentSchemaUpdate | AddPartitionSpecUpdate | SetDefaultSpecUpdate | AddSortOrderUpdate | SetDefaultSortOrderUpdate | AddSnapshotUpdate | SetSnapshotRefUpdate | RemoveSnapshotsUpdate | RemoveSnapshotRefUpdate | SetLocationUpdate | SetPropertiesUpdate | RemovePropertiesUpdate | SetStatisticsUpdate | RemoveStatisticsUpdate | SetPartitionStatisticsUpdate | RemovePartitionStatisticsUpdate | RemovePartitionSpecsUpdate | RemoveSchemasUpdate | AddEncryptionKeyUpdate | RemoveEncryptionKeyUpdate; interface AssertCreate { type: 'assert-create'; } interface AssertTableUUID { type: 'assert-table-uuid'; uuid: string; } interface AssertRefSnapshotId { type: 'assert-ref-snapshot-id'; ref: string; 'snapshot-id': number | null; } interface AssertLastAssignedFieldId { type: 'assert-last-assigned-field-id'; 'last-assigned-field-id': number; } interface AssertCurrentSchemaId { type: 'assert-current-schema-id'; 'current-schema-id': number; } interface AssertLastAssignedPartitionId { type: 'assert-last-assigned-partition-id'; 'last-assigned-partition-id': number; } interface AssertDefaultSpecId { type: 'assert-default-spec-id'; 'default-spec-id': number; } interface AssertDefaultSortOrderId { type: 'assert-default-sort-order-id'; 'default-sort-order-id': number; } type TableRequirement = AssertCreate | AssertTableUUID | AssertRefSnapshotId | AssertLastAssignedFieldId | AssertCurrentSchemaId | AssertLastAssignedPartitionId | AssertDefaultSpecId | AssertDefaultSortOrderId; interface DropTableRequest { purge?: boolean; } interface TableMetadata { 'format-version': number; 'table-uuid': string; location?: string; 'last-updated-ms'?: number; 'last-column-id'?: number; schemas: TableSchema[]; 'current-schema-id': number; 'partition-specs': PartitionSpec[]; 'default-spec-id'?: number; 'last-partition-id'?: number; 'sort-orders': SortOrder[]; 'default-sort-order-id'?: number; properties: Record; 'metadata-location'?: string; 'current-snapshot-id'?: number; snapshots?: Snapshot[]; 'snapshot-log'?: { 'snapshot-id': number; 'timestamp-ms': number; }[]; 'metadata-log'?: { 'metadata-file': string; 'timestamp-ms': number; }[]; refs?: Record; 'last-sequence-number'?: number; 'next-row-id'?: number; statistics?: StatisticsFile[]; 'partition-statistics'?: PartitionStatisticsFile[]; 'encryption-keys'?: EncryptedKey[]; /** Optional name field returned by some catalogs */ name?: string; } interface StorageCredential { prefix: string; config: Record; } interface CreateNamespaceRequest { namespace: string[]; properties?: Record; } interface CreateNamespaceResponse { namespace: string[]; properties?: Record; } interface GetNamespaceResponse { namespace: string[]; properties?: Record | null; } interface UpdateNamespacePropertiesRequest { removals?: string[]; updates?: Record; } interface UpdateNamespacePropertiesResponse { updated: string[]; removed: string[]; missing?: string[] | null; } interface ListNamespacesResponse { namespaces?: string[][]; 'next-page-token'?: string | null; } interface ListTablesResponse { identifiers?: TableIdentifier[]; 'next-page-token'?: string | null; } /** * Spec-aligned LoadTableResult (named LoadTableResponse here for backward compat). * Returned by GET /tables/{t}, POST /tables, and POST /tables/{t} (commit). */ interface LoadTableResponse { metadata: TableMetadata; 'metadata-location'?: string; config?: Record; 'storage-credentials'?: StorageCredential[]; } type LoadTableResult = LoadTableResponse; interface CommitTableResponse { 'metadata-location': string; metadata: TableMetadata; } /** * Catalog configuration as returned by GET /v1/config?warehouse=... * * Servers can use `overrides.prefix` to direct subsequent requests to a * server-specific path prefix (e.g., the warehouse identifier), which is * the recommended pattern over hard-coded `catalogName` configuration. */ interface CatalogConfig { defaults: Record; overrides: Record; endpoints?: string[]; 'idempotency-key-lifetime'?: string; } interface ListNamespacesOptions { parent?: NamespaceIdentifier; pageToken?: string; pageSize?: number; } interface ListTablesOptions { pageToken?: string; pageSize?: number; } interface ListNamespacesResult { namespaces: NamespaceIdentifier[]; nextPageToken?: string; } interface ListTablesResult { identifiers: TableIdentifier[]; nextPageToken?: string; } interface LoadTableOptions { /** ETag value from a previous response; server returns 304 (and we return null) if unchanged. */ ifNoneMatch?: string; /** * Which snapshots the server should include in the returned metadata. * - `'all'`: return every snapshot currently valid for the table * - `'refs'`: only snapshots referenced by branches or tags * Default if omitted is `'all'` per spec. */ snapshots?: 'all' | 'refs'; } interface LoadTableResultWithEtag extends LoadTableResponse { etag: string | null; } /** * Gets the current (active) schema from table metadata. * * @param metadata - Table metadata containing schemas array and current-schema-id * @returns The current table schema, or undefined if not found */ declare function getCurrentSchema(metadata: TableMetadata): TableSchema | undefined; /** * Access delegation mechanisms supported by the Iceberg REST Catalog. * * - `vended-credentials`: Server provides temporary credentials for data access * - `remote-signing`: Server signs requests on behalf of the client */ type AccessDelegation = 'vended-credentials' | 'remote-signing'; /** * Configuration options for the Iceberg REST Catalog client. */ interface IcebergRestCatalogOptions { /** Base URL of the Iceberg REST Catalog API */ baseUrl: string; /** * Warehouse identifier. The client passes this to `GET /v1/config?warehouse=…` * on first use; the server-returned `overrides.prefix` is then used for all * subsequent requests. This is the spec-recommended way to address a warehouse * (e.g., a Cloudflare R2 bucket) and replaces the older `catalogName` flow. */ warehouse?: string; /** * Alias for {@link warehouse} kept for backward compatibility. If both are * set, `warehouse` wins. */ catalogName?: string; /** Authentication configuration */ auth?: AuthConfig; /** Custom fetch implementation (defaults to globalThis.fetch) */ fetch?: typeof fetch; /** * Access delegation mechanisms to request from the server. * When specified, the X-Iceberg-Access-Delegation header will be sent * with supported operations (createTable, loadTable). * * @example ['vended-credentials'] * @example ['vended-credentials', 'remote-signing'] */ accessDelegation?: AccessDelegation[]; } /** * Client for interacting with an Apache Iceberg REST Catalog. * * This class provides methods for managing namespaces and tables in an Iceberg catalog. * It handles authentication, request formatting, and error handling automatically. * * @example * ```typescript * const catalog = new IcebergRestCatalog({ * baseUrl: 'https://my-catalog.example.com', * warehouse: 'my-warehouse', * auth: { type: 'bearer', token: process.env.ICEBERG_TOKEN } * }); * * // First call lazily fetches /v1/config?warehouse=my-warehouse * await catalog.createNamespace({ namespace: ['analytics'] }); * ``` */ declare class IcebergRestCatalog { private readonly client; private readonly namespaceOps; private readonly tableOps; private readonly accessDelegation?; private readonly warehouse?; private prefixPromise?; private cachedConfigPromise?; /** * Creates a new Iceberg REST Catalog client. * * @param options - Configuration options for the catalog client */ constructor(options: IcebergRestCatalogOptions); /** * Fetch and cache the server's catalog configuration. Subsequent calls return * the same object. Calling this is optional — operations will trigger it * lazily on first use. * * Caches the in-flight promise (not just the resolved value) so concurrent * first-callers don't all fire their own `/v1/config` request. */ loadConfig(): Promise; private resolvePrefix; private computePrefix; /** * Lists all namespaces in the catalog. * * @returns Paginated namespace list with optional `nextPageToken` * * @example * ```typescript * const { namespaces } = await catalog.listNamespaces(); * * // List children under a parent * const { namespaces: children } = await catalog.listNamespaces({ * parent: { namespace: ['analytics'] }, * }); * * // Paginate * const page1 = await catalog.listNamespaces({ pageSize: 100 }); * const page2 = await catalog.listNamespaces({ pageSize: 100, pageToken: page1.nextPageToken }); * ``` */ listNamespaces(options?: ListNamespacesOptions): Promise; /** * Creates a new namespace in the catalog. */ createNamespace(id: NamespaceIdentifier, metadata?: NamespaceMetadata): Promise; /** * Drops a namespace from the catalog. * * The namespace must be empty (contain no tables) before it can be dropped. */ dropNamespace(id: NamespaceIdentifier): Promise; /** * Loads metadata for a namespace. */ loadNamespaceMetadata(id: NamespaceIdentifier): Promise; /** * Set or remove properties on a namespace. */ updateNamespaceProperties(id: NamespaceIdentifier, request: UpdateNamespacePropertiesRequest): Promise; /** * Lists tables in a namespace. * * @returns Paginated table list with optional `nextPageToken` */ listTables(namespace: NamespaceIdentifier, options?: ListTablesOptions): Promise; /** * Creates a new table in the catalog. */ createTable(namespace: NamespaceIdentifier, request: CreateTableRequest): Promise; /** * Spec-aligned `LoadTableResult` wrapper for create. Returns the full server * response (metadata, metadata-location, server `config`, `storage-credentials`) * plus the captured ETag. Use this when `accessDelegation` is set so the * server-vended credentials are reachable. */ createTableResult(namespace: NamespaceIdentifier, request: CreateTableRequest): Promise; /** * Commit updates to a table using the spec-aligned `{ requirements, updates }` shape. * * @example * ```typescript * await catalog.updateTable( * { namespace: ['analytics'], name: 'events' }, * { * requirements: [], * updates: [{ action: 'set-properties', updates: { 'read.split.target-size': '134217728' } }], * }, * ); * ``` */ updateTable(id: TableIdentifier, request: UpdateTableRequest): Promise; /** Spec-aligned alias for {@link updateTable}. */ commitTable(id: TableIdentifier, request: CommitTableRequest): Promise; /** * Drops a table from the catalog. */ dropTable(id: TableIdentifier, options?: DropTableRequest): Promise; /** * Loads metadata for a table. * * Pass `ifNoneMatch` (a previous ETag) to perform a conditional GET. If the * server returns 304 Not Modified, the method returns `null`. */ loadTable(id: TableIdentifier): Promise; loadTable(id: TableIdentifier, options: LoadTableOptions): Promise; /** * Spec-aligned `LoadTableResult` wrapper, including server `config`, * `storage-credentials`, and the response `ETag`. Returns `null` on 304. */ loadTableResult(id: TableIdentifier, options?: LoadTableOptions): Promise; /** * Checks if a namespace exists in the catalog. */ namespaceExists(id: NamespaceIdentifier): Promise; /** * Checks if a table exists in the catalog. */ tableExists(id: TableIdentifier): Promise; /** * Creates a namespace if it does not exist. */ createNamespaceIfNotExists(id: NamespaceIdentifier, metadata?: NamespaceMetadata): Promise; /** * Creates a table if it does not exist. */ createTableIfNotExists(namespace: NamespaceIdentifier, request: CreateTableRequest): Promise; /** * Register an existing metadata file as a table in the given namespace. */ registerTable(namespace: NamespaceIdentifier, request: RegisterTableRequest): Promise; /** * Spec-aligned `LoadTableResult` wrapper for register. */ registerTableResult(namespace: NamespaceIdentifier, request: RegisterTableRequest): Promise; /** * Rename a table. Servers may or may not support cross-namespace renames. */ renameTable(request: RenameTableRequest): Promise; } interface IcebergErrorResponse { error: { message: string; type: string; code: number; stack?: string[]; }; } declare class IcebergError extends Error { readonly status: number; readonly icebergType?: string; readonly icebergCode?: number; readonly details?: unknown; readonly isCommitStateUnknown: boolean; constructor(message: string, opts: { status: number; icebergType?: string; icebergCode?: number; details?: unknown; }); /** * Returns true if the error is a 404 Not Found error. */ isNotFound(): boolean; /** * Returns true if the error is a 409 Conflict error. */ isConflict(): boolean; /** * Returns true if the error is a 419 Authentication Timeout error. */ isAuthenticationTimeout(): boolean; } /** * Generate an RFC 9562 UUIDv7 string. * * The Iceberg REST spec defines `Idempotency-Key` as a UUID format, * with the example payloads showing UUIDv7 (timestamp-prefixed). UUIDv7 * is preferred because keys are roughly time-orderable, which makes * server-side dedup windows simpler to reason about. * * Layout (RFC 9562 §5.7): * 48-bit unix-ms timestamp | 4-bit version (0111) | 12-bit rand_a * 2-bit variant (10) | 62-bit rand_b */ declare function generateIdempotencyKey(): string; /** * Git tag of `apache/iceberg` that this client is aligned to. The * spec-conformance test suite fetches and validates against the OpenAPI YAML * from this exact ref, so types, request bodies, and response handling here * match the spec at this version. * * @example 'apache-iceberg-1.10.0' */ declare const ICEBERG_REST_SPEC_TAG: string; /** * Direct link to the OpenAPI YAML this client tracks. */ declare const ICEBERG_REST_SPEC_URL: string; export { type AccessDelegation, type AddEncryptionKeyUpdate, type AddPartitionSpecUpdate, type AddSchemaUpdate, type AddSnapshotUpdate, type AddSortOrderUpdate, type AssertCreate, type AssertCurrentSchemaId, type AssertDefaultSortOrderId, type AssertDefaultSpecId, type AssertLastAssignedFieldId, type AssertLastAssignedPartitionId, type AssertRefSnapshotId, type AssertTableUUID, type AssignUUIDUpdate, type AuthConfig, type BlobMetadata, type CatalogConfig, type CommitTableRequest, type CommitTableResponse, type CreateNamespaceRequest, type CreateNamespaceResponse, type CreateTableRequest, type DropTableRequest, type EncryptedKey, type GetNamespaceResponse, ICEBERG_REST_SPEC_TAG, ICEBERG_REST_SPEC_URL, IcebergError, type IcebergErrorResponse, IcebergRestCatalog, type IcebergRestCatalogOptions, type IcebergType, type ListNamespacesOptions, type ListNamespacesResponse, type ListNamespacesResult, type ListTablesOptions, type ListTablesResponse, type ListTablesResult, type ListType, type LoadTableOptions, type LoadTableResponse, type LoadTableResult, type LoadTableResultWithEtag, type MapType, type NamespaceIdentifier, type NamespaceMetadata, type PartitionField, type PartitionSpec, type PartitionStatisticsFile, type PrimitiveType, type PrimitiveTypeValue, type RegisterTableRequest, type RemoveEncryptionKeyUpdate, type RemovePartitionSpecsUpdate, type RemovePartitionStatisticsUpdate, type RemovePropertiesUpdate, type RemoveSchemasUpdate, type RemoveSnapshotRefUpdate, type RemoveSnapshotsUpdate, type RemoveStatisticsUpdate, type RenameTableRequest, type SetCurrentSchemaUpdate, type SetDefaultSortOrderUpdate, type SetDefaultSpecUpdate, type SetLocationUpdate, type SetPartitionStatisticsUpdate, type SetPropertiesUpdate, type SetSnapshotRefUpdate, type SetStatisticsUpdate, type Snapshot, type SnapshotReference, type SortField, type SortOrder, type StatisticsFile, type StorageCredential, type StructField, type StructType, type TableField, type TableIdentifier, type TableMetadata, type TableRequirement, type TableSchema, type TableUpdate, type UpdateNamespacePropertiesRequest, type UpdateNamespacePropertiesResponse, type UpdateTableRequest, type UpgradeFormatVersionUpdate, generateIdempotencyKey, getCurrentSchema, isDecimalType, isFixedType, parseDecimalType, parseFixedType, typesEqual };