Claude Cursor Skill

supabase-js

This skill should be used when user asks to "use supabase-js", "query Supabase database", "supabase auth", "supabase storage", "supabase realtime", "supabase edge functions", or works with the @supabase/supabase-js JavaScript/TypeScript SDK.

LLM Mart · 0 points · 8 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download fcakyon-claude-codex-settings-plugins_supabase-skills_skills_supabase-js-4632eb3.zip · 32 KB
Part of fcakyon/claude-codex-settings — 83 skills

Install

skills CLI npx skills add https://github.com/fcakyon/claude-codex-settings/tree/main/plugins/supabase-skills/skills/supabase-js
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install fcakyon-claude-codex-settings@llmmart
Git git clone https://github.com/fcakyon/claude-codex-settings.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole fcakyon/claude-codex-settings collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Supabase JavaScript SDK Skill

Skill for building applications with the @supabase/supabase-js SDK. Covers Auth, Database (PostgREST), Storage, Realtime, and Edge Functions.

The SDK docs at https://supabase.com/docs/reference/javascript are the source of truth. The reference files alongside this skill contain source code and READMEs extracted from the monorepo for quick lookup.

Setup

npm install @supabase/supabase-js
import { createClient } from '@supabase/supabase-js'

const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key')

For type-safe queries, generate types from your database schema:

supabase gen types typescript --project-id your-project-id > database.types.ts
import { createClient } from '@supabase/supabase-js'
import type { Database } from './database.types'

const supabase = createClient<Database>(SUPABASE_URL, SUPABASE_ANON_KEY)

Quick Decision Trees

"I need to query data"

Database query?
├─ Select rows → supabase.from('table').select('*')
├─ Filter rows → .select().eq('col', val) / .gt() / .lt() / .in() / .like()
├─ Join tables → .select('*, other_table(*)') or .select('*, other_table!fk(*)')
├─ Insert → supabase.from('table').insert({ col: val })
├─ Upsert → supabase.from('table').upsert({ id: 1, col: val })
├─ Update → supabase.from('table').update({ col: val }).eq('id', 1)
├─ Delete → supabase.from('table').delete().eq('id', 1)
├─ Call RPC function → supabase.rpc('function_name', { arg: val })
├─ Count rows → .select('*', { count: 'exact', head: true })
├─ Pagination → .range(0, 9) or .limit(10).offset(20)
└─ Order → .order('created_at', { ascending: false })

"I need authentication"

Auth?
├─ Email/password sign up → supabase.auth.signUp({ email, password })
├─ Email/password sign in → supabase.auth.signInWithPassword({ email, password })
├─ OAuth (Google, GitHub, etc.) → supabase.auth.signInWithOAuth({ provider: 'google' })
├─ Magic link → supabase.auth.signInWithOtp({ email })
├─ Phone OTP → supabase.auth.signInWithOtp({ phone })
├─ Sign out → supabase.auth.signOut()
├─ Get current user → supabase.auth.getUser()
├─ Get session → supabase.auth.getSession()
├─ Listen to auth changes → supabase.auth.onAuthStateChange((event, session) => {})
├─ Reset password → supabase.auth.resetPasswordForEmail(email)
├─ Update user → supabase.auth.updateUser({ data: { name: 'New' } })
└─ Admin operations → supabase.auth.admin.listUsers() / .deleteUser(id)

"I need file storage"

Storage?
├─ Upload file → supabase.storage.from('bucket').upload('path/file.png', file)
├─ Download file → supabase.storage.from('bucket').download('path/file.png')
├─ Get public URL → supabase.storage.from('bucket').getPublicUrl('path/file.png')
├─ Create signed URL → supabase.storage.from('bucket').createSignedUrl('path', 3600)
├─ List files → supabase.storage.from('bucket').list('folder')
├─ Move file → supabase.storage.from('bucket').move('old/path', 'new/path')
├─ Remove file → supabase.storage.from('bucket').remove(['path/file.png'])
├─ Create bucket → supabase.storage.createBucket('name', { public: false })
└─ List buckets → supabase.storage.listBuckets()

"I need realtime"

Realtime?
├─ Listen to DB changes → supabase.channel('name')
│    .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'messages' }, handler)
│    .subscribe()
├─ Broadcast messages → channel.send({ type: 'broadcast', event: 'cursor', payload: { x, y } })
├─ Listen to broadcasts → .on('broadcast', { event: 'cursor' }, handler)
├─ Presence (who's online) → channel.track({ user_id, online_at })
│    .on('presence', { event: 'sync' }, () => channel.presenceState())
├─ Unsubscribe → supabase.removeChannel(channel)
└─ Unsubscribe all → supabase.removeAllChannels()

"I need edge functions"

Edge Functions?
├─ Invoke function → supabase.functions.invoke('function-name', { body: { key: 'val' } })
├─ With custom headers → .invoke('fn', { headers: { 'x-custom': 'val' }, body })
└─ Set region → .invoke('fn', { body, region: 'us-east-1' })

Common Patterns

Server-side with service role key

// Server-side only - bypasses RLS
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, {
  auth: { persistSession: false }
})

React/Next.js auth

import { createClient } from '@supabase/supabase-js'
import { useEffect, useState } from 'react'

const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)

function useUser() {
  const [user, setUser] = useState(null)
  useEffect(() => {
    supabase.auth.getUser().then(({ data }) => setUser(data.user))
    const { data: { subscription } } = supabase.auth.onAuthStateChange(
      (_, session) => setUser(session?.user ?? null)
    )
    return () => subscription.unsubscribe()
  }, [])
  return user
}

Typed database queries

// Generated types give autocomplete for table names, column names, and return types
const { data, error } = await supabase
  .from('profiles')        // autocompleted table name
  .select('id, username')  // autocompleted columns
  .eq('id', userId)        // type-safe filter
  .single()                // returns single row or error
// data is typed as { id: string; username: string } | null

Package Index

