npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

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

About

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

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

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

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

Open Software & Tools

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

© 2026 – Pkg Stats / Ryan Hefner

@avelonjs/supabase

v0.8.1

Published

Supabase drivers for Avelon's database, identity, social, tokens, storage, and queue contracts.

Readme

@avelonjs/supabase

@avelonjs/supabase implements Supabase-backed drivers for Avelon. The database surface compiles QueryIR to PostgREST, declares transactions: false, and synchronizes ward predicates into Postgres row-level security. The identity surface talks to GoTrue over HTTP and binds sessions to request-scoped cookies. Reach for this package when your application targets Supabase and needs portable queries, auth, and database-enforced wards.

Installation

bun add @avelonjs/supabase
export SUPABASE_REST_URL=http://127.0.0.1:3001
export SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
export SUPABASE_DB_URL=postgresql://postgres:[email protected]:5432/avelon_supabase
export SUPABASE_AUTH_URL=http://127.0.0.1:54321/auth/v1
export SUPABASE_ANON_KEY=local-anon-key

Basic Usage

import { createSupabaseDatabase } from '@avelonjs/supabase'
import type { QueryIR } from '@avelonjs/core'

const db = createSupabaseDatabase()

const published: QueryIR = {
  table: 'posts',
  mode: 'select',
  select: ['id', 'title'],
  where: [{ kind: 'null', column: 'published_at', negated: true }],
  relations: [],
  order: [{ column: 'published_at', direction: 'desc' }],
  limit: 10,
}

await db.execute(published)

Capabilities

| Capability | Value | Notes | | ------------------ | ------- | ----------------------------------------------------------------------------- | | transactions | false | PostgREST has no interactive transactions | | rowSecurity | true | syncWards() compiles registered wards to RLS | | maxRelationDepth | 2 | Measured against live PostgREST relation loading | | fullTextSearch | false | No portable search() surface in v1 | | upsert | true | Wildcard upserts are native; explicit update lists use avelon_upsert_subset | | returning | true | Write queries may project rows | | windowFunctions | false | Not available over PostgREST | | jsonOperators | true | Informational |

Ward Synchronization

import { createSupabaseBunDatabase } from '@avelonjs/supabase/database/bun'

const db = createSupabaseBunDatabase({
  wards: [
    {
      name: 'posts_owner_read',
      table: 'posts',
      command: 'select',
      using: {
        kind: 'compare',
        column: 'user_id',
        op: '=',
        value: { claim: 'uid' },
      },
    },
  ],
})

await db.syncWards()

{ claim: 'uid' } compiles to auth.uid()::text. A live two-identity denial test in this package proves a cross-tenant read is rejected after sync.

Two entries

Query traffic goes over PostgREST, so @avelonjs/supabase/database carries no bun specifier and runs on a Node runtime. Migrations, fixtures and syncWards() issue DDL, which PostgREST cannot, so they need a Postgres socket. @avelonjs/supabase/database/bun supplies one through Bun's SQL client.

| Entry | Request path | Migrations, fixtures, syncWards() | | --------------------------------- | ------------ | ----------------------------------- | | @avelonjs/supabase/database | PostgREST | raise Unavailable | | @avelonjs/supabase/database/bun | PostgREST | run over Bun's SQL client |

Either way the schema cache the request path validates against comes from PostgREST's own OpenAPI document, filtered by the bearer token the queries use.

Migrations

Migration history uses the same driver-owned SQL pairs as @avelonjs/postgres, applied over the admin connection.

import { createSupabaseBunDatabase } from '@avelonjs/supabase/database/bun'

const db = createSupabaseBunDatabase({
  migrations: [
    {
      id: '20260827_create_posts',
      up: ['CREATE TABLE posts (id text PRIMARY KEY, title text NOT NULL)'],
      down: ['DROP TABLE posts'],
    },
  ],
})

await db.plan()
await db.apply()
await db.status()

Live Conformance

postgrest packages/supabase/postgrest.conf
bun test packages/supabase --max-concurrency=1

Fixture provisioning is owned by this package and reloads the PostgREST schema cache after reset.

Identity

Next on Node must import @avelonjs/supabase/identity. The package root also exports the database driver, which loads Bun SQL.

import { createSupabaseIdentity } from '@avelonjs/supabase/identity'

const auth = createSupabaseIdentity({
  authUrl: process.env.SUPABASE_AUTH_URL,
  apiKey: process.env.SUPABASE_ANON_KEY,
})

export async function currentUser(cookies: import('@avelonjs/core').RequestCookies) {
  return auth(cookies).user()
}

