Skip to content

fix: allow better-auth 1.5 beta#259

Open
onmax wants to merge 2 commits intoget-convex:mainfrom
onmax:fix/251-better-auth-1-5-beta
Open

fix: allow better-auth 1.5 beta#259
onmax wants to merge 2 commits intoget-convex:mainfrom
onmax:fix/251-better-auth-1-5-beta

Conversation

@onmax
Copy link

@onmax onmax commented Feb 12, 2026

Fixes #251.

Summary by CodeRabbit

  • New Features

    • Test matrix added to validate multiple better-auth versions.
  • Removed Features

    • Passkey authentication plugin removed.
  • Improvements

    • Broader peer dependency range for better-auth.
    • Field selection support for queries and id/_id reconciliation.
    • More robust origin and path handling.
    • Enhanced update where-clause validation.
  • Tests

    • CI expanded to run across versions; test orchestration refactored.
  • Documentation

    • Updated supported-plugins note about Passkey installation.

@vercel
Copy link

vercel bot commented Feb 12, 2026

@onmax is attempting to deploy a commit to the Convex Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Feb 12, 2026

📝 Walkthrough

Walkthrough

Updates CI to test multiple better-auth versions, widens peer dependency range for better-auth, removes Passkey integration, adds id/_id handling and enhanced where-clause checks in the adapter, introduces optional select for findMany, and refactors inline adapter test orchestration.

Changes