Package Sub-client Reference
@supabase/supabase-js createClient() references/supabase-js/
@supabase/auth-js .auth references/auth-js/
@supabase/postgrest-js .from(), .rpc() references/postgrest-js/
@supabase/realtime-js .channel(), .realtime references/realtime-js/
@supabase/storage-js .storage references/storage-js/
@supabase/functions-js .functions references/functions-js/
Files (claude-codex-settings)
  • references
    • auth-js
      • README.md 6.5 KB
        <br />
        <p align="center">
          <a href="https://supabase.io">
                <picture>
              <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg">
              <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg">
              <img alt="Supabase Logo" width="300" src="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg">
            </picture>
          </a>
        
          <h1 align="center">Supabase Auth JS SDK</h1>
        
          <h3 align="center">An isomorphic JavaScript SDK for the <a href="https://github.com/supabase/auth">Supabase Auth</a> API.</h3>
        
          <p align="center">
            <a href="https://supabase.com/docs/guides/auth">Guides</a>
            ·
            <a href="https://supabase.com/docs/reference/javascript/auth-signup">Reference Docs</a>
            ·
            <a href="https://supabase.github.io/supabase-js/auth-js/v2/spec.json">TypeDoc</a>
          </p>
        </p>
        
        <div align="center">
        
        [![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)
        [![Package](https://img.shields.io/npm/v/@supabase/auth-js)](https://www.npmjs.com/package/@supabase/auth-js)
        [![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)
        [![pkg.pr.new](https://pkg.pr.new/badge/supabase/auth-js)](https://pkg.pr.new/~/supabase/auth-js)
        
        </div>
        
        ## Requirements
        
        - **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)
        - For browser support, all modern browsers are supported
        
        > ⚠️ **Node.js 18 Deprecation Notice**
        >
        > Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.
        
        > ⚠️ **Node.js 20 Deprecation Notice**
        >
        > Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.
        
        ## Quick start
        
        Install
        
        ```bash
        npm install --save @supabase/auth-js
        ```
        
        Usage
        
        ```js
        import { AuthClient } from '@supabase/auth-js'
        
        const GOTRUE_URL = 'http://localhost:9999'
        
        const auth = new AuthClient({ url: GOTRUE_URL })
        ```
        
        - `signUp()`: https://supabase.com/docs/reference/javascript/auth-signup
        - `signIn()`: https://supabase.com/docs/reference/javascript/auth-signin
        - `signOut()`: https://supabase.com/docs/reference/javascript/auth-signout
        
        ### Custom `fetch` implementation
        
        `auth-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:
        
        ```js
        import { AuthClient } from '@supabase/auth-js'
        
        const AUTH_URL = 'http://localhost:9999'
        
        const auth = new AuthClient({ url: AUTH_URL, fetch: fetch })
        ```
        
        ## Development
        
        This package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:
        
        ### Building
        
        ```bash
        # Complete build (from monorepo root)
        pnpm nx build auth-js
        
        # Build with watch mode for development
        pnpm nx build auth-js --watch
        
        # Individual build targets
        pnpm nx build:main auth-js    # CommonJS build (dist/main/)
        pnpm nx build:module auth-js  # ES Modules build (dist/module/)
        
        # Other useful commands
        pnpm nx lint auth-js          # Run ESLint
        pnpm nx typecheck auth-js     # TypeScript type checking
        pnpm nx docs auth-js          # Generate documentation
        ```
        
        #### Build Outputs
        
        - **CommonJS (`dist/main/`)** - For Node.js environments
        - **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)
        - **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects
        
        ### Testing
        
        The auth-js package has two test suites:
        
        1. **CLI Tests** - Main test suite using Supabase CLI (331 tests)
        2. **Docker Tests** - Edge case tests requiring specific GoTrue configurations (11 tests)
        
        #### Prerequisites
        
        - **Supabase CLI** - Required for main test suite ([installation guide](https://supabase.com/docs/guides/cli))
        - **Docker** - Required for edge case tests
        
        #### Running Tests
        
        ```bash
        # Run main test suite with Supabase CLI (recommended)
        pnpm nx test:auth auth-js
        
        # Run Docker-only edge case tests
        pnpm nx test:docker auth-js
        
        # Run both test suites
        pnpm nx test:auth auth-js && pnpm nx test:docker auth-js
        ```
        
        #### Main Test Suite (Supabase CLI)
        
        The `test:auth` command automatically:
        
        1. Stops any existing Supabase instance
        2. Starts a local Supabase instance via CLI
        3. Runs the test suite (excludes `docker-tests/` folder)
        4. Cleans up after tests complete
        
        ```bash
        # Individual commands for manual control
        pnpm nx test:infra auth-js    # Start Supabase CLI
        pnpm nx test:suite auth-js    # Run tests only
        pnpm nx test:clean-post auth-js  # Stop Supabase CLI
        ```
        
        #### Docker Tests (Edge Cases)
        
        The `test:docker` target runs tests that require specific GoTrue configurations not possible with a single Supabase CLI instance:
        
        - **Signup disabled** - Tests for disabled signup functionality
        - **Asymmetric JWT (RS256)** - Tests for RS256 JWT verification
        - **Phone OTP / SMS** - Tests requiring Twilio SMS provider
        - **Anonymous sign-in disabled** - Tests for disabled anonymous auth
        
        These tests are located in `test/docker-tests/` and use the Docker Compose setup in `infra/docker-compose.yml`.
        
        ```bash
        # Individual commands for manual control
        pnpm nx test:docker:infra auth-js    # Start Docker containers
        pnpm nx test:docker:suite auth-js    # Run Docker tests only
        pnpm nx test:docker:clean-post auth-js  # Stop Docker containers
        ```
        
        #### Development Testing
        
        For actively developing and debugging tests:
        
        ```bash
        # Start Supabase CLI once
        pnpm nx test:infra auth-js
        
        # Run tests multiple times (faster since instance stays up)
        pnpm nx test:suite auth-js
        
        # Clean up when done
        pnpm nx test:clean-post auth-js
        ```
        
        #### Test Infrastructure
        
        | Suite        | Infrastructure | Configuration               |
        | ------------ | -------------- | --------------------------- |
        | CLI Tests    | Supabase CLI   | `test/supabase/config.toml` |
        | Docker Tests | Docker Compose | `infra/docker-compose.yml`  |
        
        ### Contributing
        
        We welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.
        
        For major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.
        
    • functions-js
      • README.md 4.8 KB
        <br />
        <p align="center">
          <a href="https://supabase.io">
                <picture>
              <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg">
              <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg">
              <img alt="Supabase Logo" width="300" src="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg">
            </picture>
          </a>
        
          <h1 align="center">Supabase Functions JS SDK</h1>
        
          <h3 align="center">JavaScript SDK to interact with Supabase Edge Functions.</h3>
        
          <p align="center">
            <a href="https://supabase.com/docs/guides/functions">Guides</a>
            ·
            <a href="https://supabase.com/docs/reference/javascript/functions-invoke">Reference Docs</a>
            ·
            <a href="https://supabase.github.io/supabase-js/functions-js/v2/spec.json">TypeDoc</a>
          </p>
        </p>
        
        <div align="center">
        
        [![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)
        [![Package](https://img.shields.io/npm/v/@supabase/functions-js)](https://www.npmjs.com/package/@supabase/functions-js)
        [![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)
        [![pkg.pr.new](https://pkg.pr.new/badge/supabase/functions-js)](https://pkg.pr.new/~/supabase/functions-js)
        
        </div>
        
        ## Requirements
        
        - **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)
        - For browser support, all modern browsers are supported
        
        > ⚠️ **Node.js 18 Deprecation Notice**
        >
        > Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.
        
        > ⚠️ **Node.js 20 Deprecation Notice**
        >
        > Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.
        
        ## Quick Start
        
        ### Installation
        
        ```bash
        npm install @supabase/functions-js
        ```
        
        ### Usage
        
        ```js
        import { FunctionsClient } from '@supabase/functions-js'
        
        const functionsUrl = 'https://<project_ref>.supabase.co/functions/v1'
        const publishableKey = '<publishable_key>'
        
        const functions = new FunctionsClient(functionsUrl, {
          headers: {
            Authorization: `Bearer ${publishableKey}`,
          },
        })
        
        // Invoke a function
        const { data, error } = await functions.invoke('hello-world', {
          body: { name: 'Functions' },
        })
        ```
        
        ## Development
        
        This package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:
        
        ### Building
        
        ```bash
        # Complete build (from monorepo root)
        pnpm nx build functions-js
        
        # Build with watch mode for development
        pnpm nx build functions-js --watch
        
        # Individual build targets
        pnpm nx build:main functions-js    # CommonJS build (dist/main/)
        pnpm nx build:module functions-js  # ES Modules build (dist/module/)
        
        # Other useful commands
        pnpm nx clean functions-js         # Clean build artifacts
        pnpm nx typecheck functions-js     # TypeScript type checking
        pnpm nx docs functions-js          # Generate documentation
        ```
        
        #### Build Outputs
        
        - **CommonJS (`dist/main/`)** - For Node.js environments
        - **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)
        - **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects
        
        ### Testing
        
        **Docker Required** for relay tests. The functions-js tests use testcontainers to spin up a Deno relay server for testing Edge Function invocations.
        
        ```bash
        # Run all tests (from monorepo root)
        pnpm nx test functions-js
        
        # Run tests with coverage report
        pnpm nx test functions-js --coverage
        
        # Run tests in watch mode during development
        pnpm nx test functions-js --watch
        
        # CI test command (runs with coverage)
        pnpm nx test:ci functions-js
        ```
        
        #### Test Requirements
        
        - **Node.js 22+** - Required for testcontainers
        - **Docker** - Must be installed and running for relay tests
        - No Supabase instance needed - Tests use mocked services and testcontainers
        
        #### What Gets Tested
        
        - **Function invocation** - Testing the `invoke()` method with various options
        - **Relay functionality** - Using a containerized Deno relay to test real Edge Function scenarios
        - **Error handling** - Ensuring proper error responses and retries
        - **Request/response models** - Validating headers, body, and response formats
        
        ### Contributing
        
        We welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.
        
        For major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.
        
    • postgrest-js
      • README.md 6.9 KB
        <br />
        <p align="center">
          <a href="https://supabase.io">
                <picture>
              <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg">
              <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg">
              <img alt="Supabase Logo" width="300" src="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg">
            </picture>
          </a>
        
          <h1 align="center">Supabase PostgREST JS SDK</h1>
        
          <h3 align="center">Isomorphic JavaScript SDK for <a href="https://postgrest.org">PostgREST</a> with an ORM-like interface.</h3>
        
          <p align="center">
            <a href="https://supabase.com/docs/guides/database">Guides</a>
            ·
            <a href="https://supabase.com/docs/reference/javascript/select">Reference Docs</a>
            ·
            <a href="https://supabase.github.io/supabase-js/postgrest-js/v2/spec.json">TypeDoc</a>
          </p>
        </p>
        
        <div align="center">
        
        [![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)
        [![Package](https://img.shields.io/npm/v/@supabase/postgrest-js)](https://www.npmjs.com/package/@supabase/postgrest-js)
        [![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)
        [![pkg.pr.new](https://pkg.pr.new/badge/supabase/postgrest-js)](https://pkg.pr.new/~/supabase/postgrest-js)
        
        </div>
        
        ### Quick start
        
        Install
        
        ```bash
        npm install @supabase/postgrest-js
        ```
        
        Usage
        
        ```js
        import { PostgrestClient } from '@supabase/postgrest-js'
        
        const REST_URL = 'http://localhost:3000'
        const postgrest = new PostgrestClient(REST_URL)
        ```
        
        - [select()](https://supabase.com/docs/reference/javascript/select)
        - [insert()](https://supabase.com/docs/reference/javascript/insert)
        - [update()](https://supabase.com/docs/reference/javascript/update)
        - [delete()](https://supabase.com/docs/reference/javascript/delete)
        
        #### Custom `fetch` implementation
        
        `postgrest-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:
        
        ```js
        import { PostgrestClient } from '@supabase/postgrest-js'
        
        const REST_URL = 'http://localhost:3000'
        const postgrest = new PostgrestClient(REST_URL, {
          fetch: (...args) => fetch(...args),
        })
        ```
        
        ## Development
        
        This package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:
        
        ### Building
        
        ```bash
        # Build (from monorepo root)
        pnpm nx build postgrest-js
        
        # Build with watch mode for development
        pnpm nx build:watch postgrest-js
        
        # TypeScript type checking
        pnpm nx type-check postgrest-js
        
        # Generate documentation
        pnpm nx docs postgrest-js
        ```
        
        ### Testing
        
        **Supabase CLI Required!** The `postgrest-js` tests use the [Supabase CLI](https://supabase.com/docs/guides/local-development/cli/getting-started) to run a local PostgreSQL database and PostgREST server.
        
        #### Quick Start
        
        ```bash
        # Run all tests (from monorepo root)
        pnpm nx test:ci:postgrest postgrest-js
        ```
        
        This single command automatically:
        
        1. Stops any existing Supabase CLI containers
        2. Starts PostgreSQL database and PostgREST server via Supabase CLI
        3. Resets and seeds the database
        4. Runs all Jest unit tests with coverage
        5. Cleans up containers
        
        #### Individual Test Commands
        
        ```bash
        # Run Jest tests with coverage (requires infrastructure running)
        pnpm nx test:run postgrest-js
        
        # Run type tests with tstyche
        pnpm nx test:types postgrest-js
        
        # Run smoke tests (CommonJS and ESM imports)
        pnpm nx test:smoke postgrest-js
        
        # Format code
        pnpm nx format postgrest-js
        
        # Check formatting
        pnpm nx format:check postgrest-js
        ```
        
        #### Test Infrastructure
        
        The tests use Supabase CLI to spin up:
        
        - **PostgreSQL** - Database with test schema and seed data (port 54322)
        - **PostgREST** - REST API server that the client connects to (port 54321)
        
        ```bash
        # Manually manage test infrastructure (from monorepo root)
        pnpm nx test:infra postgrest-js      # Start containers
        pnpm nx test:clean-pre postgrest-js  # Stop and remove containers
        ```
        
        Or directly via Supabase CLI:
        
        ```bash
        cd packages/core/postgrest-js
        npx supabase --workdir ./test start        # Start all services
        npx supabase --workdir ./test db reset     # Reset and seed database
        npx supabase --workdir ./test stop         # Stop all services
        ```
        
        #### Regenerating TypeScript Types
        
        When the database schema changes, regenerate TypeScript types from the actual database:
        
        ```bash
        # From the monorepo root
        pnpm run codegen:postgrest
        ```
        
        This command automatically:
        
        1. Cleans up any existing Supabase containers
        2. Starts Supabase (PostgreSQL, PostgREST, and all services)
        3. Generates TypeScript types from the database schema
        4. Post-processes the generated types (updates JSON type definitions)
        5. Formats the generated file with Prettier
        6. Cleans up Supabase containers
        
        The generated types are written to `test/types.generated.ts`.
        
        #### Test Types Explained
        
        - **Unit Tests** - Jest tests covering all client functionality (`pnpm nx test:run postgrest-js`)
        - **Type Tests** - Validates TypeScript types using tstyche (`pnpm nx test:types postgrest-js`)
        - **Smoke Tests** - Basic import/require tests for CommonJS and ESM (`pnpm nx test:smoke postgrest-js`)
        
        #### Prerequisites
        
        - **Supabase CLI** must be installed ([instructions](https://supabase.com/docs/guides/local-development/cli/getting-started)) or can be used through `npx` (`npx supabase`)
        - **Docker** must be installed and running (Supabase CLI uses Docker under the hood)
        - **Port 54321** - PostgREST API
        - **Port 54322** - PostgreSQL database
        - **Port 54323** - Supabase Studio (used for type generation)
        
        #### PostgREST v12 Backward Compatibility Tests
        
        We maintain backward compatibility tests for PostgREST v12 (the current Supabase CLI uses v14+). These tests ensure the SDK works correctly for users still running older PostgREST versions.
        
        ```bash
        # Run v12 compatibility tests (requires Docker)
        pnpm nx test:ci:v12 postgrest-js
        ```
        
        This command:
        
        1. Starts PostgREST v12 + PostgreSQL in Docker (ports 3012/5433)
        2. Runs runtime tests that verify v12-specific behavior
        3. Cleans up containers
        
        **Type-only tests** for v12 compatibility also run as part of the regular type tests:
        
        ```bash
        pnpm nx test:types postgrest-js  # Includes v12-compat.test-d.ts
        ```
        
        **Note:** These v12 tests will be removed when v3 ships (sometime in 2026).
        
        ### Contributing
        
        We welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.
        
        For major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.
        
        ## License
        
        This repo is licensed under MIT License.
        
    • realtime-js
      • README.md 14.8 KB
        <br />
        <p align="center">
          <a href="https://supabase.io">
                <picture>
              <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg">
              <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg">
              <img alt="Supabase Logo" width="300" src="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg">
            </picture>
          </a>
        
          <h1 align="center">Supabase Realtime JS SDK</h1>
        
          <h3 align="center">Send ephemeral messages with <b>Broadcast</b>, track and synchronize state with <b>Presence</b>, and listen to database changes with <b>Postgres Change Data Capture (CDC)</b>.</h3>
        
          <p align="center">
            <a href="https://supabase.com/docs/guides/realtime">Guides</a>
            ·
            <a href="https://supabase.com/docs/reference/javascript">Reference Docs</a>
            ·
            <a href="https://multiplayer.dev">Multiplayer Demo</a>
          </p>
        </p>
        
        <div align="center">
        
        [![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)
        [![Package](https://img.shields.io/npm/v/@supabase/realtime-js)](https://www.npmjs.com/package/@supabase/realtime-js)
        [![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)
        [![pkg.pr.new](https://pkg.pr.new/badge/supabase/realtime-js)](https://pkg.pr.new/~/supabase/realtime-js)
        
        </div>
        
        # Overview
        
        This SDK enables you to use the following Supabase Realtime's features:
        
        - **Broadcast**: send ephemeral messages from client to clients with minimal latency. Use cases include sharing cursor positions between users.
        - **Presence**: track and synchronize shared state across clients with the help of CRDTs. Use cases include tracking which users are currently viewing a specific webpage.
        - **Postgres Change Data Capture (CDC)**: listen for changes in your PostgreSQL database and send them to clients.
        
        # Usage
        
        ## Installing the Package
        
        ```bash
        npm install @supabase/realtime-js
        ```
        
        ## Creating a Channel
        
        ```js
        import { RealtimeClient } from '@supabase/realtime-js'
        
        const client = new RealtimeClient(REALTIME_URL, {
          params: {
            apikey: API_KEY,
          },
        })
        
        const channel = client.channel('test-channel', {})
        
        channel.subscribe((status, err) => {
          if (status === 'SUBSCRIBED') {
            console.log('Connected!')
          }
        
          if (status === 'CHANNEL_ERROR') {
            console.log(`There was an error subscribing to channel: ${err.message}`)
          }
        
          if (status === 'TIMED_OUT') {
            console.log('Realtime server did not respond in time.')
          }
        
          if (status === 'CLOSED') {
            console.log('Realtime channel was unexpectedly closed.')
          }
        })
        ```
        
        ### Notes:
        
        - `REALTIME_URL` is `'ws://localhost:4000/socket'` when developing locally and `'wss://<project_ref>.supabase.co/realtime/v1'` when connecting to your Supabase project.
        - `API_KEY` is a JWT whose claims must contain `exp` and `role` (existing database role).
        - Channel name can be any `string`.
        - Setting `private` to `true` means that the client will use RLS to determine if the user can connect or not to a given channel.
        
        ## Broadcast
        
        Your client can send and receive messages based on the `event`.
        
        ```js
        // Setup...
        
        const channel = client.channel('broadcast-test', { broadcast: { ack: false, self: false } })
        
        channel.on('broadcast', { event: 'some-event' }, (payload) => console.log(payload))
        
        channel.subscribe(async (status) => {
          if (status === 'SUBSCRIBED') {
            // Send message to other clients listening to 'broadcast-test' channel
            await channel.send({
              type: 'broadcast',
              event: 'some-event',
              payload: { hello: 'world' },
            })
          }
        })
        ```
        
        ### Notes:
        
        - Setting `ack` to `true` means that the `channel.send` promise will resolve once server replies with acknowledgment that it received the broadcast message request.
        - Setting `self` to `true` means that the client will receive the broadcast message it sent out.
        
        ### Broadcast Replay
        
        Broadcast Replay enables **private** channels to access messages that were sent earlier. Only messages published via [Broadcast From the Database](https://supabase.com/docs/guides/realtime/broadcast#trigger-broadcast-messages-from-your-database) are available for replay.
        
        You can configure replay with the following options:
        
        - **`since`** (Required): The epoch timestamp in milliseconds, specifying the earliest point from which messages should be retrieved.
        - **`limit`** (Optional): The number of messages to return. This must be a positive integer, with a maximum value of 25.
        
        Example:
        
        ```typescript
        const twelveHours = 12 * 60 * 60 * 1000
        const twelveHoursAgo = Date.now() - twelveHours
        
        const config = { private: true, broadcast: { replay: { since: twelveHoursAgo, limit: 10 } } }
        
        supabase
          .channel('main:room', { config })
          .on('broadcast', { event: 'my_event' }, (payload) => {
            if (payload?.meta?.replayed) {
              console.log('This message was sent earlier:', payload)
            } else {
              console.log('This is a new message', payload)
            }
            // ...
          })
          .subscribe()
        ```
        
        ## Presence
        
        Your client can track and sync state that's stored in the channel.
        
        ```js
        // Setup...
        
        const channel = client.channel('presence-test', {
          config: {
            presence: {
              key: '',
            },
          },
        })
        
        channel.on('presence', { event: 'sync' }, () => {
          console.log('Online users: ', channel.presenceState())
        })
        
        channel.on('presence', { event: 'join' }, ({ newPresences }) => {
          console.log('New users have joined: ', newPresences)
        })
        
        channel.on('presence', { event: 'leave' }, ({ leftPresences }) => {
          console.log('Users have left: ', leftPresences)
        })
        
        channel.subscribe(async (status) => {
          if (status === 'SUBSCRIBED') {
            const status = await channel.track({ user_id: 1 })
            console.log(status)
          }
        })
        ```
        
        > `config.presence.enabled` (set automatically if you add an `.on('presence', ...)` listener)
        > controls whether _this_ client receives presence state and updates from other clients —
        > without it, `presenceState()` stays empty for you. It does not affect whether other clients
        > see you: calling `track()` always makes you visible to subscribers that do have presence
        > enabled. On RLS-protected channels, receiving presence updates additionally requires the
        > `presence.read` policy to authorize this client.
        
        ## Postgres CDC
        
        Receive database changes on the client.
        
        ```js
        // Setup...
        
        const channel = client.channel('db-changes')
        
        channel.on('postgres_changes', { event: '*', schema: 'public' }, (payload) => {
          console.log('All changes in public schema: ', payload)
        })
        
        channel.on(
          'postgres_changes',
          { event: 'INSERT', schema: 'public', table: 'messages' },
          (payload) => {
            console.log('All inserts in messages table: ', payload)
          }
        )
        
        channel.on(
          'postgres_changes',
          { event: 'UPDATE', schema: 'public', table: 'users', filter: 'username=eq.Realtime' },
          (payload) => {
            console.log('All updates on users table when username is Realtime: ', payload)
          }
        )
        
        channel.subscribe(async (status) => {
          if (status === 'SUBSCRIBED') {
            console.log('Ready to receive database changes!')
          }
        })
        ```
        
        ### Filters
        
        The `filter` option accepts **either** a raw string **or** a
        `postgresChangesFilter()` builder — both produce the exact same wire format, so
        you can mix and match and existing string filters keep working unchanged:
        
        ```js
        // Raw string — always supported, fully backward compatible
        { event: 'UPDATE', schema: 'public', table: 'users', filter: 'id=eq.1' }
        
        // Builder — type-checked, ergonomic; the SDK serializes it for you
        { event: 'UPDATE', schema: 'public', table: 'users', filter: postgresChangesFilter().eq('id', 1) }
        ```
        
        A filter is a `column=operator.value` expression evaluated server-side. The
        following operators are supported:
        
        | Operator              | String form                  | Builder                                | Meaning                           |
        | --------------------- | ---------------------------- | -------------------------------------- | --------------------------------- |
        | `eq`                  | `id=eq.1`                    | `.eq('id', 1)`                         | equal                             |
        | `neq`                 | `id=neq.1`                   | `.neq('id', 1)`                        | not equal                         |
        | `lt` `lte` `gt` `gte` | `age=gte.18`                 | `.gte('age', 18)`                      | comparison                        |
        | `in`                  | `status=in.(active,pending)` | `.in('status', ['active', 'pending'])` | in list                           |
        | `like` `ilike`        | `title=like.%foo%`           | `.like('title', '%foo%')`              | pattern match (case in/sensitive) |
        | `is`                  | `deleted_at=is.null`         | `.is('deleted_at', null)`              | `IS null/true/false/unknown`      |
        | `match` `imatch`      | `title=match.^foo`           | `.match('title', '^foo')`              | POSIX regex match (`~` / `~*`)    |
        | `isdistinct`          | `value=isdistinct.1`         | `.isDistinct('value', 1)`              | NULL-safe inequality              |
        
        **Negation** — prefix any operator with `not.` (string) or use
        `.not(column, operator, value)` (builder):
        
        ```js
        // String
        { event: '*', schema: 'public', table: 'posts', filter: 'status=not.in.(draft,archived)' }
        
        // Builder
        {
          event: '*',
          schema: 'public',
          table: 'posts',
          filter: postgresChangesFilter().not('status', 'in', ['draft', 'archived']),
        }
        ```
        
        **AND composition** — multiple conditions are combined with commas and applied
        as an `AND`. With the builder you just chain calls:
        
        ```js
        // String
        { event: 'UPDATE', schema: 'public', table: 'orders', filter: 'amount=gt.100,status=in.(open,pending)' }
        
        // Builder — equivalent, chained
        {
          event: 'UPDATE',
          schema: 'public',
          table: 'orders',
          filter: postgresChangesFilter().gt('amount', 100).in('status', ['open', 'pending']),
        }
        ```
        
        #### Building filters with `postgresChangesFilter()`
        
        The builder (modeled on the `postgrest-js` filter methods) is the recommended,
        type-checked way to compose filters — but it is entirely optional; raw strings
        remain fully supported.
        
        ```js
        import { postgresChangesFilter } from '@supabase/realtime-js'
        
        channel.on(
          'postgres_changes',
          {
            event: 'UPDATE',
            schema: 'public',
            table: 'orders',
            // → 'amount=gt.100,status=not.in.(draft,archived)'
            filter: postgresChangesFilter().gt('amount', 100).not('status', 'in', ['draft', 'archived']),
          },
          (payload) => console.log(payload)
        )
        ```
        
        The builder exposes `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `like`,
        `ilike`, `match`, `imatch`, `is`, `isDistinct` and `not`. Call `.build()` if you
        need the raw string yourself (e.g. to log it or store it).
        
        **Values are sent verbatim** — the server has no quoting/escaping, so spaces and
        quotes are preserved as-is. The server separates conditions by commas outside
        parentheses, so a literal comma in a scalar value can't be expressed (commas
        inside `in.(…)` are fine); the builder throws on such values rather than
        silently producing a broken filter.
        
        > **Note for PostgREST users:** Realtime evaluates filters server-side over a
        > single table's WAL — there is no resource embedding (`!inner`, embedded
        > filters) and no `or()` grouping. Use `%` (not `*`) for `like`/`ilike`
        > wildcards, since filters travel in the WebSocket payload rather than a URL.
        
        ### Selecting columns
        
        Use `select` to receive only a subset of columns instead of the full row. This
        reduces payload size (helpful for large `bytea`/`jsonb` columns). The selected
        columns must be selectable by the subscribing role:
        
        ```js
        channel.on(
          'postgres_changes',
          { event: '*', schema: 'public', table: 'users', select: ['id', 'first_name'] },
          (payload) => {
            // payload.new only contains { id, first_name }
            console.log(payload)
          }
        )
        ```
        
        ## Get All Channels
        
        You can see all the channels that your client has instantiatied.
        
        ```js
        // Setup...
        
        client.getChannels()
        ```
        
        ## Cleanup
        
        It is highly recommended that you clean up your channels after you're done with them.
        
        - Remove a single channel
        
        ```js
        // Setup...
        
        const channel = client.channel('some-channel-to-remove')
        
        channel.unsubscribe()
        client.removeChannel(channel)
        ```
        
        - Remove all channels and close the connection
        
        ```js
        // Setup...
        
        client.removeAllChannels()
        client.disconnect()
        ```
        
        ## Development
        
        This package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:
        
        ### Building
        
        ```bash
        # Complete build (from monorepo root)
        pnpm nx build realtime-js
        
        # Build with watch mode for development
        pnpm nx build realtime-js --watch
        
        # Individual build targets
        pnpm nx build:main realtime-js    # CommonJS build (dist/main/)
        pnpm nx build:module realtime-js  # ES Modules build (dist/module/)
        
        # Other useful commands
        pnpm nx clean realtime-js         # Clean build artifacts
        pnpm nx lint realtime-js          # Run ESLint
        pnpm nx typecheck realtime-js     # TypeScript type checking
        ```
        
        #### Build Outputs
        
        - **CommonJS (`dist/main/`)** - For Node.js environments
        - **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)
        - **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects
        
        Note: Unlike some other packages, realtime-js doesn't include a UMD build since it's primarily used in Node.js or bundled applications.
        
        #### Validating Package Exports
        
        ```bash
        # Check if package exports are correctly configured
        pnpm nx check-exports realtime-js
        ```
        
        This command uses ["Are the types wrong?"](https://github.com/arethetypeswrong/arethetypeswrong.github.io) to verify that the package exports work correctly in different environments. Run this before publishing to ensure your package can be imported correctly by all consumers.
        
        ### Testing
        
        **No Docker or Supabase instance required!** The realtime-js tests use mocked WebSocket connections, so they're completely self-contained.
        
        ```bash
        # Run unit tests (from monorepo root)
        pnpm nx test realtime-js
        
        # Run tests with coverage report
        pnpm nx test:coverage realtime-js
        
        # Run tests in watch mode during development
        pnpm nx test:watch realtime-js
        ```
        
        #### Test Scripts Explained
        
        - **test** - Runs all unit tests once using Vitest
        - **test:coverage** - Runs tests and generates coverage report with terminal output
        - **test:watch** - Runs tests in interactive watch mode for development
        
        The tests mock WebSocket connections using `mock-socket`, so you can run them anytime without any external dependencies.
        
        ### Contributing
        
        We welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.
        
        For major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.
        
        ## Credits
        
        This repo draws heavily from [phoenix-js](https://github.com/phoenixframework/phoenix/tree/master/assets/js/phoenix).
        
        ## License
        
        MIT.
        
    • storage-js
      • README.md 35.7 KB
        <br />
        <p align="center">
          <a href="https://supabase.io">
                <picture>
              <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg">
              <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg">
              <img alt="Supabase Logo" width="300" src="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg">
            </picture>
          </a>
        
          <h1 align="center">Supabase Storage JS SDK</h1>
        
          <h3 align="center">JavaScript SDK to interact with Supabase Storage, including file storage and vector embeddings.</h3>
        
          <p align="center">
            <a href="https://supabase.com/docs/guides/storage">Guides</a>
            ·
            <a href="https://supabase.com/docs/reference/javascript/storage-createbucket">Reference Docs</a>
            ·
            <a href="https://supabase.github.io/supabase-js/storage-js/v2/spec.json">TypeDoc</a>
          </p>
        </p>
        
        <div align="center">
        
        [![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)
        [![Package](https://img.shields.io/npm/v/@supabase/storage-js)](https://www.npmjs.com/package/@supabase/storage-js)
        [![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)
        [![pkg.pr.new](https://pkg.pr.new/badge/supabase/storage-js)](https://pkg.pr.new/~/supabase/storage-js)
        
        </div>
        
        ## Requirements
        
        - **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)
        - For browser support, all modern browsers are supported
        
        > ⚠️ **Node.js 18 Deprecation Notice**
        >
        > Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.
        
        > ⚠️ **Node.js 20 Deprecation Notice**
        >
        > Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.
        
        ## Features
        
        - **File Storage**: Upload, download, list, move, and delete files
        - **Access Control**: Public and private buckets with fine-grained permissions
        - **Signed URLs**: Generate time-limited URLs for secure file access
        - **Image Transformations**: On-the-fly image resizing and optimization
        - **Vector Embeddings**: Store and query high-dimensional embeddings with similarity search
        - **Analytics Buckets**: Iceberg table-based buckets optimized for analytical queries and data processing
        - **Lifecycle**: Expire previous versions of objects after a number of days
        
        ## Quick Start Guide
        
        ### Installing the module
        
        ```bash
        npm install @supabase/storage-js
        ```
        
        ### Connecting to the storage backend
        
        There are two ways to use the Storage SDK:
        
        #### Option 1: Via Supabase Client (Recommended)
        
        If you're already using `@supabase/supabase-js`, access storage through the client:
        
        ```js
        import { createClient } from '@supabase/supabase-js'
        
        // Use publishable key for frontend applications
        const supabase = createClient('https://<project_ref>.supabase.co', '<your-publishable-key>')
        
        // Access storage
        const storage = supabase.storage
        
        // Access different bucket types
        const regularBucket = storage.from('my-bucket')
        const vectorBucket = storage.vectors.from('embeddings-bucket')
        const analyticsBucket = storage.analytics // Analytics API
        ```
        
        #### Option 2: Standalone StorageClient
        
        For backend applications or when you need to bypass Row Level Security:
        
        ```js
        import { StorageClient } from '@supabase/storage-js'
        
        const STORAGE_URL = 'https://<project_ref>.supabase.co/storage/v1'
        const SERVICE_KEY = '<your-secret-key>' // Use secret key for backend operations
        
        const storageClient = new StorageClient(STORAGE_URL, {
          apikey: SERVICE_KEY,
          Authorization: `Bearer ${SERVICE_KEY}`,
        })
        
        // Access different bucket types
        const regularBucket = storageClient.from('my-bucket')
        const vectorBucket = storageClient.vectors.from('embeddings-bucket')
        const analyticsBucket = storageClient.analytics // Analytics API
        ```
        
        > **When to use each approach:**
        >
        > - Use `supabase.storage` when working with other Supabase features (auth, database, etc.) in frontend applications
        > - Use `new StorageClient()` for backend applications, Edge Functions, or when you need to bypass RLS policies
        
        > **Note:** Refer to the [Storage Access Control guide](https://supabase.com/docs/guides/storage/access-control) for detailed information on creating RLS policies.
        
        ### Understanding Bucket Types
        
        Supabase Storage supports three types of buckets, each optimized for different use cases:
        
        #### 1. Regular Storage Buckets (File Storage)
        
        Standard buckets for storing files, images, videos, and other assets.
        
        ```js
        // Create regular storage bucket
        const { data, error } = await storageClient.createBucket('my-files', {
          public: false,
        })
        
        // Upload files
        await storageClient.from('my-files').upload('avatar.png', file)
        ```
        
        **Use cases:** User uploads, media assets, documents, backups
        
        #### 2. Vector Buckets (Embeddings Storage)
        
        Specialized buckets for storing and querying high-dimensional vector embeddings.
        
        ```js
        // Create vector bucket
        await storageClient.vectors.createBucket('embeddings-prod')
        
        // Create index and insert vectors
        const bucket = storageClient.vectors.from('embeddings-prod')
        await bucket.createIndex({
          indexName: 'documents',
          dimension: 1536,
          distanceMetric: 'cosine',
        })
        ```
        
        **Use cases:** Semantic search, AI-powered recommendations, similarity matching
        
        **[See full Vector Embeddings documentation below](#vector-embeddings)**
        
        #### 3. Analytics Buckets
        
        Specialized buckets using Apache Iceberg table format, optimized for analytical queries and large-scale data processing.
        
        ```js
        // Create analytics bucket
        await storageClient.analytics.createBucket('analytics-data')
        
        // List analytics buckets
        const { data, error } = await storageClient.analytics.listBuckets()
        
        // Delete analytics bucket
        await storageClient.analytics.deleteBucket('analytics-data')
        ```
        
        **Use cases:** Time-series data, analytical queries, data lakes, large-scale data processing, business intelligence
        
        **[See full Analytics Buckets documentation below](#analytics-buckets)**
        
        ---
        
        ### Handling resources
        
        #### Handling Storage Buckets
        
        - Create a new Storage bucket:
        
          ```js
          const { data, error } = await storageClient.createBucket(
            'test_bucket', // Bucket name (must be unique)
            { public: false } // Bucket options
          )
          ```
        
        - Retrieve the details of an existing Storage bucket:
        
          ```js
          const { data, error } = await storageClient.getBucket('test_bucket')
          ```
        
        - Update a new Storage bucket:
        
          ```js
          const { data, error } = await storageClient.updateBucket(
            'test_bucket', // Bucket name
            { public: false } // Bucket options
          )
          ```
        
        - Remove all objects inside a single bucket:
        
          ```js
          const { data, error } = await storageClient.emptyBucket('test_bucket')
          ```
        
        - Delete an existing bucket (a bucket can't be deleted with existing objects inside it):
        
          ```js
          const { data, error } = await storageClient.deleteBucket('test_bucket')
          ```
        
        - Retrieve the details of all Storage buckets within an existing project:
        
          ```js
          // List all buckets
          const { data, error } = await storageClient.listBuckets()
        
          // List buckets with options (pagination, sorting, search)
          const { data, error } = await storageClient.listBuckets({
            limit: 10,
            offset: 0,
            sortColumn: 'created_at',
            sortOrder: 'desc',
            search: 'prod',
          })
          ```
        
        - Manage a bucket's lifecycle policy. Rules expire **previous versions** of objects after a number of days, so versioning needs to be enabled or the policy has nothing to act on. This is Standard buckets only, and the project must have lifecycle enabled.
        
          ```js
          // Replaces every existing rule
          const { data, error } = await storageClient.updateBucketLifecycle('test_bucket', {
            rules: [
              {
                id: 'expire-old-versions',
                status: 'Enabled',
                filter: {},
                noncurrentVersionExpiration: { noncurrentDays: 30 },
              },
            ],
          })
        
          // Fails with NoSuchLifecycleConfiguration when the bucket has no policy
          const { data: config, error: configError } = await storageClient.getBucketLifecycle('test_bucket')
        
          await storageClient.deleteBucketLifecycle('test_bucket')
          ```
        
        #### Handling Files
        
        - Upload a file to an existing bucket:
        
          ```js
          const fileBody = ... // load your file here
        
          const { data, error } = await storageClient.from('bucket').upload('path/to/file', fileBody)
          ```
        
          > Note:  
          > The path in `data.Key` is prefixed by the bucket ID and is not the value which should be passed to the `download` method in order to fetch the file.  
          > To fetch the file via the `download` method, use `data.path` and `data.bucketId` as follows:
          >
          > ```javascript
          > const { data, error } = await storageClient.from('bucket').upload('/folder/file.txt', fileBody)
          > // check for errors
          > const { data2, error2 } = await storageClient.from(data.bucketId).download(data.path)
          > ```
        
          > Note: The `upload` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-upload).
        
        - Download a file from an exisiting bucket:
        
          ```js
          const { data, error } = await storageClient.from('bucket').download('path/to/file')
          ```
        
        - List all the files within a bucket:
        
          ```js
          const { data, error } = await storageClient.from('bucket').list('folder')
          ```
        
          > Note: The `list` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-list).
        
        - Replace an existing file at the specified path with a new one:
        
          ```js
          const fileBody = ... // load your file here
        
          const { data, error } = await storageClient
            .from('bucket')
            .update('path/to/file', fileBody)
          ```
        
          > Note: The `upload` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-upload).
        
        - Move an existing file:
        
          ```js
          const { data, error } = await storageClient
            .from('bucket')
            .move('old/path/to/file', 'new/path/to/file')
          ```
        
        - Delete files within the same bucket:
        
          ```js
          const { data, error } = await storageClient.from('bucket').remove(['path/to/file'])
          ```
        
        - Create signed URL to download file without requiring permissions:
        
          ```js
          const expireIn = 60
        
          const { data, error } = await storageClient
            .from('bucket')
            .createSignedUrl('path/to/file', expireIn)
          ```
        
        - Retrieve URLs for assets in public buckets:
        
          ```js
          const { data, error } = await storageClient.from('public-bucket').getPublicUrl('path/to/file')
          ```
        
        ## Analytics Buckets
        
        Supabase Storage provides specialized analytics buckets using Apache Iceberg table format, optimized for analytical workloads and large-scale data processing. These buckets are designed for data lake architectures, time-series data, and business intelligence applications.
        
        ### What are Analytics Buckets?
        
        Analytics buckets use the Apache Iceberg open table format, providing:
        
        - **ACID transactions** for data consistency
        - **Schema evolution** without data rewrites
        - **Time travel** to query historical data
        - **Efficient metadata management** for large datasets
        - **Optimized for analytical queries** rather than individual file operations
        
        ### When to Use Analytics Buckets
        
        **Use analytics buckets for:**
        
        - Time-series data (logs, metrics, events)
        - Data lake architectures
        - Business intelligence and reporting
        - Large-scale batch processing
        - Analytical workloads requiring ACID guarantees
        
        **Use regular storage buckets for:**
        
        - User file uploads (images, documents, videos)
        - Individual file management
        - Content delivery
        - Simple object storage needs
        
        ### Quick Start
        
        You can access analytics functionality through the `analytics` property on your storage client:
        
        #### Via Supabase Client
        
        ```typescript
        import { createClient } from '@supabase/supabase-js'
        
        const supabase = createClient('https://your-project.supabase.co', 'your-publishable-key')
        
        // Access analytics operations
        const analytics = supabase.storage.analytics
        
        // Create an analytics bucket
        const { data, error } = await analytics.createBucket('analytics-data')
        if (error) {
          console.error('Failed to create analytics bucket:', error.message)
        } else {
          console.log('Created bucket:', data.name)
        }
        ```
        
        #### Via StorageClient
        
        ```typescript
        import { StorageClient } from '@supabase/storage-js'
        
        const storageClient = new StorageClient('https://your-project.supabase.co/storage/v1', {
          apikey: 'YOUR_API_KEY',
          Authorization: 'Bearer YOUR_TOKEN',
        })
        
        // Access analytics operations
        const analytics = storageClient.analytics
        
        // Create an analytics bucket
        await analytics.createBucket('analytics-data')
        ```
        
        ### API Reference
        
        #### Create Analytics Bucket
        
        Creates a new analytics bucket using Iceberg table format:
        
        ```typescript
        const { data, error } = await analytics.createBucket('my-analytics-bucket')
        
        if (error) {
          console.error('Error:', error.message)
        } else {
          console.log('Created bucket:', data)
        }
        ```
        
        **Returns:**
        
        ```typescript
        {
          data: {
            id: string
            type: 'ANALYTICS'
            format: string
            created_at: string
            updated_at: string
          } | null
          error: StorageError | null
        }
        ```
        
        #### List Analytics Buckets
        
        Retrieves all analytics buckets in your project with optional filtering and pagination:
        
        ```typescript
        const { data, error } = await analytics.listBuckets({
          limit: 10,
          offset: 0,
          sortColumn: 'created_at',
          sortOrder: 'desc',
          search: 'prod',
        })
        
        if (data) {
          console.log(`Found ${data.length} analytics buckets`)
          data.forEach((bucket) => {
            console.log(`- ${bucket.id} (created: ${bucket.created_at})`)
          })
        }
        ```
        
        **Parameters:**
        
        - `limit?: number` - Maximum number of buckets to return
        - `offset?: number` - Number of buckets to skip (for pagination)
        - `sortColumn?: 'id' | 'name' | 'created_at' | 'updated_at'` - Column to sort by
        - `sortOrder?: 'asc' | 'desc'` - Sort direction
        - `search?: string` - Search term to filter bucket names
        
        **Returns:**
        
        ```typescript
        {
          data: AnalyticBucket[] | null
          error: StorageError | null
        }
        ```
        
        **Example with Pagination:**
        
        ```typescript
        // Fetch first page
        const firstPage = await analytics.listBuckets({
          limit: 100,
          offset: 0,
          sortColumn: 'created_at',
          sortOrder: 'desc',
        })
        
        // Fetch second page
        const secondPage = await analytics.listBuckets({
          limit: 100,
          offset: 100,
          sortColumn: 'created_at',
          sortOrder: 'desc',
        })
        ```
        
        #### Delete Analytics Bucket
        
        Deletes an analytics bucket. The bucket must be empty before deletion.
        
        ```typescript
        const { data, error } = await analytics.deleteBucket('old-analytics-bucket')
        
        if (error) {
          console.error('Failed to delete:', error.message)
        } else {
          console.log('Bucket deleted:', data.message)
        }
        ```
        
        **Returns:**
        
        ```typescript
        {
          data: { message: string } | null
          error: StorageError | null
        }
        ```
        
        > **Note:** A bucket cannot be deleted if it contains data. You must empty the bucket first.
        
        #### Get Iceberg Catalog for Advanced Operations
        
        For advanced operations like creating tables, namespaces, and querying Iceberg metadata, use the `from()` method to get a configured [iceberg-js](https://github.com/supabase/iceberg-js) client:
        
        ```typescript
        // Get an Iceberg REST Catalog client for your analytics bucket
        const catalog = analytics.from('analytics-data')
        
        // Create a namespace
        await catalog.createNamespace({ namespace: ['default'] }, { properties: { owner: 'data-team' } })
        
        // Create a table with schema
        await catalog.createTable(
          { namespace: ['default'] },
          {
            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',
            },
          }
        )
        
        // List tables in namespace
        const tables = await catalog.listTables({ namespace: ['default'] })
        console.log(tables) // [{ namespace: ['default'], name: 'events' }]
        
        // Load table metadata
        const table = await catalog.loadTable({ namespace: ['default'], name: 'events' })
        
        // Update table properties
        await catalog.updateTable(
          { namespace: ['default'], name: 'events' },
          { properties: { 'read.split.target-size': '134217728' } }
        )
        
        // Drop table
        await catalog.dropTable({ namespace: ['default'], name: 'events' })
        
        // Drop namespace
        await catalog.dropNamespace({ namespace: ['default'] })
        ```
        
        **Returns:** `IcebergRestCatalog` instance from [iceberg-js](https://github.com/supabase/iceberg-js)
        
        > **Note:** The `from()` method returns an Iceberg REST Catalog client that provides full access to the Apache Iceberg REST API. For complete documentation of available operations, see the [iceberg-js documentation](https://supabase.github.io/iceberg-js/).
        
        ### Error Handling
        
        Analytics buckets use the same error handling pattern as the rest of the Storage SDK:
        
        ```typescript
        const { data, error } = await analytics.createBucket('my-bucket')
        
        if (error) {
          console.error('Error:', error.message)
          console.error('Status:', error.status)
          console.error('Status Code:', error.statusCode)
          // Handle error appropriately
        }
        ```
        
        #### Throwing Errors
        
        You can configure the client to throw errors instead of returning them:
        
        ```typescript
        const analytics = storageClient.analytics
        analytics.throwOnError()
        
        try {
          const { data } = await analytics.createBucket('my-bucket')
          // data is guaranteed to be present
          console.log('Success:', data)
        } catch (error) {
          if (error instanceof StorageApiError) {
            console.error('API Error:', error.statusCode, error.message)
          }
        }
        ```
        
        ### TypeScript Types
        
        The library exports TypeScript types for analytics buckets:
        
        ```typescript
        import type { AnalyticBucket, BucketType, StorageError } from '@supabase/storage-js'
        
        // AnalyticBucket type
        interface AnalyticBucket {
          id: string
          type: 'ANALYTICS'
          format: string
          created_at: string
          updated_at: string
        }
        ```
        
        ### Common Patterns
        
        #### Checking if a Bucket Exists
        
        ```typescript
        async function bucketExists(bucketName: string): Promise<boolean> {
          const { data, error } = await analytics.listBuckets({
            search: bucketName,
          })
        
          if (error) {
            console.error('Error checking bucket:', error.message)
            return false
          }
        
          return data?.some((bucket) => bucket.id === bucketName) ?? false
        }
        ```
        
        #### Creating Bucket with Error Handling
        
        ```typescript
        async function ensureAnalyticsBucket(bucketName: string) {
          // Try to create the bucket
          const { data, error } = await analytics.createBucket(bucketName)
        
          if (error) {
            // Check if bucket already exists (conflict error)
            if (error.statusCode === '409') {
              console.log(`Bucket '${bucketName}' already exists`)
              return { success: true, created: false }
            }
        
            // Other error occurred
            console.error('Failed to create bucket:', error.message)
            return { success: false, error }
          }
        
          console.log(`Created new bucket: '${bucketName}'`)
          return { success: true, created: true, data }
        }
        ```
        
        #### Listing All Buckets with Pagination
        
        ```typescript
        async function getAllAnalyticsBuckets() {
          const allBuckets: AnalyticBucket[] = []
          let offset = 0
          const limit = 100
        
          while (true) {
            const { data, error } = await analytics.listBuckets({
              limit,
              offset,
              sortColumn: 'created_at',
              sortOrder: 'desc',
            })
        
            if (error) {
              console.error('Error fetching buckets:', error.message)
              break
            }
        
            if (!data || data.length === 0) {
              break
            }
        
            allBuckets.push(...data)
        
            // If we got fewer results than the limit, we've reached the end
            if (data.length < limit) {
              break
            }
        
            offset += limit
          }
        
          return allBuckets
        }
        ```
        
        ## Vector Embeddings
        
        Supabase Storage provides built-in support for storing and querying high-dimensional vector embeddings, powered by S3 Vectors. This enables semantic search, similarity matching, and AI-powered applications without needing a separate vector database.
        
        > **Note:** Vector embeddings functionality is available in `@supabase/storage-js` v2.76 and later.
        
        ### Features
        
        - **Vector Buckets**: Organize vector indexes into logical containers
        - **Vector Indexes**: Define schemas with configurable dimensions and distance metrics
        - **Batch Operations**: Insert/update/delete up to 500 vectors per request
        - **Similarity Search**: Query for nearest neighbors using cosine, euclidean, or dot product distance
        - **Metadata Filtering**: Store and filter vectors by arbitrary JSON metadata
        - **Pagination**: Efficiently scan large vector datasets
        - **Parallel Scanning**: Distribute scans across multiple workers for high throughput
        - **Cross-platform**: Works in Node.js, browsers, and edge runtimes
        
        ### Quick Start
        
        You can access vector functionality in three ways, depending on your use case:
        
        #### Option 1: Via Supabase Client (Most Common)
        
        If you're using the full Supabase client:
        
        ```typescript
        import { createClient } from '@supabase/supabase-js'
        
        const supabase = createClient('https://your-project.supabase.co', 'your-publishable-key')
        
        // Access vector operations through storage
        const vectors = supabase.storage.vectors
        
        // Create a vector bucket
        await vectors.createBucket('embeddings-prod')
        
        // Create an index
        const bucket = vectors.from('embeddings-prod')
        await bucket.createIndex({
          indexName: 'documents-openai',
          dataType: 'float32',
          dimension: 1536,
          distanceMetric: 'cosine',
        })
        
        // Insert vectors
        const index = bucket.index('documents-openai')
        await index.putVectors({
          vectors: [
            {
              key: 'doc-1',
              data: { float32: [0.1, 0.2, 0.3 /* ...1536 dimensions */] },
              metadata: { title: 'Introduction', category: 'docs' },
            },
          ],
        })
        
        // Query similar vectors
        const { data, error } = await index.queryVectors({
          queryVector: { float32: [0.15, 0.25, 0.35 /* ...1536 dimensions */] },
          topK: 5,
          returnDistance: true,
          returnMetadata: true,
        })
        
        if (data) {
          data.vectors.forEach((match) => {
            console.log(`${match.key}: distance=${match.distance}`)
            console.log('Metadata:', match.metadata)
          })
        }
        ```
        
        #### Option 2: Via StorageClient
        
        If you're using the standalone `StorageClient` for storage operations, access vectors through the `vectors` property:
        
        ```typescript
        import { StorageClient } from '@supabase/storage-js'
        
        const storageClient = new StorageClient('https://your-project.supabase.co/storage/v1', {
          apikey: 'YOUR_API_KEY',
          Authorization: 'Bearer YOUR_TOKEN',
        })
        
        // Access vector operations
        const vectors = storageClient.vectors
        
        // Use the same API as shown in Option 1
        await vectors.createBucket('embeddings-prod')
        const bucket = vectors.from('embeddings-prod')
        // ... rest of operations
        ```
        
        #### Option 3: Standalone Vector Client
        
        For vector-only applications that don't need regular file storage operations:
        
        ```typescript
        import { StorageVectorsClient } from '@supabase/storage-js'
        
        // Initialize standalone vector client
        const vectorClient = new StorageVectorsClient('https://your-project.supabase.co/storage/v1', {
          headers: { Authorization: 'Bearer YOUR_TOKEN' },
        })
        
        // Use the same API as shown in Option 1
        await vectorClient.createBucket('embeddings-prod')
        const bucket = vectorClient.from('embeddings-prod')
        // ... rest of operations
        ```
        
        > **When to use each approach:**
        >
        > - **Option 1**: When using other Supabase features (auth, database, realtime)
        > - **Option 2**: When working with both file storage and vectors
        > - **Option 3**: For dedicated vector-only applications without file storage
        
        ### API Reference
        
        #### Client Initialization
        
        ```typescript
        const vectorClient = new StorageVectorsClient(url, options?)
        ```
        
        **Options:**
        
        - `headers?: Record<string, string>` - Custom HTTP headers (e.g., Authorization)
        - `fetch?: Fetch` - Custom fetch implementation
        
        #### Vector Buckets
        
        Vector buckets are top-level containers for organizing vector indexes.
        
        ##### Create Bucket
        
        ```typescript
        const { data, error } = await vectorClient.createBucket('my-bucket')
        ```
        
        ##### Get Bucket
        
        ```typescript
        const { data, error } = await vectorClient.getBucket('my-bucket')
        console.log('Created at:', new Date(data.vectorBucket.creationTime! * 1000))
        ```
        
        ##### List Buckets
        
        ```typescript
        const { data, error } = await vectorClient.listBuckets({
          prefix: 'prod-',
          maxResults: 100,
        })
        
        // Pagination
        if (data?.nextToken) {
          const next = await vectorClient.listBuckets({ nextToken: data.nextToken })
        }
        ```
        
        ##### Delete Bucket
        
        ```typescript
        // Bucket must be empty (all indexes deleted first)
        const { error } = await vectorClient.deleteBucket('my-bucket')
        ```
        
        #### Vector Indexes
        
        Vector indexes define the schema for embeddings including dimension and distance metric.
        
        ##### Create Index
        
        ```typescript
        const bucket = vectorClient.from('my-bucket')
        
        await bucket.createIndex({
          indexName: 'my-index',
          dataType: 'float32',
          dimension: 1536,
          distanceMetric: 'cosine', // 'cosine' | 'euclidean' | 'dotproduct'
          metadataConfiguration: {
            nonFilterableMetadataKeys: ['raw_text', 'internal_id'],
          },
        })
        ```
        
        **Distance Metrics:**
        
        - `cosine` - Cosine similarity (normalized dot product)
        - `euclidean` - Euclidean distance (L2 norm)
        - `dotproduct` - Dot product similarity
        
        ##### Get Index
        
        ```typescript
        const { data, error } = await bucket.getIndex('my-index')
        console.log('Dimension:', data?.index.dimension)
        console.log('Distance metric:', data?.index.distanceMetric)
        ```
        
        ##### List Indexes
        
        ```typescript
        const { data, error } = await bucket.listIndexes({
          prefix: 'documents-',
          maxResults: 100,
        })
        ```
        
        ##### Delete Index
        
        ```typescript
        // Deletes index and all its vectors
        await bucket.deleteIndex('my-index')
        ```
        
        #### Vector Operations
        
        ##### Insert/Update Vectors (Upsert)
        
        ```typescript
        const index = vectorClient.from('my-bucket').index('my-index')
        
        await index.putVectors({
          vectors: [
            {
              key: 'unique-id-1',
              data: {
                float32: [
                  /* 1536 numbers */
                ],
              },
              metadata: {
                title: 'Document Title',
                category: 'technical',
                page: 1,
              },
            },
            // ... up to 500 vectors per request
          ],
        })
        ```
        
        **Limitations:**
        
        - 1-500 vectors per request
        - Vectors must match index dimension
        - Keys must be unique within index
        
        ##### Get Vectors by Key
        
        ```typescript
        const { data, error } = await index.getVectors({
          keys: ['doc-1', 'doc-2', 'doc-3'],
          returnData: true, // Include embeddings
          returnMetadata: true, // Include metadata
        })
        
        data?.vectors.forEach((v) => {
          console.log(v.key, v.metadata)
        })
        ```
        
        ##### Query Similar Vectors (ANN Search)
        
        ```typescript
        const { data, error } = await index.queryVectors({
          queryVector: {
            float32: [
              /* 1536 numbers */
            ],
          },
          topK: 10,
          filter: {
            category: 'technical',
            published: true,
          },
          returnDistance: true,
          returnMetadata: true,
        })
        
        // Results ordered by similarity
        data?.vectors.forEach((match) => {
          console.log(`${match.key}: distance=${match.distance}`)
        })
        ```
        
        S3 vector buckets support deep queries with `topK` up to 10,000, returning at most 100 vectors per response. Pass the response's `nextToken` with the same query to retrieve the next page:
        
        ```typescript
        const query = {
          queryVector: { float32: embedding },
          topK: 1000,
          returnDistance: true,
        }
        
        let nextToken: string | undefined
        
        do {
          const { data, error } = await index.queryVectors({ ...query, nextToken })
          if (error) throw error
        
          for (const vector of data.vectors) {
            console.log(`${vector.key}: distance=${vector.distance}`)
          }
        
          nextToken = data.nextToken
        } while (nextToken)
        ```
        
        The pgvector backend supports `topK` up to 100 and does not support `nextToken` pagination.
        
        **Filter Syntax:**
        The `filter` parameter accepts arbitrary JSON for metadata filtering. Non-filterable keys (configured at index creation) cannot be used in filters but can still be returned.
        
        ##### List/Scan Vectors
        
        ```typescript
        // Simple pagination
        let nextToken: string | undefined
        do {
          const { data } = await index.listVectors({
            maxResults: 500,
            nextToken,
            returnMetadata: true,
          })
        
          console.log('Batch:', data?.vectors.length)
          nextToken = data?.nextToken
        } while (nextToken)
        
        // Parallel scanning (4 workers)
        const workers = [0, 1, 2, 3].map(async (segmentIndex) => {
          const { data } = await index.listVectors({
            segmentCount: 4,
            segmentIndex,
            returnMetadata: true,
          })
          return data?.vectors || []
        })
        
        const results = await Promise.all(workers)
        const allVectors = results.flat()
        ```
        
        **Limitations:**
        
        - `maxResults`: 1-1000 (default: 500)
        - `segmentCount`: 1-16
        - Response may be limited by 1MB size
        
        ##### Delete Vectors
        
        ```typescript
        await index.deleteVectors({
          keys: ['doc-1', 'doc-2', 'doc-3'],
          // ... up to 500 keys per request
        })
        ```
        
        ### Error Handling
        
        The library uses a consistent error handling pattern:
        
        ```typescript
        const { data, error } = await vectorClient.createBucket('my-bucket')
        
        if (error) {
          console.error('Error:', error.message)
          console.error('Status:', error.status)
          console.error('Code:', error.statusCode)
        }
        ```
        
        #### Error Codes
        
        | Code                         | HTTP | Description             |
        | ---------------------------- | ---- | ----------------------- |
        | `InternalError`              | 500  | Internal server error   |
        | `S3VectorConflictException`  | 409  | Resource already exists |
        | `S3VectorNotFoundException`  | 404  | Resource not found      |
        | `S3VectorBucketNotEmpty`     | 400  | Bucket contains indexes |
        | `S3VectorMaxBucketsExceeded` | 400  | Bucket quota exceeded   |
        | `S3VectorMaxIndexesExceeded` | 400  | Index quota exceeded    |
        
        #### Throwing Errors
        
        You can configure the client to throw errors instead:
        
        ```typescript
        const vectorClient = new StorageVectorsClient(url, options)
        vectorClient.throwOnError()
        
        try {
          const { data } = await vectorClient.createBucket('my-bucket')
          // data is guaranteed to be present
        } catch (error) {
          if (error instanceof StorageVectorsApiError) {
            console.error('API Error:', error.statusCode)
          }
        }
        ```
        
        ### Advanced Usage
        
        #### Scoped Clients
        
        Create scoped clients for cleaner code:
        
        ```typescript
        // Bucket-scoped operations
        const bucket = vectorClient.from('embeddings-prod')
        await bucket.createIndex({
          /* ... */
        })
        await bucket.listIndexes()
        
        // Index-scoped operations
        const index = bucket.index('documents-openai')
        await index.putVectors({
          /* ... */
        })
        await index.queryVectors({
          /* ... */
        })
        ```
        
        #### Custom Fetch
        
        Provide a custom fetch implementation:
        
        ```typescript
        import { StorageVectorsClient } from '@supabase/storage-js'
        
        const vectorClient = new StorageVectorsClient(url, {
          fetch: customFetch,
          headers: {
            /* ... */
          },
        })
        ```
        
        #### Batch Processing
        
        Process large datasets in batches:
        
        ```typescript
        async function insertLargeDataset(vectors: VectorObject[]) {
          const batchSize = 500
        
          for (let i = 0; i < vectors.length; i += batchSize) {
            const batch = vectors.slice(i, i + batchSize)
            await index.putVectors({ vectors: batch })
            console.log(`Inserted ${i + batch.length}/${vectors.length}`)
          }
        }
        ```
        
        #### Float32 Validation
        
        Ensure vectors are properly normalized to float32:
        
        ```typescript
        import { normalizeToFloat32 } from '@supabase/storage-js'
        
        const vector = normalizeToFloat32([0.1, 0.2, 0.3 /* ... */])
        ```
        
        ### Type Definitions
        
        The library exports comprehensive TypeScript types:
        
        ```typescript
        import type {
          VectorBucket,
          VectorIndex,
          VectorData,
          VectorObject,
          VectorMatch,
          VectorMetadata,
          DistanceMetric,
          ApiResponse,
          StorageVectorsError,
        } from '@supabase/storage-js'
        ```
        
        ## Development
        
        This package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:
        
        ### Building
        
        #### Build Scripts Overview
        
        ```bash
        # Build the package
        pnpm nx build storage-js
        
        # Watch mode for development
        pnpm nx build storage-js --watch
        
        # Generate documentation
        pnpm nx docs storage-js
        ```
        
        ### Testing
        
        **Important:** The storage-js tests require a local Supabase stack running via the Supabase CLI. Docker must be running since the Supabase CLI uses it internally.
        
        #### Prerequisites
        
        1. **Docker** must be installed and running (used by Supabase CLI internally)
        2. **Supabase CLI** — installed automatically via `pnpm exec supabase`
        
        #### Test Scripts Overview
        
        | Script            | Description                       | What it does                                                      |
        | ----------------- | --------------------------------- | ----------------------------------------------------------------- |
        | `test:storage`    | **Complete test workflow**        | Runs the full test cycle: clean → start infra → run tests → clean |
        | `test:suite`      | **Jest tests only**               | Runs Jest tests with coverage (requires infra to be running)      |
        | `test:infra`      | **Start test infrastructure**     | Starts Supabase CLI stack (PostgreSQL, Storage API, Kong, etc.)   |
        | `test:clean-post` | **Stop and clean infrastructure** | Stops the Supabase CLI stack                                      |
        
        #### Running Tests
        
        ##### Option 1: Complete Test Run (Recommended)
        
        This handles everything automatically - starting infrastructure, running tests, and cleaning up:
        
        ```bash
        # From monorepo root
        pnpm nx test:storage storage-js
        ```
        
        This command will:
        
        1. Stop any existing test containers
        2. Build and start fresh test infrastructure
        3. Wait for services to be ready
        4. Run all Jest tests with coverage
        5. Clean up all containers after tests complete
        
        ##### Option 2: Manual Infrastructure Management
        
        Useful for development when you want to run tests multiple times without restarting Docker:
        
        ```bash
        # Step 1: Start the test infrastructure
        # From root
        pnpm nx test:infra storage-js
        # This starts: PostgreSQL, Storage API, Kong Gateway, and imgproxy
        
        # Step 2: Run tests (can run multiple times)
        pnpm nx test:suite storage-js
        
        # Step 3: When done, clean up the infrastructure
        pnpm nx test:clean-post storage-js
        ```
        
        ##### Option 3: Development Mode
        
        For actively developing and debugging tests:
        
        ```bash
        # Start infrastructure once (from root)
        pnpm nx test:infra storage-js
        
        # Run tests in watch mode
        pnpm nx test:suite storage-js --watch
        
        # Clean up when done
        pnpm nx test:clean-post storage-js
        ```
        
        #### Test Infrastructure Details
        
        The test infrastructure is managed via the Supabase CLI (`pnpm exec supabase start --workdir test`), which starts a local Supabase stack defined by the config in `test/`. This includes PostgreSQL, the Storage API, Kong Gateway, and supporting services.
        
        #### Common Issues and Solutions
        
        | Issue                             | Solution                                                                                          |
        | --------------------------------- | ------------------------------------------------------------------------------------------------- |
        | Port conflicts                    | Another service is using a required port. Run `pnpm nx test:clean-post storage-js` then try again |
        | "request failed, reason:" errors  | Infrastructure isn't running. Run `pnpm nx test:infra storage-js` first                           |
        | Tests fail with connection errors | Ensure Docker is running (Supabase CLI requires Docker)                                           |
        | Stack already running             | Run `pnpm nx test:clean-post storage-js` to stop it before restarting                             |
        
        #### Understanding Test Failures
        
        - **StorageUnknownError with "request failed"**: Infrastructure not running
        - **Snapshot failures**: Expected test data has changed — review and update snapshots if needed
        
        ### Contributing
        
        We welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.
        
        For major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.
        
    • supabase-js
      • README.md 11.7 KB
        <br />
        <p align="center">
          <a href="https://supabase.io">
                <picture>
              <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg">
              <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg">
              <img alt="Supabase Logo" width="300" src="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg">
            </picture>
          </a>
        
          <h1 align="center">Supabase JS SDK</h1>
        
          <h3 align="center">Isomorphic JavaScript SDK for Supabase - combining Auth, Database, Storage, Functions, and Realtime.</h3>
        
          <p align="center">
            <a href="https://supabase.com/docs/guides/getting-started">Guides</a>
            ·
            <a href="https://supabase.com/docs/reference/javascript/start">Reference Docs</a>
            ·
            <a href="https://supabase.github.io/supabase-js/supabase-js/v2/spec.json">TypeDoc</a>
          </p>
        </p>
        
        <div align="center">
        
        [![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)
        [![Package](https://img.shields.io/npm/v/@supabase/supabase-js)](https://www.npmjs.com/package/@supabase/supabase-js)
        [![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)
        [![pkg.pr.new](https://pkg.pr.new/badge/supabase/supabase-js)](https://pkg.pr.new/~/supabase/supabase-js)
        
        </div>
        
        ## Usage
        
        First of all, you need to install the library:
        
        ```sh
        npm install @supabase/supabase-js
        ```
        
        Then you're able to import the library and establish the connection with the database:
        
        ```js
        import { createClient } from '@supabase/supabase-js'
        
        // Create a single supabase client for interacting with your database
        const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')
        ```
        
        ### UMD
        
        You can use plain `<script>`s to import supabase-js from CDNs, like:
        
        ```html
        <script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
        ```
        
        or even:
        
        ```html
        <script src="https://unpkg.com/@supabase/supabase-js@2"></script>
        ```
        
        Then you can use it from a global `supabase` variable:
        
        ```html
        <script>
          const { createClient } = supabase
          const _supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')
        
          console.log('Supabase Instance: ', _supabase)
          // ...
        </script>
        ```
        
        ### ESM
        
        You can use `<script type="module">` to import supabase-js from CDNs, like:
        
        ```html
        <script type="module">
          import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm'
          const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')
        
          console.log('Supabase Instance: ', supabase)
          // ...
        </script>
        ```
        
        ### Deno
        
        You can use supabase-js in the Deno runtime via [JSR](https://jsr.io/@supabase/supabase-js):
        
        ```js
        import { createClient } from 'jsr:@supabase/supabase-js@2'
        ```
        
        ### Custom `fetch` implementation
        
        `supabase-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:
        
        ```js
        import { createClient } from '@supabase/supabase-js'
        
        // Provide a custom `fetch` implementation as an option
        const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key', {
          global: {
            fetch: (...args) => fetch(...args),
          },
        })
        ```
        
        ### Distributed Tracing with OpenTelemetry
        
        The Supabase JS SDK can attach W3C/OpenTelemetry trace context headers (`traceparent`, `tracestate`, `baggage`) to outgoing requests, enabling end-to-end request tracing from your client application through Supabase services.
        
        Trace propagation is **opt-in** and disabled by default. When enabled, headers are only attached to requests targeting Supabase domains (`*.supabase.co`, `*.supabase.in`, `localhost`).
        
        #### Enable trace propagation
        
        Opting in takes two steps: install `@opentelemetry/api`, and load the tracing runtime by importing the `@supabase/supabase-js/tracing` subpath once at your application entry point. The main bundle contains no OpenTelemetry code — the subpath import is what wires it up.
        
        ```js
        import '@supabase/supabase-js/tracing'
        import { createClient } from '@supabase/supabase-js'
        import { trace } from '@opentelemetry/api'
        
        const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {
          tracePropagation: true,
        })
        
        const tracer = trace.getTracer('my-app')
        await tracer.startActiveSpan('fetch-users', async (span) => {
          // This request now includes the active trace context.
          const { data, error } = await supabase.from('users').select('*')
          span.end()
        })
        ```
        
        The subpath imports `@opentelemetry/api` directly, so module resolution fails loudly if it is not installed. If `tracePropagation` is enabled without the subpath import, the SDK logs a one-time warning and sends requests without trace headers; if no active context exists at request time, it silently no-ops.
        
        Trace propagation is not available via the CDN/UMD build (`https://cdn.jsdelivr.net/.../supabase.js`) — there is no way to load the tracing runtime there.
        
        #### Advanced configuration
        
        ```typescript
        interface TracePropagationOptions {
          // Enable trace propagation (default: false).
          enabled?: boolean
        
          // Respect upstream sampling decisions (default: true).
          // When true, non-sampled requests carry only `traceparent` (flag preserved,
          // so nothing is recorded downstream) — Supabase logs still get a trace_id,
          // while `tracestate` and `baggage` are withheld.
          respectSamplingDecision?: boolean
        }
        ```
        
        ```js
        // Always propagate the full trace context, even for non-sampled traces.
        const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {
          tracePropagation: { enabled: true, respectSamplingDecision: false },
        })
        ```
        
        ## Support Policy
        
        This section outlines the scope of support for various runtime environments in Supabase JavaScript client.
        
        ### Node.js
        
        We only support Node.js versions that are in **Active LTS** or **Maintenance** status as defined by the [official Node.js release schedule](https://nodejs.org/en/about/previous-releases#release-schedule). This means we support versions that are currently receiving long-term support and critical bug fixes.
        
        When a Node.js version reaches end-of-life and is no longer in Active LTS or Maintenance status, Supabase will drop it in a **minor release**, and **this won't be considered a breaking change**.
        
        > ⚠️ **Node.js 18 Deprecation Notice**
        >
        > Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped in version `2.79.0`.
        >
        > If you must use Node.js 18, please use version `2.78.0`, which is the last version that supported Node.js 18.
        
        > ⚠️ **Node.js 20 Deprecation Notice**
        >
        > Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in version `2.110.0`.
        >
        > If you must use Node.js 20, please use version `2.109.0`, which is the last version that supported Node.js 20.
        
        ### Deno
        
        We support Deno versions that are currently receiving active development and security updates. We follow the [official Deno release schedule](https://docs.deno.com/runtime/fundamentals/stability_and_releases/) and only support versions from the `stable` and `lts` release channels.
        
        When a Deno version reaches end-of-life and is no longer receiving security updates, Supabase will drop it in a **minor release**, and **this won't be considered a breaking change**.
        
        ### Browsers
        
        All modern browsers are supported. We support browsers that provide native `fetch` API. For Realtime features, browsers must also support native `WebSocket` API.
        
        ### Bun
        
        We support Bun runtime environments. Bun provides native fetch support and is compatible with Node.js APIs. Since Bun does not follow a structured release schedule like Node.js or Deno, we support current stable versions of Bun and may drop support for older versions in minor releases without considering it a breaking change.
        
        ### React Native
        
        We support React Native environments with fetch polyfills provided by the framework. Since React Native does not follow a structured release schedule, we support current stable versions and may drop support for older versions in minor releases without considering it a breaking change.
        
        ### Cloudflare Workers
        
        We support Cloudflare Workers runtime environments. Cloudflare Workers provides native fetch support. Since Cloudflare Workers does not follow a structured release schedule, we support current stable versions and may drop support for older versions in minor releases without considering it a breaking change.
        
        ### Important Notes
        
        - **Experimental features**: Features marked as experimental may be removed or changed without notice
        
        ## Known Build Warnings
        
        ### `UNUSED_EXTERNAL_IMPORT` in Vite / Rollup / Nuxt
        
        When bundling your app, you may see warnings like:
        
        ```
        "PostgrestError" is imported from external module "@supabase/postgrest-js" but never used in "...supabase-js/dist/index.mjs".
        "FunctionRegion", "FunctionsError", "FunctionsFetchError", "FunctionsHttpError" and "FunctionsRelayError" are imported from external module "@supabase/functions-js" but never used in "...".
        ```
        
        **This is a false positive — your bundle is fine.** Here is why it happens:
        
        `@supabase/supabase-js` re-exports `PostgrestError`, `FunctionsError`, and related symbols so you can import them directly from `@supabase/supabase-js`. However, our build tool merges all imports from the same package into a single import statement in the built output:
        
        ```js
        // dist/index.mjs (simplified)
        import { PostgrestClient, PostgrestError } from '@supabase/postgrest-js'
        //       ^ used internally    ^ re-exported for you
        ```
        
        Your bundler checks which names from that import are used _in the code body_, and flags `PostgrestError` as unused because it only appears in an `export` statement — not called or assigned. The export itself is the usage, but downstream bundlers don't track this correctly. This is a known Rollup/Vite limitation with re-exported external imports.
        
        **Nothing is broken.** Tree-shaking and bundle size are unaffected.
        
        To suppress the warning:
        
        **Vite / Rollup (`vite.config.js` or `rollup.config.js`):**
        
        ```js
        export default {
          build: {
            rollupOptions: {
              onwarn(warning, warn) {
                if (warning.code === 'UNUSED_EXTERNAL_IMPORT' && warning.exporter?.includes('@supabase/'))
                  return
                warn(warning)
              },
            },
          },
        }
        ```
        
        **Nuxt (`nuxt.config.ts`):**
        
        ```ts
        export default defineNuxtConfig({
          vite: {
            build: {
              rollupOptions: {
                onwarn(warning, warn) {
                  if (warning.code === 'UNUSED_EXTERNAL_IMPORT' && warning.exporter?.includes('@supabase/'))
                    return
                  warn(warning)
                },
              },
            },
          },
        })
        ```
        
        ## Contributing
        
        We welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.
        
        For major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.
        
        ### Building
        
        ```bash
        # From the monorepo root
        pnpm nx build supabase-js
        
        # Or with watch mode for development
        pnpm nx build supabase-js --watch
        ```
        
        ### Testing
        
        There's a complete guide on how to set up your environment for running locally the `supabase-js` integration tests. Please refer to [TESTING.md](./TESTING.md).
        
        ## Badges
        
        [![Coverage Status](https://coveralls.io/repos/github/supabase/supabase-js/badge.svg?branch=master)](https://coveralls.io/github/supabase/supabase-js?branch=master)
        
    • overview.md 9.2 KB
      <br />
      <p align="center">
        <a href="https://supabase.io">
              <picture>
            <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg">
            <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg">
            <img alt="Supabase Logo" width="300" src="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg">
          </picture>
        </a>
      
        <h1 align="center">Supabase JS SDK</h1>
      
        <p align="center">
          <a href="https://supabase.com/docs/guides/getting-started">Guides</a>
          ·
          <a href="https://supabase.com/docs/reference/javascript/introduction">Reference Docs</a>
        </p>
      </p>
      
      <div align="center">
      
      [![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)
      [![Package](https://img.shields.io/npm/v/@supabase/supabase-js)](https://www.npmjs.com/package/@supabase/postgrest-js)
      [![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)
      [![pkg.pr.new](https://pkg.pr.new/badge/supabase/supabase-js)](https://pkg.pr.new/~/supabase/supabase-js)
      
      </div>
      
      ## 📦 Libraries
      
      This monorepo contains the complete suite of Supabase JavaScript SDK:
      
      | Library                                                    | Description                           |
      | ---------------------------------------------------------- | ------------------------------------- |
      | **[@supabase/supabase-js](./packages/core/supabase-js)**   | Main isomorphic SDK for Supabase      |
      | **[@supabase/auth-js](./packages/core/auth-js)**           | Authentication SDK                    |
      | **[@supabase/postgrest-js](./packages/core/postgrest-js)** | PostgREST SDK for database operations |
      | **[@supabase/realtime-js](./packages/core/realtime-js)**   | Real-time subscriptions SDK           |
      | **[@supabase/storage-js](./packages/core/storage-js)**     | File storage SDK                      |
      | **[@supabase/functions-js](./packages/core/functions-js)** | Edge Functions SDK                    |
      
      ## Support Policy
      
      This section outlines the scope of support for various runtime environments in Supabase JavaScript client.
      
      ### Node.js
      
      We only support Node.js versions that are in **Active LTS** or **Maintenance** status as defined by the [official Node.js release schedule](https://nodejs.org/en/about/previous-releases#release-schedule). This means we support versions that are currently receiving long-term support and critical bug fixes.
      
      When a Node.js version reaches end-of-life and is no longer in Active LTS or Maintenance status, Supabase will drop it in a **minor release**, and **this won't be considered a breaking change**.
      
      > ⚠️ **Node.js 18 Deprecation Notice**
      >
      > Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped in version `2.79.0`.
      >
      > If you must use Node.js 18, please use version `2.78.0`, which is the last version that supported Node.js 18.
      
      > ⚠️ **Node.js 20 Deprecation Notice**
      >
      > Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in version `2.110.0`.
      >
      > If you must use Node.js 20, please use version `2.109.0`, which is the last version that supported Node.js 20.
      
      ### Deno
      
      We support Deno versions that are currently receiving active development and security updates. We follow the [official Deno release schedule](https://docs.deno.com/runtime/fundamentals/stability_and_releases/) and only support versions from the `stable` and `lts` release channels.
      
      When a Deno version reaches end-of-life and is no longer receiving security updates, Supabase will drop it in a **minor release**, and **this won't be considered a breaking change**.
      
      ### Browsers
      
      All modern browsers are supported. We support browsers that provide native `fetch` API. For Realtime features, browsers must also support native `WebSocket` API.
      
      ### Bun
      
      We support Bun runtime environments. Bun provides native fetch support and is compatible with Node.js APIs. Since Bun does not follow a structured release schedule like Node.js or Deno, we support current stable versions of Bun and may drop support for older versions in minor releases without considering it a breaking change.
      
      ### React Native
      
      We support React Native environments with fetch polyfills provided by the framework. Since React Native does not follow a structured release schedule, we support current stable versions and may drop support for older versions in minor releases without considering it a breaking change.
      
      ### Cloudflare Workers
      
      We support Cloudflare Workers runtime environments. Cloudflare Workers provides native fetch support. Since Cloudflare Workers does not follow a structured release schedule, we support current stable versions and may drop support for older versions in minor releases without considering it a breaking change.
      
      ### Important Notes
      
      - **Experimental features**: Features marked as experimental may be removed or changed without notice
      - **Build warnings**: If you see `UNUSED_EXTERNAL_IMPORT` warnings from Vite/Nuxt, see the [supabase-js README](./packages/core/supabase-js/README.md#known-build-warnings) — these are false positives
      
      ## 🚀 Quick Start
      
      ### Installation
      
      ```bash
      npm install @supabase/supabase-js
      ```
      
      Read more in each package's README file.
      
      ## 🤝 Contributing
      
      We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) for details.
      
      ### Quick Contribution Steps
      
      1. **Fork the repository**
      2. **Create a feature branch** (`git checkout -b feature/amazing-feature`)
      3. **Make your changes** and add tests
      4. **Run tests** (`pnpm nx affected --target=test`)
      5. **Commit your changes** (`pnpm commit`)
      6. **Push to your branch** (`git push origin feature/amazing-feature`)
      7. **Open a Pull Request**
      
      ### Development Guidelines
      
      - Follow [conventional commits](https://www.conventionalcommits.org/) for commit messages
      - Add tests for new functionality
      - Update documentation for API changes
      - Run `pnpm nx format` before committing
      - Ensure all tests pass with `pnpm nx affected --target=test`
      
      ## 🧪 Testing
      
      Testing varies per package. See the top-level [TESTING.md](docs/TESTING.md) for an overview and links to package-specific guides.
      
      ## 📚 Documentation
      
      ### API Documentation
      
      - **[Auth SDK](./packages/core/auth-js/README.md)** - Authentication and user management
      - **[Database SDK](./packages/core/postgrest-js/README.md)** - Database queries and operations
      - **[Realtime SDK](./packages/core/realtime-js/README.md)** - Real-time subscriptions
      - **[Storage SDK](./packages/core/storage-js/README.md)** - File upload and management
      - **[Functions SDK](./packages/core/functions-js/README.md)** - Edge Functions invocation
      - **[Main SDK](./packages/core/supabase-js/README.md)** - Combined SDK
      
      ### Architecture Documentation
      
      - **[Contributing](./CONTRIBUTING.md)** - Development guidelines
      - **[Release Workflows](./docs/RELEASE.md)** - Release and publishing process
      - **[Migration Guide](./docs/MIGRATION.md)** - Cross-cutting migration notes (per-package migrations live alongside each package under `packages/core/<package>/migrations/`)
      - **[Security Policy](https://github.com/supabase/supabase-js/security/policy)** - Vulnerability reporting and disclosure policy
      - **[Securing your npm installs](https://supabase.com/docs/guides/security/npm-security)** - Consumer-side guide to defending your install against npm supply-chain attacks
      
      ## 🔐 Verifying provenance attestations
      
      You can verify registry signatures and provenance attestations for installed packages using the npm CLI:
      
      ```bash
      npm audit signatures
      ```
      
      Quick example for a single package install:
      
      ```bash
      npm install @supabase/auth-js
      npm audit signatures
      ```
      
      Example output:
      
      ```text
      audited 1 package in 0s
      
      1 package has a verified registry signature
      ```
      
      Because provenance attestations are a new capability, security features may evolve over time. Ensure you are using the latest npm CLI to verify attestation signatures reliably. This may require updating npm beyond the version bundled with Node.js.
      
      For a broader checklist — minimum release age, lockfile hygiene, blocking exotic transitive deps, lifecycle script controls, and what to do if you suspect a compromise — see [Securing your npm installs](https://supabase.com/docs/guides/security/npm-security).
      
      ## 📄 License
      
      This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
      
      ## 🆘 Support
      
      - **Documentation**: [supabase.com/docs](https://supabase.com/docs)
      - **Community**: [GitHub Discussions](https://github.com/supabase/supabase/discussions)
      - **Issues**: [GitHub Issues](https://github.com/supabase/supabase-js/issues)
      - **Discord**: [Supabase Discord](https://discord.supabase.com)
      
      ---
      
      <div align="center">
      
      **[Website](https://supabase.com) • [Documentation](https://supabase.com/docs) • [Community](https://github.com/supabase/supabase/discussions) • [Twitter](https://twitter.com/supabase)**
      
      </div>
      
  • SKILL.md 6.3 KB
    ---
    name: supabase-js
    description: This skill should be used when user asks to "use supabase-js", "query Supabase database", "supabase auth", "supabase storage", "supabase realtime", "supabase edge functions", or works with the @supabase/supabase-js JavaScript/TypeScript SDK.
    references:
      - supabase-js
      - auth-js
      - postgrest-js
      - storage-js
    license: MIT
    ---
    
    # Supabase JavaScript SDK Skill
    
    Skill for building applications with the `@supabase/supabase-js` SDK. Covers Auth, Database (PostgREST), Storage, Realtime, and Edge Functions.
    
    The SDK docs at https://supabase.com/docs/reference/javascript are the source of truth. The reference files alongside this skill contain source code and READMEs extracted from the monorepo for quick lookup.
    
    ## Setup
    
    ```bash
    npm install @supabase/supabase-js
    ```
    
    ```typescript
    import { createClient } from '@supabase/supabase-js'
    
    const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key')
    ```
    
    For type-safe queries, generate types from your database schema:
    
    ```bash
    supabase gen types typescript --project-id your-project-id > database.types.ts
    ```
    
    ```typescript
    import { createClient } from '@supabase/supabase-js'
    import type { Database } from './database.types'
    
    const supabase = createClient<Database>(SUPABASE_URL, SUPABASE_ANON_KEY)
    ```
    
    ## Quick Decision Trees
    
    ### "I need to query data"
    
    ```
    Database query?
    ├─ Select rows → supabase.from('table').select('*')
    ├─ Filter rows → .select().eq('col', val) / .gt() / .lt() / .in() / .like()
    ├─ Join tables → .select('*, other_table(*)') or .select('*, other_table!fk(*)')
    ├─ Insert → supabase.from('table').insert({ col: val })
    ├─ Upsert → supabase.from('table').upsert({ id: 1, col: val })
    ├─ Update → supabase.from('table').update({ col: val }).eq('id', 1)
    ├─ Delete → supabase.from('table').delete().eq('id', 1)
    ├─ Call RPC function → supabase.rpc('function_name', { arg: val })
    ├─ Count rows → .select('*', { count: 'exact', head: true })
    ├─ Pagination → .range(0, 9) or .limit(10).offset(20)
    └─ Order → .order('created_at', { ascending: false })
    ```
    
    ### "I need authentication"
    
    ```
    Auth?
    ├─ Email/password sign up → supabase.auth.signUp({ email, password })
    ├─ Email/password sign in → supabase.auth.signInWithPassword({ email, password })
    ├─ OAuth (Google, GitHub, etc.) → supabase.auth.signInWithOAuth({ provider: 'google' })
    ├─ Magic link → supabase.auth.signInWithOtp({ email })
    ├─ Phone OTP → supabase.auth.signInWithOtp({ phone })
    ├─ Sign out → supabase.auth.signOut()
    ├─ Get current user → supabase.auth.getUser()
    ├─ Get session → supabase.auth.getSession()
    ├─ Listen to auth changes → supabase.auth.onAuthStateChange((event, session) => {})
    ├─ Reset password → supabase.auth.resetPasswordForEmail(email)
    ├─ Update user → supabase.auth.updateUser({ data: { name: 'New' } })
    └─ Admin operations → supabase.auth.admin.listUsers() / .deleteUser(id)
    ```
    
    ### "I need file storage"
    
    ```
    Storage?
    ├─ Upload file → supabase.storage.from('bucket').upload('path/file.png', file)
    ├─ Download file → supabase.storage.from('bucket').download('path/file.png')
    ├─ Get public URL → supabase.storage.from('bucket').getPublicUrl('path/file.png')
    ├─ Create signed URL → supabase.storage.from('bucket').createSignedUrl('path', 3600)
    ├─ List files → supabase.storage.from('bucket').list('folder')
    ├─ Move file → supabase.storage.from('bucket').move('old/path', 'new/path')
    ├─ Remove file → supabase.storage.from('bucket').remove(['path/file.png'])
    ├─ Create bucket → supabase.storage.createBucket('name', { public: false })
    └─ List buckets → supabase.storage.listBuckets()
    ```
    
    ### "I need realtime"
    
    ```
    Realtime?
    ├─ Listen to DB changes → supabase.channel('name')
    │    .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'messages' }, handler)
    │    .subscribe()
    ├─ Broadcast messages → channel.send({ type: 'broadcast', event: 'cursor', payload: { x, y } })
    ├─ Listen to broadcasts → .on('broadcast', { event: 'cursor' }, handler)
    ├─ Presence (who's online) → channel.track({ user_id, online_at })
    │    .on('presence', { event: 'sync' }, () => channel.presenceState())
    ├─ Unsubscribe → supabase.removeChannel(channel)
    └─ Unsubscribe all → supabase.removeAllChannels()
    ```
    
    ### "I need edge functions"
    
    ```
    Edge Functions?
    ├─ Invoke function → supabase.functions.invoke('function-name', { body: { key: 'val' } })
    ├─ With custom headers → .invoke('fn', { headers: { 'x-custom': 'val' }, body })
    └─ Set region → .invoke('fn', { body, region: 'us-east-1' })
    ```
    
    ## Common Patterns
    
    ### Server-side with service role key
    
    ```typescript
    // Server-side only - bypasses RLS
    const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, {
      auth: { persistSession: false }
    })
    ```
    
    ### React/Next.js auth
    
    ```typescript
    import { createClient } from '@supabase/supabase-js'
    import { useEffect, useState } from 'react'
    
    const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)
    
    function useUser() {
      const [user, setUser] = useState(null)
      useEffect(() => {
        supabase.auth.getUser().then(({ data }) => setUser(data.user))
        const { data: { subscription } } = supabase.auth.onAuthStateChange(
          (_, session) => setUser(session?.user ?? null)
        )
        return () => subscription.unsubscribe()
      }, [])
      return user
    }
    ```
    
    ### Typed database queries
    
    ```typescript
    // Generated types give autocomplete for table names, column names, and return types
    const { data, error } = await supabase
      .from('profiles')        // autocompleted table name
      .select('id, username')  // autocompleted columns
      .eq('id', userId)        // type-safe filter
      .single()                // returns single row or error
    // data is typed as { id: string; username: string } | null
    ```
    
    ## Package Index
    
    | Package | Sub-client | Reference |
    |---------|-----------|-----------|
    | `@supabase/supabase-js` | `createClient()` | `references/supabase-js/` |
    | `@supabase/auth-js` | `.auth` | `references/auth-js/` |
    | `@supabase/postgrest-js` | `.from()`, `.rpc()` | `references/postgrest-js/` |
    | `@supabase/realtime-js` | `.channel()`, `.realtime` | `references/realtime-js/` |
    | `@supabase/storage-js` | `.storage` | `references/storage-js/` |
    | `@supabase/functions-js` | `.functions` | `references/functions-js/` |
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related