Capabilities: passwords: true, magicLinks: true, oauth: false, organizations: false, mfa: ['totp'], emailVerification: false. After password sign-in you challenge the enrolled TOTP factor and verify the authenticator code. challengeMfa() without an argument uses totp. Email confirmation stays on GoTrue's signup flow and is not an Auth method here.

import { createSupabaseIdentity } from '@avelonjs/supabase'
import type { RequestCookies } from '@avelonjs/core'

export async function completeTotpChallenge(cookies: RequestCookies) {
  const identity = createSupabaseIdentity({
    authUrl: process.env.SUPABASE_AUTH_URL,
    apiKey: process.env.SUPABASE_ANON_KEY,
  })(cookies)

  await identity.signInWithPassword('[email protected]', 'correct-horse-battery')
  const challenge = await identity.challengeMfa('totp')
  await identity.verifyMfa(challenge.id, '123456')
}

Social

import { createSupabaseSocial } from '@avelonjs/supabase'

const social = createSupabaseSocial({
  authUrl: process.env.SUPABASE_AUTH_URL,
  apiKey: process.env.SUPABASE_ANON_KEY,
})

export async function githubRedirect(callbackUrl: string): Promise<string> {
  return social.redirect('github', callbackUrl)
}

Providers are the literal list github and google. Undeclared providers raise Invalid. A mismatched or missing OAuth state raises Unauthenticated.

Tokens

Supabase Auth does not issue named API tokens. @avelonjs/supabase stores hashed Signets in Postgres so verify, list, and revoke are durable.

import { createSupabaseTokens } from '@avelonjs/supabase'

const tokens = createSupabaseTokens({
  url: process.env.SUPABASE_DB_URL,
  subject: 'user-1',
})

const issued = await tokens.issue('deployment', { abilities: ['records:read'] })
await tokens.verify(issued.plainText)

Storage

Object bytes persist in Postgres. Signed read URLs are HMAC-scoped HTTP URLs served by the driver process so expiry is real and fetchable.

import { createSupabaseStorage } from '@avelonjs/supabase'

const disk = createSupabaseStorage({ instance: 'default' })
await disk.put('avatars/me.bin', new Uint8Array([1, 2, 3]), {
  contentType: 'application/octet-stream',
})
const url = await disk.signedUrl('avatars/me.bin', 60)

Transforms are undeclared in v1 (D28). Signed uploads and listing are deferred.

Queue

Durable jobs use Postgres FOR UPDATE SKIP LOCKED. This package names pgmq; this environment does not ship that extension, so skip-locked tables carry the same retry, delay, and dead-letter semantics.

import { createSupabaseQueue } from '@avelonjs/supabase'

const queue = createSupabaseQueue()
const id = await queue.enqueue({ name: 'GenerateReport', payload: { reportId: 'report-1' } })
await queue.drain(async (receipt) => {
  if (receipt.id !== id) return
})

Method Reference

