Skip to content

feat(auth): add Supabase Auth REST client#42

Merged
gentamura merged 3 commits intomainfrom
feat/supabase-auth-client
Nov 11, 2025
Merged

feat(auth): add Supabase Auth REST client#42
gentamura merged 3 commits intomainfrom
feat/supabase-auth-client

Conversation

@gentamura
Copy link
Member

@gentamura gentamura commented Nov 11, 2025

Summary

  • add a REST-friendly Supabase Auth client so runtimes can exchange JWTs without duplicating HTTP plumbing
  • bump @listee/auth and @listee/types to 0.5.0 to publish the new client

Testing

  • bun run lint
  • bun run build

Summary by CodeRabbit

  • New Features

    • Introduced Supabase Auth REST client supporting signup, login, and token refresh
    • Supabase authentication now accepts audience as a single string or an array
  • Documentation

    • Added quick-start guides for JWT verification and calling Supabase Auth REST endpoints
  • Chores

    • Bumped package versions and updated changelogs across related packages

@coderabbitai
Copy link

coderabbitai bot commented Nov 11, 2025

Walkthrough

Adds a Supabase Auth REST client (signup, login, refresh), new SupabaseAuthError, tests, README examples, and broadens audience types/normalization for Supabase JWTs. Also bumps package versions: api@0.3.2, auth@0.5.0, types@0.5.0 with changelog updates.

Changes

