Skip to content

Fix SurrealDB peer runtime identity - #6

Open
JustKira wants to merge 1 commit into
surrealdb:mainfrom
JustKira:main
Open

Fix SurrealDB peer runtime identity#6
JustKira wants to merge 1 commit into
surrealdb:mainfrom
JustKira:main

Conversation

@JustKira

@JustKira JustKira commented Jul 4, 2026

Copy link
Copy Markdown

This PR fixes a runtime class identity issue in the published adapter build.

The adapter source imports RecordId from surrealdb, but the current Bun build can bundle dependencies into dist/index.js. That means the published adapter can contain a private bundled copy of SurrealDB's runtime classes.

A consuming app also imports surrealdb for its own Surreal client. Even when both copies are the same package version, they are separate JavaScript class identities:

adapter bundled RecordId !== app RecordId

The adapter creates a record id for the Surreal row id slot:

new RecordId("user", id)

But if that RecordId comes from the adapter's bundled copy, the app's Surreal client may not recognize it as its own RecordId class when encoding query bindings. The malformed binding can create rows like:

user:{ }

instead of:

user:⟨uuid⟩

Before

@surrealdb/better-auth/dist/index.js
  └─ bundled surrealdb
      └─ RecordId class B

consumer app
  └─ node_modules/surrealdb
      ├─ Surreal client
      └─ RecordId class A

adapter creates RecordId class B
app client expects RecordId class A
class identity mismatch
query binding encodes incorrectly
flowchart TD
    BA["Better Auth"]
    Adapter["@surrealdb/better-auth dist"]
    Bundled["bundled surrealdb copy<br/>RecordId class B"]
    AppClient["consumer app surrealdb<br/>Surreal client + RecordId class A"]
    DB["SurrealDB"]
    Bad["created row:<br/>user:{ }"]

    BA -->|"id = UUID string"| Adapter
    Adapter -->|"new RecordId('user', id)"| Bundled
    Bundled -->|"RecordId class B"| AppClient
    AppClient -->|"does not recognize class B"| DB
    DB --> Bad

    style Bad fill:#ffd6d6,stroke:#aa0000,color:#000
Loading

After

@surrealdb/better-auth/dist/index.js
  └─ import { RecordId } from "surrealdb"

consumer app
  └─ node_modules/surrealdb
      ├─ Surreal client
      └─ RecordId class A

adapter imports RecordId class A
app client expects RecordId class A
class identity matches
query binding encodes correctly
flowchart TD
    BA["Better Auth"]
    Adapter["@surrealdb/better-auth dist"]
    AppRuntime["consumer app surrealdb<br/>Surreal client + RecordId class A"]
    DB["SurrealDB"]
    Good["created row:<br/>user:⟨uuid⟩"]

    Adapter -->|"import { RecordId } from 'surrealdb'"| AppRuntime
    BA -->|"id = UUID string"| Adapter
    Adapter -->|"new RecordId('user', id)<br/>using class A"| AppRuntime
    AppRuntime -->|"recognized RecordId"| DB
    DB --> Good

    style Good fill:#d8ffd8,stroke:#008a00,color:#000
Loading

Why both changes are needed

This PR makes two packaging changes:

"build": "bun build ./src/index.ts --outdir dist --target node --packages external && tsc -p tsconfig.build.json --emitDeclarationOnly"

and:

"peerDependencies": {
  "surrealdb": "^2.0.3"
}

--packages external keeps surrealdb as an external import in dist/index.js instead of bundling it.

peerDependencies.surrealdb ensures the adapter does not install or own a nested SurrealDB runtime and instead uses the consumer app's installed surrealdb.

Together they preserve the invariant:

adapter RecordId === app Surreal client RecordId

peerDependencies alone is not enough if dist/index.js already contains bundled SurrealDB code.

--packages external alone is not enough if the adapter can still install a nested node_modules/surrealdb copy.

Id semantics

This does not change Better Auth id semantics.

Better Auth-facing ids remain strings:

user.id
session.userId
account.userId
verification.identifier

Only the SurrealDB intrinsic row id slot is converted to RecordId at query time:

row.id

Correct flow:

Better Auth generateId -> string UUID
adapter create user row -> RecordId("user", uuid) only for Surreal row.id
SurrealDB stores -> user:⟨uuid⟩
adapter returns -> string UUID back to Better Auth

Summary

The source logic using new RecordId(...) is not the bug by itself. The bug is when that RecordId comes from a bundled/private copy of surrealdb instead of the same surrealdb runtime used by the consuming app's Surreal client.

This PR fixes that by externalizing package imports during build and making surrealdb a peer dependency.

@rowan-baker

rowan-baker commented Jul 4, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Comment thread src/index.ts Outdated
@JustKira

JustKira commented Jul 5, 2026

Copy link
Copy Markdown
Author

Actually my bad i push incorrect commit this shouldn't be pushed like 900+ lines changes
only these changes b15636d should have been in this pull request let me fix that on sec

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.

2 participants