Cohort / File(s) Summary
CI Configuration
​.github/workflows/node.js.yml
Adds matrix strategy (fail-fast: false) and installs better-auth per-matrix (1.4.18, 1.5.0-beta.13) before tests.
Dependencies / Manifest
package.json
Expands peerDependencies.better-auth range to `>=1.4.9 <1.6.0
Passkey removal & docs
src/auth-options.ts, docs/content/docs/supported-plugins.mdx
Removes @better-auth/passkey import and passkey() plugin; docs updated to note passkey requires local install of @better-auth/passkey.
Test orchestration refactor
src/client/adapter.test.ts, src/component/adapterTest.ts
Removes exported test helper wrapper and runAdapterTest pathway; inlines test orchestration and updates getAdapter signature, test flow, and some timestamp assertions.
Adapter behavior changes
src/client/adapter.ts, src/client/adapter-utils.ts
adapter.update: tighter where-clause validation and allow multi-equality (AND) clauses; selectFields: special handling to map id and _id between adapter and Convex shapes.
API & client changes
src/client/create-api.ts, src/client/create-client.ts
findMany adds optional select argument; create-client normalizes trustedOrigins to support array or function-returning-array and handles values defensively.
Plugin path normalization
src/plugins/...
src/plugins/convex/index.ts, src/plugins/cross-domain/index.ts
Guard ctx.path with const path = ctx.path ?? "" in several matchers and switch some imports to better-auth/api.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

"I nibbled at peer ranges and hopped through CI trees,
Removed a passkey leaf blown off by the breeze.
I stitched tests inline and tidied where's and ids,
A rabbit's small refactor—soft paws on many mids. 🐇✨"

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes out-of-scope changes beyond supporting 1.5 beta: refactoring test infrastructure in adapterTest.ts, restructuring adapter utilities, and modifying plugin implementations (convex and cross-domain). Separate refactoring changes (test infrastructure and plugin logic updates) into distinct PRs focused on supporting 1.5 beta compatibility. Scope this PR to dependency updates and version compatibility only.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: allow better-auth 1.5 beta' directly summarizes the main change in the changeset: widening dependency support for better-auth 1.5 beta.
Linked Issues check ✅ Passed The PR successfully implements all key requirements from issue #251: widens peer dependency range to support 1.4.x and 1.5 beta, removes @better-auth/passkey dependency, and adds CI matrix testing across both versions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
src/plugins/convex/index.ts (1)

270-274: Inconsistent ctx.path access — missing nullish guard in before-hook matcher.

Both after-hook matchers (Lines 291, 331) defensively normalize ctx.path with ?? "", but this before-hook at Line 273 accesses ctx.path directly. If ctx.path can be undefined in better-auth 1.5 beta (the reason for the other guards), this comparison would evaluate to false silently — not a crash, but the inconsistency is worth cleaning up.

Suggested fix
         matcher: (ctx) => {
+            const path = ctx.path ?? "";
             return (
               !ctx.context.adapter.options?.isRunMutationCtx &&
-              ctx.path === "/get-session"
+              path === "/get-session"
             );
           },
src/client/create-client.ts (1)

404-425: Solid normalization for cross-version compatibility.

The approach of handling both array and function forms of trustedOrigins is clean and defensive. A couple of minor observations:

  1. If trustedOriginsOption is a function that throws, the error will propagate unhandled through the allowedOrigins callback. Consider wrapping the invocation in a try/catch with a fallback to [] (and optionally a console.warn when config?.verbose).

  2. If the function returns a non-array value (e.g., a single string), trustedOrigins silently defaults to []. A verbose-mode warning could help users debug misconfiguration.

Neither is a blocker — the current behavior is safe and won't break anything.

Optional: add resilience and verbose logging around the function call
           } else if (typeof trustedOriginsOption === "function") {
-            const result = await (trustedOriginsOption as any)(request);
-            if (Array.isArray(result)) {
-              trustedOrigins = result.filter(
-                (origin): origin is string => typeof origin === "string"
-              );
+            try {
+              const result = await (trustedOriginsOption as any)(request);
+              if (Array.isArray(result)) {
+                trustedOrigins = result.filter(
+                  (origin): origin is string => typeof origin === "string"
+                );
+              } else if (config?.verbose) {
+                console.warn("trustedOrigins function returned a non-array value, ignoring");
+              }
+            } catch (e) {
+              if (config?.verbose) {
+                console.warn("trustedOrigins function threw an error, falling back to []", e);
+              }
             }
           }
src/client/adapter-utils.ts (1)

295-313: Redundant fallback values — doc["_id"] and doc._id are identical property accesses.

Both bracket notation (doc as any)["_id"] and dot notation (doc as any)._id resolve to the same property in JavaScript, making the fallback chains effectively:

  • Line 299–303 (field === "id"): doc._id ?? doc._id ?? doc.id ?? doc.iddoc._id ?? doc.id
  • Line 307–311 (field === "_id"): doc._id ?? doc.id ?? doc._id ?? doc.iddoc._id ?? doc.id

Both branches are semantically identical. Consider simplifying to a single shared helper.

♻️ Suggested simplification
   return select.reduce((acc, field) => {
-    // Convex stores ids in `_id`, but Better Auth's adapter interface expects `id`.
-    // The Better Auth adapter factory applies `_id -> id` mapping on output, so
-    // we must return `_id` here even when the caller selects `id`.
-    if (field === "id") {
-      (acc as any)._id =
-        (doc as any)["_id"] ??
-        (doc as any)._id ??
-        (doc as any)["id"] ??
-        (doc as any).id;
-      return acc;
-    }
-    if (field === "_id") {
-      (acc as any)._id =
-        (doc as any)["_id"] ??
-        (doc as any)["id"] ??
-        (doc as any)._id ??
-        (doc as any).id;
+    // Convex stores ids in `_id`, but Better Auth's adapter interface
+    // expects `id`. The adapter factory applies `_id -> id` on output,
+    // so we always return `_id` here regardless of which key was requested.
+    if (field === "id" || field === "_id") {
+      (acc as any)._id = (doc as any)._id ?? (doc as any).id;
       return acc;
     }
     (acc as any)[field] = doc[field];
     return acc;
   }, {} as D);
src/client/adapter.ts (1)

274-295: Ambiguous error messages — both "empty where" and "non-eq operators" throw the same text.

Lines 275 and 295 both throw "where clause not supported", but they represent different failure modes: missing/empty where vs. unsupported non-equality operators. Distinct messages would improve debuggability.

♻️ Suggested improvement
           if (!data.where?.length) {
-            throw new Error("where clause not supported");
+            throw new Error("update requires a non-empty where clause");
           }
           // Better Auth can pass multiple `eq` where clauses (AND semantics).
           if (data.where.every((w) => !w.operator || w.operator === "eq")) {
             ...
           }
-          throw new Error("where clause not supported");
+          throw new Error(
+            `update only supports eq where clauses, got: ${data.where.map((w) => w.operator).join(", ")}`
+          );

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/component/adapterTest.ts (1)

158-168: ⚠️ Potential issue | 🟡 Minor

Type mismatch: typeof getAdapter doesn't match the value actually passed.

At line 153, getAdapter(ctx) is passed — this is the return type of getAdapter, i.e. (opts?: Omit<BetterAuthOptions, "database">) => Promise<adapter>. But line 164 annotates the parameter as typeof getAdapter, which is the full curried signature (ctx: GenericCtx<DataModel>) => (opts?: Omit<BetterAuthOptions, "database">) => Promise<adapter>.

Inside runCustomAdapterTests, getAdapter() is called with no arguments (e.g., lines 170, 181), which happens to work at runtime because the inner function's opts parameter is optional. However, the type annotation is semantically incorrect.

Proposed fix
-  getAdapter: typeof getAdapter;
+  getAdapter: ReturnType<typeof getAdapter>;
🤖 Fix all issues with AI agents
In `@package.json`:
- Line 106: The peer dependency range for "better-auth" currently
("better-auth": ">=1.4.9 <1.6.0") excludes prerelease 1.5.0-beta.* versions;
update the version spec for the "better-auth" entry in package.json to
explicitly allow prereleases (for example use an OR clause like >=1.4.9 <1.5.0
|| >=1.5.0-beta.0 <1.6.0) so that 1.5.0-beta.* is matched by the peerDependency
resolver.
🧹 Nitpick comments (1)
src/component/adapterTest.ts (1)

55-62: Consider clearing all models consistently with runCustomAdapterTests.

The reset helper clears user, session, account, and verification, while the beforeEach in runCustomAdapterTests (line 169-179) only clears user and session. This inconsistency could cause test pollution if custom tests ever touch account or verification data. Not a bug today, but worth noting.

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.

Question: plans to support better-auth 1.5 beta?

1 participant