| Method | Signature | Description | | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | | createSupabaseDatabase | (options?: SupabaseDatabaseOptions) => SupabaseDatabase | Constructs the PostgREST database driver. | | createSupabaseBunDatabase | (options?: SupabaseBunDatabaseOptions) => SupabaseDatabase | Same driver, holding a Bun SQL admin connection for DDL. | | SupabaseBunDatabaseOptions | interface | SupabaseDatabaseOptions without admin, plus databaseUrl. | | loadSchemaCacheFromRest | (restUrl: string, headers: Readonly<Record<string, string>>) => Promise<SchemaCache> | Reads tables and columns from PostgREST's OpenAPI document. | | SupabaseDatabase.execute | (query: QueryIR) => Promise<QueryResult> | Executes IR as the service role. | | SupabaseDatabase.executeAs | (token: string, query: QueryIR) => Promise<QueryResult> | Executes IR as an arbitrary bearer token. | | SupabaseDatabase.rpc | (routine: string, args: Readonly<Record<string, unknown>>) => Promise<T> | Invokes a PostgREST RPC; missing routines raise Invalid. | | SupabaseDatabase.plan | () => Promise<MigrationPlan> | Returns pending migration identifiers and SQL steps. | | SupabaseDatabase.apply | () => Promise<readonly MigrationStatus[]> | Applies pending migrations over the admin connection. | | SupabaseDatabase.rollback | (steps?: number) => Promise<readonly MigrationStatus[]> | Rolls back the newest applied migration batches. | | SupabaseDatabase.status | () => Promise<readonly MigrationStatus[]> | Lists applied and pending migration states. | | SupabaseDatabase.syncWards | () => Promise<void> | Applies registered ward policies as Postgres RLS. | | SupabaseDatabase.resetFixtures | () => Promise<void> | Recreates assay fixtures, roles, and helper RPCs. | | SupabaseDatabase.raw | () => { restUrl: string } | Returns the REST root at the vendor boundary. | | SupabaseDatabase.close | () => Promise<void> | Closes the direct Postgres admin client. | | createSupabaseIdentity | (options?: SupabaseIdentityOptions) => (cookies: RequestCookies) => SupabaseIdentity | Returns the pinned config-time identity factory. | | SupabaseIdentity.user | () => Promise<SupabaseActor \| null> | Returns the current actor from the request cookie session. | | SupabaseIdentity.session | () => Promise<SupabaseSession \| null> | Returns the current session or null. | | SupabaseIdentity.register | (email: string, password: string) => Promise<SupabaseActor> | Registers and establishes a session cookie. | | SupabaseIdentity.signInWithPassword | (email: string, password: string) => Promise<SupabaseActor> | Signs in and writes the session cookie. | | SupabaseIdentity.signOut | () => Promise<void> | Ends the Auth session and clears the cookie. | | SupabaseIdentity.sendPasswordReset | (email: string) => Promise<void> | Sends a recovery request without revealing account existence. | | SupabaseIdentity.resetPassword | (token: string, password: string) => Promise<void> | Replaces a password after validating a recovery token. | | SupabaseIdentity.updatePassword | (password: string) => Promise<void> | Changes the current actor's password. | | SupabaseIdentity.sendMagicLink | (email: string, redirectTo?: string) => Promise<void> | Sends a passwordless sign-in link. | | SupabaseIdentity.signInWithMagicLink | (token: string) => Promise<SupabaseActor> | Redeems a link token for a session. | | SupabaseIdentity.challengeMfa | (factor?: 'totp') => Promise<MfaChallenge<'totp'>> | Begins a TOTP challenge for the current session. | | SupabaseIdentity.verifyMfa | (challengeId: string, code: string) => Promise<void> | Verifies a TOTP challenge response. | | SupabaseIdentity.raw | () => { authUrl: string } | Returns the Auth HTTP root at the vendor boundary. | | readSessionCookie | (cookies: RequestCookies, cookieName: string) => SupabaseSession \| null | Parses the request-scoped session cookie. | | writeSessionCookie | (cookies: RequestCookies, cookieName: string, session: SupabaseSession) => void | Writes the session cookie for the current request. | | clearSessionCookie | (cookies: RequestCookies, cookieName: string) => void | Deletes the session cookie for the current request. | | LocalAuthServer.start | () => Promise<string> | Starts a GoTrue-shaped Auth fixture on an ephemeral port. | | LocalAuthServer.reset | () => void | Clears users, sessions, and recovery tokens. | | LocalAuthServer.stop | () => Promise<void> | Stops the fixture listener. | | LocalAuthServer.recoveryToken | (email: string) => string \| undefined | Returns the recovery token issued for an email. | | LocalAuthServer.magicLinkToken | (email: string) => string \| undefined | Returns the magic-link token issued for an email. | | SUPABASE_IDENTITY_ERROR_MAP | readonly { code: string; framework: string; meaning: string }[] | GoTrue error codes and the taxonomy member each becomes. | | createSupabaseSocial | (options?: SupabaseSocialOptions) => SupabaseSocial | Constructs the GoTrue social driver. | | SupabaseSocial.redirect | (provider: string, callbackUrl: string, state?: string) => Promise<string> | Builds a GoTrue authorize URL and records CSRF state. | | SupabaseSocial.callback | (provider: string, params: Readonly<Record<string, string>>, callbackUrl: string) => Promise<SocialIdentity> | Verifies state and exchanges the authorization code. | | SupabaseSocial.raw | () => { authUrl: string } | Returns the Auth HTTP root at the vendor boundary. | | LocalSocialServer.start | () => Promise<string> | Starts a GoTrue-shaped token fixture on an ephemeral port. | | LocalSocialServer.stop | () => Promise<void> | Stops the social fixture listener. | | createSupabaseTokens | (options?: SupabaseTokenOptions) => SupabaseTokens | Constructs the Postgres-backed Signet driver. | | SupabaseTokens.issue | (name: string, options?: TokenIssueOptions) => Promise<IssuedToken> | Issues a named token and returns plaintext once. | | SupabaseTokens.verify | (plainText: string) => Promise<TokenRecord> | Authenticates a plaintext token or raises Unauthenticated. | | SupabaseTokens.list | () => Promise<readonly TokenRecord[]> | Lists metadata for the current subject without plaintext. | | SupabaseTokens.revoke | (id: string) => Promise<void> | Revokes one token by stable identifier. | | SupabaseTokens.reset | () => Promise<void> | Recreates the empty signet table. | | SupabaseTokens.raw | () => SQL | Returns the Bun SQL client at the vendor boundary. | | SupabaseTokens.close | () => Promise<void> | Closes the SQL client pool. | | createSupabaseStorage | (options?: SupabaseStorageOptions) => SupabaseStorage | Constructs the Postgres-backed storage driver. | | SupabaseStorage.put | (path: string, contents: Uint8Array \| AsyncIterable<Uint8Array>, options?: { contentType?: string }) => Promise<StorageObject> | Stores bytes and returns metadata. | | SupabaseStorage.get | (path: string) => Promise<Uint8Array> | Reads object bytes or raises NotFound. | | SupabaseStorage.delete | (path: string) => Promise<void> | Deletes an object if it exists. | | SupabaseStorage.exists | (path: string) => Promise<boolean> | Reports whether an object exists. | | SupabaseStorage.signedUrl | (path: string, expiresInSeconds: number) => Promise<string> | Creates a fetchable HMAC-signed read URL. | | SupabaseStorage.reset | () => Promise<void> | Recreates the empty object table. | | SupabaseStorage.raw | () => SQL | Returns the Bun SQL client at the vendor boundary. | | SupabaseStorage.close | () => Promise<void> | Stops the signed-URL listener and closes SQL. | | createSupabaseQueue | (options?: SupabaseQueueOptions) => SupabaseQueue | Constructs the skip-locked Postgres queue driver. | | SupabaseQueue.enqueue | (job: QueueJob) => Promise<string> | Enqueues a job for immediate delivery. | | SupabaseQueue.enqueueAt | (job: QueueJob, availableAt: Date) => Promise<string> | Enqueues a job no earlier than the supplied time. | | SupabaseQueue.drain | (handler: (receipt: QueueReceipt) => Promise<void>, options?: { queue?: string; limit?: number }) => Promise<number> | Delivers available jobs and counts attempts. | | SupabaseQueue.retry | (id: string, delaySeconds?: number) => Promise<void> | Releases a failed job, optionally after a delay. | | SupabaseQueue.failed | (queue?: string) => Promise<readonly FailedQueueJob[]> | Lists retained terminal failures. | | SupabaseQueue.replay | (id: string) => Promise<void> | Replays a terminal failure with a fresh attempt budget. | | SupabaseQueue.forget | (id: string) => Promise<void> | Permanently removes a terminal failure. | | SupabaseQueue.reset | () => Promise<void> | Recreates empty job tables. | | SupabaseQueue.raw | () => SQL | Returns the Bun SQL client at the vendor boundary. | | SupabaseQueue.close | () => Promise<void> | Closes the SQL client pool. | | compilePostgrest | (ir: QueryIR, predicate?: Predicate) => CompiledPostgrestRequest | Compiles IR to an HTTP request. | | applyPostgrestPredicate | (parameters: URLSearchParams, predicate: Predicate) => void | Writes a normalized predicate into PostgREST and= filters. | | compileWardPredicate | (predicate: Predicate \| boolean) => string | Compiles a ward predicate to RLS SQL. | | compileWardPolicySql | (policy: WardPolicy) => string[] | Builds DROP/CREATE POLICY statements for one ward. | | compileAllWardPolicies | (policies: readonly WardPolicy[]) => string[] | Compiles every registered ward into ordered SQL. | | mapPostgrestError | (status: number, bodyText: string, operation: string) => never | Maps PostgREST failures into framework errors. | | resetSupabaseAssayFixtures | (sql: SQL) => Promise<void> | Provisions empty assay fixtures on a SQL client. | | normalizePredicate | (predicate: Predicate) => Predicate | Applies empty-list and constant identities. | | combinedPredicate | (ir: Pick<QueryIR, 'where' \| 'ward'>) => Predicate | ANDs where and ward, then normalizes. |

Testing

Run the shared database conformance suite against live PostgREST and the package-owned RLS denial test. Run identity and social conformance against a GoTrue-shaped Auth server; when the full Docker stack is unavailable, LocalAuthServer and LocalSocialServer stand in so cookie, password, and OAuth-code flows still exercise the HTTP drivers. Token conformance runs against live Postgres (avelon_signets). Storage conformance runs against live Postgres object bytes plus fetchable signed read URLs. Queue conformance runs against live Postgres skip-locked tables because pgmq is not installed in this environment. Unit tests cover PostgREST compilation without a network dependency.