Cohort / File(s) Summary
Version & changelogs
packages/api/CHANGELOG.md, packages/api/package.json, packages/auth/CHANGELOG.md, packages/auth/package.json, packages/types/CHANGELOG.md, packages/types/package.json
Package version bumps (api 0.3.2, auth 0.5.0, types 0.5.0) and changelog entries describing the Supabase REST client and audience-array support.
Supabase Auth REST client
packages/auth/src/supabase/auth-client.ts, packages/auth/src/supabase/errors.ts, packages/auth/src/supabase/index.ts
New SupabaseAuthClient implementation with signup, login, refresh; SupabaseAuthError class; re-exports from supabase index.
Tests for auth client
packages/auth/src/supabase/auth-client.test.ts
New test suite covering token normalization, nested payloads, redirect behavior, Supabase error propagation, network failures, and project URL validation.
Audience handling & JWT verification
packages/types/src/authentication.ts, packages/auth/src/authentication/supabase.ts
SupabaseAuthenticationOptions.audience widened to `string
Public exports & docs
packages/auth/src/index.ts, packages/auth/README.md
Re-exports supabase client/types/errors; README updated with Supabase REST client usage, JWT verification quick start, and signup/login/refresh examples.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client as App / Consumer
  participant Lib as SupabaseAuthClient
  participant Fetch as HTTP(fetch)
  rect rgb(220,235,255)
    Client->>Lib: createSupabaseAuthClient(opts)
    Client->>Lib: .signup(email,password, redirect?)
    Lib->>Fetch: POST /auth/v1/signup {email,password,redirect_to}
    Fetch-->>Lib: 200 / error JSON
    alt success
      Lib-->>Client: SupabaseTokenPayload
    else error
      Lib-->>Client: SupabaseAuthError
    end
  end
  rect rgb(235,245,220)
    Client->>Lib: .login(email,password)
    Lib->>Fetch: POST /auth/v1/token {grant_type=password,...}
    Fetch-->>Lib: 200 / error JSON
    Lib-->>Client: token or SupabaseAuthError
  end
  rect rgb(255,240,230)
    Client->>Lib: .refresh(refreshToken)
    Lib->>Fetch: POST /auth/v1/token {grant_type=refresh_token,...}
    Fetch-->>Lib: 200 / error JSON
    Lib-->>Client: token or SupabaseAuthError
  end
  note right of Lib: Token normalization and extractTokenResponse\nhandles nested `data` and multiple payload shapes
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–25 minutes

  • Focus areas:
    • packages/auth/src/supabase/auth-client.ts: request construction, JSON parsing, error mapping, and token-shape detection/conversion.
    • Audience normalization: consistency between packages/types/src/authentication.ts and packages/auth/src/authentication/supabase.ts.
    • Tests: ensure coverage matches implemented error branches and payload shapes.
    • Public exports and README examples: verify exported typings and example correctness.

Possibly related PRs

  • #41 — Direct conflict on audience handling: modifies same audience normalization/type surface in the opposite direction.
  • #39 — Also touches Supabase authentication and audience-type changes; related to normalization and exports.
  • #2 — Overlaps on Supabase auth client and authentication file changes; similar code-level surface.

Suggested labels

codex

Poem

🐰 I hopped a patch down to Supabase lands,
Built signup, login, refresh with careful hands.
Audiences now sing in strings or in arrays,
Tokens tidy, errors wrapped in polite displays.
Version bumps made — a small rabbit dance.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and clearly summarizes the main change: adding a Supabase Auth REST client to the auth package.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/supabase-auth-client

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0956a04 and a6c9ce3.

📒 Files selected for processing (14)
  • packages/api/CHANGELOG.md (1 hunks)
  • packages/api/package.json (1 hunks)
  • packages/auth/CHANGELOG.md (1 hunks)
  • packages/auth/README.md (2 hunks)
  • packages/auth/package.json (1 hunks)
  • packages/auth/src/authentication/supabase.ts (2 hunks)
  • packages/auth/src/index.ts (1 hunks)
  • packages/auth/src/supabase/auth-client.test.ts (1 hunks)
  • packages/auth/src/supabase/auth-client.ts (1 hunks)
  • packages/auth/src/supabase/errors.ts (1 hunks)
  • packages/auth/src/supabase/index.ts (1 hunks)
  • packages/types/CHANGELOG.md (1 hunks)
  • packages/types/package.json (1 hunks)
  • packages/types/src/authentication.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
packages/*/package.json

📄 CodeRabbit inference engine (AGENTS.md)

Reference shared dependencies via the "catalog:" protocol in package manifests

Files:

  • packages/auth/package.json
  • packages/types/package.json
  • packages/api/package.json
packages/*/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

packages/*/src/**/*.{ts,tsx}: Avoid implicit any; TypeScript is run with strict enabled
Prefer type guards or the satisfies operator over as casts where appropriate
Prefer unknown for external inputs
Use PascalCase for types and enums
Use camelCase for variables and functions
Ensure source comments are written in English

Files:

  • packages/auth/src/authentication/supabase.ts
  • packages/auth/src/supabase/errors.ts
  • packages/auth/src/supabase/auth-client.ts
  • packages/auth/src/index.ts
  • packages/types/src/authentication.ts
  • packages/auth/src/supabase/auth-client.test.ts
  • packages/auth/src/supabase/index.ts
packages/auth/src/authentication/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Place runtime-specific authentication adapters under packages/auth/src/authentication/ (e.g., header.ts, supabase.ts, shared utilities, errors.ts)

Files:

  • packages/auth/src/authentication/supabase.ts
packages/auth/src/authentication/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Extend Supabase JWT verification (createSupabaseAuthentication using .well-known/jwks.json) only via dedicated modules to keep caching and claim validation centralized

Files:

  • packages/auth/src/authentication/supabase.ts
packages/*/src/**/{*.test.ts,__tests__/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

packages/*/src/**/{*.test.ts,__tests__/**/*.ts}: Write test names and descriptions in English
Co-locate tests as *.test.ts or under tests/ using Bun’s test runner

Files:

  • packages/auth/src/supabase/auth-client.test.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.ts : Extend Supabase JWT verification (createSupabaseAuthentication using .well-known/jwks.json) only via dedicated modules to keep caching and claim validation centralized
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.{ts,tsx} : Place runtime-specific authentication adapters under packages/auth/src/authentication/ (e.g., header.ts, supabase.ts, shared utilities, errors.ts)
📚 Learning: 2025-10-02T12:40:33.718Z
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.ts : Extend Supabase JWT verification (createSupabaseAuthentication using .well-known/jwks.json) only via dedicated modules to keep caching and claim validation centralized

Applied to files:

  • packages/auth/src/authentication/supabase.ts
  • packages/auth/src/supabase/errors.ts
  • packages/auth/src/supabase/auth-client.ts
  • packages/auth/src/index.ts
  • packages/types/src/authentication.ts
  • packages/auth/src/supabase/auth-client.test.ts
  • packages/auth/src/supabase/index.ts
  • packages/auth/README.md
📚 Learning: 2025-10-02T12:40:33.718Z
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.{ts,tsx} : Place runtime-specific authentication adapters under packages/auth/src/authentication/ (e.g., header.ts, supabase.ts, shared utilities, errors.ts)

Applied to files:

  • packages/auth/src/authentication/supabase.ts
  • packages/auth/src/supabase/errors.ts
  • packages/auth/src/supabase/auth-client.ts
  • packages/auth/src/index.ts
  • packages/types/src/authentication.ts
  • packages/auth/src/supabase/auth-client.test.ts
  • packages/auth/src/supabase/index.ts
  • packages/auth/README.md
📚 Learning: 2025-10-02T12:40:33.718Z
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authorization/**/*.{ts,tsx} : Place domain authorization policies under packages/auth/src/authorization/ (e.g., policies/chat.ts exporting canAccessChat)

Applied to files:

  • packages/auth/src/supabase/auth-client.ts
  • packages/auth/src/index.ts
  • packages/auth/src/supabase/index.ts
🧬 Code graph analysis (3)
packages/auth/src/supabase/errors.ts (2)
packages/auth/src/index.ts (1)
  • SupabaseAuthError (25-25)
packages/auth/src/supabase/index.ts (1)
  • SupabaseAuthError (7-7)
packages/auth/src/supabase/auth-client.ts (1)
packages/auth/src/supabase/errors.ts (1)
  • SupabaseAuthError (1-8)
packages/auth/src/supabase/auth-client.test.ts (2)
packages/auth/src/supabase/auth-client.ts (1)
  • createSupabaseAuthClient (124-226)
packages/auth/src/supabase/errors.ts (1)
  • SupabaseAuthError (1-8)
🪛 GitHub Actions: CI
packages/auth/src/supabase/auth-client.test.ts

[error] 7-7: TS2741: Property 'preconnect' is missing in type '(input: RequestInfo, init?: RequestInit) => Promise' but required in type 'typeof fetch'.


[error] 97-97: TS2769: No overload matches this call. Overload 1 of 2, '(expected: null): void', gave the following error. Argument of type 'string' is not assignable to parameter of type 'null'. Overload 2 of 2, '(expected: null): void', gave the following error. Argument of type 'string' is not assignable to parameter of type 'null'.

🪛 LanguageTool
packages/auth/README.md

[grammar] ~51-~51: Use a hyphen to join words.
Context: ...l adapters and tests demonstrating error handling scenarios. ## Development - B...

(QB_NEW_EN_HYPHEN)

🔇 Additional comments (27)
packages/api/CHANGELOG.md (1)

3-9: LGTM! Changelog entry is clear and consistent.

The patch version bump and dependency update entry accurately reflect the changes in this release.

packages/auth/CHANGELOG.md (1)

3-12: LGTM! Changelog accurately documents the new features.

The minor version bump is appropriate for introducing the Supabase Auth REST client and audience array support.

packages/types/CHANGELOG.md (1)

3-7: LGTM! Changelog is consistent with related package changes.

The version and description align with the broader feature introduction across the monorepo.

packages/auth/package.json (1)

3-3: LGTM! Version bump is consistent with changelog.

The minor version increment to 0.5.0 correctly reflects the new Supabase Auth REST client feature.

packages/types/package.json (1)

3-3: LGTM! Version bump aligns with changelog.

The 0.5.0 version correctly reflects the new authentication types and audience config changes.

packages/auth/src/index.ts (1)

18-26: LGTM! Clean public API exports.

The new Supabase Auth client types and factory function are properly exposed through the public API with appropriate separation of type and value exports.

packages/api/package.json (1)

3-3: LGTM! Patch version bump for dependency updates.

The version increment to 0.3.2 appropriately reflects the dependency updates to @listee/auth@0.5.0 and @listee/types@0.5.0.

packages/types/src/authentication.ts (1)

24-24: LGTM! Backward-compatible type widening.

The audience type change from string to string | readonly string[] enables multiple audience values while maintaining full backward compatibility with existing single-string usage.

packages/auth/src/supabase/auth-client.test.ts (5)

13-51: LGTM!

The login test thoroughly verifies token payload normalization and request body formatting.


53-77: LGTM!

The refresh test correctly validates nested data payload handling.


102-117: LGTM!

Error propagation test correctly validates error message extraction from Supabase response payloads.


119-131: LGTM!

Network failure test correctly validates that low-level errors are wrapped in SupabaseAuthError.


133-142: LGTM!

Validation test correctly ensures empty project URLs are rejected with a clear error message.

packages/auth/src/supabase/errors.ts (1)

1-8: LGTM!

The SupabaseAuthError class provides clear error context with HTTP status codes and is properly structured for use throughout the auth client.

packages/auth/src/authentication/supabase.ts (2)

72-75: LGTM!

The audience normalization correctly handles both single and multiple audiences, converting readonly arrays to mutable arrays as required by jose's JWTVerifyOptions.


116-123: LGTM!

The normalized audience is properly typed and applied to the token payload, maintaining consistency with the verification logic.

packages/auth/README.md (2)

13-16: LGTM!

The features list clearly documents the new Supabase Auth REST client alongside existing functionality.


20-51: LGTM!

The quick start examples are clear and demonstrate both JWT verification and REST endpoint usage patterns. The examples properly reference the new createSupabaseAuthClient implementation.

packages/auth/src/supabase/index.ts (1)

1-7: LGTM!

The module exports provide a clean public API surface for the Supabase auth client and related types.

packages/auth/src/supabase/auth-client.ts (8)

40-56: LGTM!

The type guards are well-implemented with proper checks for all required token fields, including finite number validation for expires_in.


67-86: LGTM!

Input validation for project URL and publishable key is thorough, with clear error messages for empty values and invalid URLs.


88-105: LGTM!

The error message extraction logic tries multiple common error field names and falls back gracefully to a default message.


107-122: LGTM!

JSON parsing is safely handled with proper error wrapping, including handling of empty response bodies.


137-174: LGTM!

The request function properly handles network errors, response parsing, and maps HTTP errors to SupabaseAuthError with user-friendly messages. The headers include both apikey and Authorization as required by Supabase.


176-189: LGTM!

Token response extraction correctly handles both direct token payloads and nested data payloads, matching the test expectations.


191-226: LGTM!

The public methods (signup, login, refresh) are well-implemented:

  • Signup correctly encodes the redirect URL as a query parameter
  • Login and refresh use the appropriate grant types
  • All methods properly transform responses to the public SupabaseTokenPayload type

3-7: The review comment is based on a misunderstanding of the Fetch API.

The fetch?: typeof fetch type is correctly used. The Fetch API's RequestInit does not include a preconnect property—that's an HTML link relation attribute, not part of the fetch specification. The code properly calls fetchImpl with only standard parameters (method, headers, body), and the test file successfully demonstrates that mock fetch implementations work correctly with this type signature. No changes needed.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/auth/src/supabase/auth-client.test.ts (2)

122-137: Consider verifying error type and status code.

The test successfully verifies error message propagation. For more complete coverage, consider also asserting the error type and status code:

-    await expect(
-      client.login({ email: "user@example.com", password: "bad" }),
-    ).rejects.toThrow("Invalid login");
+    const error = await client.login({ 
+      email: "user@example.com", 
+      password: "bad" 
+    }).catch((e) => e);
+    
+    expect(error).toBeInstanceOf(SupabaseAuthError);
+    expect(error.statusCode).toBe(400);
+    expect(error.message).toContain("Invalid login");

139-151: Consider more specific assertions for network errors.

While the test correctly verifies that network failures throw SupabaseAuthError, you could add assertions for the status code and message to ensure proper error wrapping:

-    await expect(
-      client.refresh({ refreshToken: "refresh-token" }),
-    ).rejects.toThrow(SupabaseAuthError);
+    const error = await client.refresh({ 
+      refreshToken: "refresh-token" 
+    }).catch((e) => e);
+    
+    expect(error).toBeInstanceOf(SupabaseAuthError);
+    expect(error.statusCode).toBe(500);
+    expect(error.message).toContain("connection reset");
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a6c9ce3 and 73fcdf7.

📒 Files selected for processing (1)
  • packages/auth/src/supabase/auth-client.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
packages/*/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

packages/*/src/**/*.{ts,tsx}: Avoid implicit any; TypeScript is run with strict enabled
Prefer type guards or the satisfies operator over as casts where appropriate
Prefer unknown for external inputs
Use PascalCase for types and enums
Use camelCase for variables and functions
Ensure source comments are written in English

Files:

  • packages/auth/src/supabase/auth-client.test.ts
packages/*/src/**/{*.test.ts,__tests__/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

packages/*/src/**/{*.test.ts,__tests__/**/*.ts}: Write test names and descriptions in English
Co-locate tests as *.test.ts or under tests/ using Bun’s test runner

Files:

  • packages/auth/src/supabase/auth-client.test.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.ts : Extend Supabase JWT verification (createSupabaseAuthentication using .well-known/jwks.json) only via dedicated modules to keep caching and claim validation centralized
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.{ts,tsx} : Place runtime-specific authentication adapters under packages/auth/src/authentication/ (e.g., header.ts, supabase.ts, shared utilities, errors.ts)
📚 Learning: 2025-10-02T12:40:33.718Z
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.ts : Extend Supabase JWT verification (createSupabaseAuthentication using .well-known/jwks.json) only via dedicated modules to keep caching and claim validation centralized

Applied to files:

  • packages/auth/src/supabase/auth-client.test.ts
📚 Learning: 2025-10-02T12:40:33.718Z
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.{ts,tsx} : Place runtime-specific authentication adapters under packages/auth/src/authentication/ (e.g., header.ts, supabase.ts, shared utilities, errors.ts)

Applied to files:

  • packages/auth/src/supabase/auth-client.test.ts
🧬 Code graph analysis (1)
packages/auth/src/supabase/auth-client.test.ts (2)
packages/auth/src/supabase/auth-client.ts (1)
  • createSupabaseAuthClient (124-226)
packages/auth/src/supabase/errors.ts (1)
  • SupabaseAuthError (1-8)
🔇 Additional comments (6)
packages/auth/src/supabase/auth-client.test.ts (6)

6-11: Good pattern for type narrowing in tests.

The ensureValue helper is well-implemented and successfully addresses the previous TypeScript type narrowing issue with receivedUrl. This approach is clear and explicit for test assertions.


13-26: Mock fetch implementation correctly addresses the TypeScript error.

The use of Object.assign to add the preconnect method successfully resolves the previous TS2741 compilation error. This minimal mock implementation is appropriate for testing purposes.


29-66: LGTM! Comprehensive test for login normalization.

The test effectively verifies that the login method correctly normalizes Supabase's snake_case token response to camelCase and sends the expected request body.


68-92: LGTM! Verifies nested data payload handling.

The test correctly validates that the refresh method can extract tokens from Supabase's nested data wrapper format.


94-120: Type narrowing issue resolved correctly.

The use of ensureValue successfully addresses the previous TS2769 error by narrowing receivedUrl from string | null to string before the assertion. The test effectively verifies redirect URL forwarding with proper encoding.


153-162: LGTM! Input validation test is clear.

The test effectively verifies project URL validation with an appropriate inline snapshot for the error message.

@gentamura gentamura merged commit 2be1f48 into main Nov 11, 2025
5 checks passed
@gentamura gentamura deleted the feat/supabase-auth-client branch November 11, 2025 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant