A small, framework-agnostic JavaScript/TypeScript client for the Apache Iceberg REST Catalog
npm install iceberg-js


A small, framework-agnostic JavaScript/TypeScript client for the Apache Iceberg REST Catalog.
- Generic: Works with any Iceberg REST Catalog implementation, not tied to any specific vendor
- Minimal: Thin HTTP wrapper over the official REST API, no engine-specific logic
- Type-safe: First-class TypeScript support with strongly-typed request/response models
- Fetch-based: Uses native fetch API with support for custom implementations
- Universal: Targets Node 20+ and modern browsers (ES2020)
- Catalog-only: Focused on catalog operations (no data reading/Parquet support in v0.1.0)
š Full API documentation: supabase.github.io/iceberg-js
``bash`
npm install iceberg-js
`typescript
import { IcebergRestCatalog } from 'iceberg-js'
const catalog = new IcebergRestCatalog({
baseUrl: 'https://my-catalog.example.com/iceberg/v1',
auth: {
type: 'bearer',
token: process.env.ICEBERG_TOKEN,
},
})
// Create a namespace
await catalog.createNamespace({ namespace: ['analytics'] })
// Create a table
await catalog.createTable(
{ namespace: ['analytics'] },
{
name: 'events',
schema: {
type: 'struct',
fields: [
{ id: 1, name: 'id', type: 'long', required: true },
{ id: 2, name: 'timestamp', type: 'timestamp', required: true },
{ id: 3, name: 'user_id', type: 'string', required: false },
],
'schema-id': 0,
'identifier-field-ids': [1],
},
'partition-spec': {
'spec-id': 0,
fields: [],
},
'write-order': {
'order-id': 0,
fields: [],
},
properties: {
'write.format.default': 'parquet',
},
}
)
`
#### new IcebergRestCatalog(options)
Creates a new catalog client instance.
Options:
- baseUrl (string, required): Base URL of the REST catalogauth
- (AuthConfig, optional): Authentication configurationcatalogName
- (string, optional): Catalog name for multi-catalog servers. When specified, requests are sent to {baseUrl}/v1/{catalogName}/.... For example, with baseUrl: 'https://host.com' and catalogName: 'prod', requests go to https://host.com/v1/prod/namespacesfetch
- (typeof fetch, optional): Custom fetch implementationaccessDelegation
- (AccessDelegation[], optional): Access delegation mechanisms to request from the server
Authentication types:
`typescript
// No authentication
{ type: 'none' }
// Bearer token
{ type: 'bearer', token: 'your-token' }
// Custom header
{ type: 'header', name: 'X-Custom-Auth', value: 'secret' }
// Custom function
{ type: 'custom', getHeaders: async () => ({ 'Authorization': 'Bearer ...' }) }
`
Access Delegation:
Access delegation allows the catalog server to provide temporary credentials or sign requests on your behalf:
`typescript
import { IcebergRestCatalog } from 'iceberg-js'
const catalog = new IcebergRestCatalog({
baseUrl: 'https://catalog.example.com/iceberg/v1',
auth: { type: 'bearer', token: 'your-token' },
// Request vended credentials for data access
accessDelegation: ['vended-credentials'],
})
// The server may return temporary credentials in the table metadata
const metadata = await catalog.loadTable({ namespace: ['analytics'], name: 'events' })
// Use credentials from metadata.config to access table data files
`
Supported delegation mechanisms:
- vended-credentials: Server provides temporary credentials (e.g., AWS STS tokens) for accessing table dataremote-signing
- : Server signs data access requests on behalf of the client
#### listNamespaces(parent?: NamespaceIdentifier): Promise
List all namespaces, optionally under a parent namespace.
`typescript
const namespaces = await catalog.listNamespaces()
// [{ namespace: ['default'] }, { namespace: ['analytics'] }]
const children = await catalog.listNamespaces({ namespace: ['analytics'] })
// [{ namespace: ['analytics', 'prod'] }]
`
#### createNamespace(id: NamespaceIdentifier, metadata?: NamespaceMetadata): Promise
Create a new namespace with optional properties.
`typescript`
await catalog.createNamespace({ namespace: ['analytics'] }, { properties: { owner: 'data-team' } })
#### dropNamespace(id: NamespaceIdentifier): Promise
Drop a namespace. The namespace must be empty.
`typescript`
await catalog.dropNamespace({ namespace: ['analytics'] })
#### loadNamespaceMetadata(id: NamespaceIdentifier): Promise
Load namespace metadata and properties.
`typescript`
const metadata = await catalog.loadNamespaceMetadata({ namespace: ['analytics'] })
// { properties: { owner: 'data-team', ... } }
#### listTables(namespace: NamespaceIdentifier): Promise
List all tables in a namespace.
`typescript`
const tables = await catalog.listTables({ namespace: ['analytics'] })
// [{ namespace: ['analytics'], name: 'events' }]
#### createTable(namespace: NamespaceIdentifier, request: CreateTableRequest): Promise
Create a new table.
`typescript`
const metadata = await catalog.createTable(
{ namespace: ['analytics'] },
{
name: 'events',
schema: {
type: 'struct',
fields: [
{ id: 1, name: 'id', type: 'long', required: true },
{ id: 2, name: 'timestamp', type: 'timestamp', required: true },
],
'schema-id': 0,
},
'partition-spec': {
'spec-id': 0,
fields: [
{
source_id: 2,
field_id: 1000,
name: 'ts_day',
transform: 'day',
},
],
},
}
)
#### loadTable(id: TableIdentifier): Promise
Load table metadata.
`typescript`
const metadata = await catalog.loadTable({
namespace: ['analytics'],
name: 'events',
})
#### updateTable(id: TableIdentifier, request: UpdateTableRequest): Promise
Update table metadata (schema, partition spec, or properties).
`typescript`
const updated = await catalog.updateTable(
{ namespace: ['analytics'], name: 'events' },
{
properties: { 'read.split.target-size': '134217728' },
}
)
#### dropTable(id: TableIdentifier): Promise
Drop a table from the catalog.
`typescript`
await catalog.dropTable({ namespace: ['analytics'], name: 'events' })
All API errors throw an IcebergError with details from the server:
`typescript
import { IcebergError } from 'iceberg-js'
try {
await catalog.loadTable({ namespace: ['test'], name: 'missing' })
} catch (error) {
if (error instanceof IcebergError) {
console.log(error.status) // 404
console.log(error.icebergType) // 'NoSuchTableException'
console.log(error.message) // 'Table does not exist'
}
}
`
The library exports all relevant types:
`typescript`
import type {
NamespaceIdentifier,
TableIdentifier,
TableSchema,
TableField,
IcebergType,
PartitionSpec,
SortOrder,
CreateTableRequest,
TableMetadata,
AuthConfig,
AccessDelegation,
} from 'iceberg-js'
The following Iceberg primitive types are supported:
- boolean, int, long, float, doublestring
- , uuid, binarydate
- , time, timestamp, timestamptzdecimal(precision, scale)
- , fixed(length)
This package is built to work in all Node.js and JavaScript environments:
| Environment | Module System | Import Method | Status |
| ------------------- | -------------------- | --------------------------------------- | --------------------- |
| Node.js ESM | "type": "module" | import { ... } from 'iceberg-js' | ā
Fully supported |const { ... } = require('iceberg-js')
| Node.js CommonJS | Default | | ā
Fully supported |module: "ESNext"
| TypeScript ESM | | import { ... } from 'iceberg-js' | ā
Full type support |module: "CommonJS"
| TypeScript CommonJS | | import { ... } from 'iceberg-js' | ā
Full type support |
| Bundlers | Any | Webpack, Vite, esbuild, Rollup, etc. | ā
Auto-detected |
| Browsers | ESM |