npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

iceberg-js

v0.8.1

Published

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

Readme

iceberg-js

CI npm version pkg.pr.new

A small, framework-agnostic JavaScript/TypeScript client for the Apache Iceberg REST Catalog.

Features

  • 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)

Documentation

📚 Full API documentation: supabase.github.io/iceberg-js

Installation

npm install iceberg-js

Quick Start

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',
    },
  }
)

API Reference

Constructor

new IcebergRestCatalog(options)

Creates a new catalog client instance.

Options:

  • baseUrl (string, required): Base URL of the REST catalog
  • auth (AuthConfig, optional): Authentication configuration
  • catalogName (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/namespaces
  • fetch (typeof fetch, optional): Custom fetch implementation
  • accessDelegation (AccessDelegation[], optional): Access delegation mechanisms to request from the server

Authentication types:

// 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:

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 data
  • remote-signing: Server signs data access requests on behalf of the client

Namespace Operations

listNamespaces(parent?: NamespaceIdentifier): Promise<NamespaceIdentifier[]>

List all namespaces, optionally under a parent namespace.

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<void>

Create a new namespace with optional properties.

await catalog.createNamespace({ namespace: ['analytics'] }, { properties: { owner: 'data-team' } })

dropNamespace(id: NamespaceIdentifier): Promise<void>

Drop a namespace. The namespace must be empty.

await catalog.dropNamespace({ namespace: ['analytics'] })

loadNamespaceMetadata(id: NamespaceIdentifier): Promise<NamespaceMetadata>

Load namespace metadata and properties.

const metadata = await catalog.loadNamespaceMetadata({ namespace: ['analytics'] })
// { properties: { owner: 'data-team', ... } }

Table Operations

listTables(namespace: NamespaceIdentifier): Promise<TableIdentifier[]>

List all tables in a namespace.

const tables = await catalog.listTables({ namespace: ['analytics'] })
// [{ namespace: ['analytics'], name: 'events' }]

createTable(namespace: NamespaceIdentifier, request: CreateTableRequest): Promise<TableMetadata>

Create a new table.

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<TableMetadata>

Load table metadata.

const metadata = await catalog.loadTable({
  namespace: ['analytics'],
  name: 'events',
})

updateTable(id: TableIdentifier, request: UpdateTableRequest): Promise<TableMetadata>

Update table metadata (schema, partition spec, or properties).

const updated = await catalog.updateTable(
  { namespace: ['analytics'], name: 'events' },
  {
    properties: { 'read.split.target-size': '134217728' },
  }
)

dropTable(id: TableIdentifier): Promise<void>

Drop a table from the catalog.

await catalog.dropTable({ namespace: ['analytics'], name: 'events' })

Error Handling

All API errors throw an IcebergError with details from the server:

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'
  }
}

TypeScript Types

The library exports all relevant types:

import type {
  NamespaceIdentifier,
  TableIdentifier,
  TableSchema,
  TableField,
  IcebergType,
  PartitionSpec,
  SortOrder,
  CreateTableRequest,
  TableMetadata,
  AuthConfig,
  AccessDelegation,
} from 'iceberg-js'

Supported Iceberg Types

The following Iceberg primitive types are supported:

  • boolean, int, long, float, double
  • string, uuid, binary
  • date, time, timestamp, timestamptz
  • decimal(precision, scale), fixed(length)

Compatibility

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 | | Node.js CommonJS | Default | const { ... } = require('iceberg-js') | ✅ Fully supported | | TypeScript ESM | module: "ESNext" | import { ... } from 'iceberg-js' | ✅ Full type support | | TypeScript CommonJS | module: "CommonJS" | import { ... } from 'iceberg-js' | ✅ Full type support | | Bundlers | Any | Webpack, Vite, esbuild, Rollup, etc. | ✅ Auto-detected | | Browsers | ESM | <script type="module"> | ✅ Modern browsers | | Deno | ESM | import from npm: | ✅ With npm specifier |

Package exports:

  • ESM: dist/index.mjs with dist/index.d.ts
  • CommonJS: dist/index.cjs with dist/index.d.cts
  • Proper exports field for Node.js 12+ module resolution

All scenarios are tested in CI on Node.js 20 and 22.

Browser Usage

The library works in modern browsers that support native fetch:

import { IcebergRestCatalog } from 'iceberg-js'

const catalog = new IcebergRestCatalog({
  baseUrl: 'https://public-catalog.example.com/iceberg/v1',
  auth: { type: 'none' },
})

const namespaces = await catalog.listNamespaces()

Node.js Usage

Node.js 20+ includes native fetch support. For older versions, provide a custom fetch implementation:

import { IcebergRestCatalog } from 'iceberg-js'
import fetch from 'node-fetch'

const catalog = new IcebergRestCatalog({
  baseUrl: 'https://catalog.example.com/iceberg/v1',
  auth: { type: 'bearer', token: 'token' },
  fetch: fetch as any,
})

Limitations (v0.1.0)

This is a catalog client only. The following are not supported:

  • Reading table data (scanning Parquet files)
  • Writing data to tables
  • Advanced table operations (commits, snapshots, time travel)
  • Views support
  • Multi-table transactions

Development

# Install dependencies
pnpm install

# Build the library
pnpm run build

# Run unit tests
pnpm test

# Run integration tests (requires Docker)
pnpm test:integration

# Run integration tests with cleanup (for CI)
pnpm test:integration:ci

# Run compatibility tests (all module systems)
pnpm test:compatibility

# Format code
pnpm run format

# Lint and test
pnpm run check

Testing with Docker

Integration tests run against a local Iceberg REST Catalog in Docker. See TESTING-DOCKER.md for details.

# Start Docker services and run integration tests
pnpm test:integration

# Or manually
docker compose up -d
npx tsx test/integration/test-local-catalog.ts
docker compose down -v

Compatibility Testing

The test:compatibility script verifies the package works correctly in all JavaScript/TypeScript environments:

  • Pure JavaScript ESM - Projects with "type": "module"
  • Pure JavaScript CommonJS - Traditional Node.js projects
  • TypeScript ESM - TypeScript with module: "ESNext"
  • TypeScript CommonJS - TypeScript with module: "CommonJS"

These tests ensure proper module resolution, type definitions, and runtime behavior across all supported environments. See test/compatibility/README.md for more details.

License

MIT

Releases

This project uses release-please for automated releases. Here's how it works:

  1. Commit with conventional commits: Use Conventional Commits format for your commits:

    • feat: for new features (minor version bump)
    • fix: for bug fixes (patch version bump)
    • feat!: or BREAKING CHANGE: for breaking changes (major version bump)
    • chore:, docs:, test:, etc. for non-release commits
  2. Release PR is created automatically: When you push to main, release-please creates/updates a release PR with:

    • Version bump in package.json
    • Updated CHANGELOG.md
    • Release notes
  3. Merge the release PR: When you're ready to release, merge the PR. This will:

    • Create a GitHub release and git tag
    • Automatically publish to npm with provenance (using trusted publishing, no secrets needed)

Example commits:

git commit -m "feat: add support for view operations"
git commit -m "fix: handle empty namespace list correctly"
git commit -m "feat!: change auth config structure"

Contributing

Contributions are welcome! This library aims to be a minimal, generic client for the Iceberg REST Catalog API.