Skip to content

Custom Inspector for all SurrealDB Data Types#503

Merged
macjuul merged 4 commits into
surrealdb:mainfrom
msanchezdev:custom-record-id-inspect
Dec 18, 2025
Merged

Custom Inspector for all SurrealDB Data Types#503
macjuul merged 4 commits into
surrealdb:mainfrom
msanchezdev:custom-record-id-inspect

Conversation

@msanchezdev
Copy link
Copy Markdown
Contributor

@msanchezdev msanchezdev commented Nov 17, 2025

Thank you for submitting this pull request! We appreciate you spending the time to work on these changes.

What is the motivation?

It's hard to debug SurrealDB Results when logging any value just prints you the class name and all its properties with getters and all.

Currently you cannot see what's the table or id of a Record IDs without accessing table and id properties explicitly.

What does this change do?

Adds custom inspect to all of SurrealDB Value types are properly inspected when logged.
The print helper below is just a wrapper for the console.log you can find the full script in the gist: https://gist.github.com/msanchezdev/c45b1393084a4cbe68d556ea9d06b33d

Table

image
print("Table:", [
  new Table("client"),
  new Table("order"),
  new Table("product"),
]);

RecordId

image
print("RecordId:", [
  new RecordId("user", "msanchezdev"),
  new RecordId("order", 123456),
  new RecordId("product", "01KC8FMT9XX38MN93RPZGQ8HTP"),
  new RecordId("product", "123456"),
]);

StringRecordId

image
print("StringRecordId:", [
  new StringRecordId("user:msanchezdev"),
  new StringRecordId("order:01KC8FMT9XX38MN93RPZGQ8HTP"),
  new StringRecordId("product:123456"),
  r`user:msanchezdev`,
]);

RecordIdRange

image
print("RecordIdRange:", [
  new RecordIdRange("order", new BoundIncluded(1), new BoundIncluded(10)),
  new RecordIdRange("order", new BoundIncluded(1), new BoundExcluded(10)),
  new RecordIdRange("order", new BoundExcluded(1), new BoundIncluded(10)),
  new RecordIdRange("order", new BoundExcluded(1), new BoundExcluded(10)),
]);

DateTime

image
print("DateTime:", [
  new DateTime(),
  new DateTime(new Date("2025-01-01T00:00:00Z")),
  d`2025-01-01T00:00:00Z`,
]);

Uuid

image
print("Uuid:", [
  new Uuid("123e4567-e89b-12d3-a456-426614174000"),
  u`123e4567-e89b-12d3-a456-426614174000`,
]);

Range

image
print("Range:", [
  new Range(new BoundIncluded(1), new BoundIncluded(10)),
  new Range(new BoundIncluded(1), new BoundExcluded(10)),
  new Range(new BoundExcluded(1), new BoundIncluded(10)),
  new Range(new BoundExcluded(1), new BoundExcluded(10)),
]);

FileRef

image
print("FileRef:", [
  new FileRef("root", "hello.txt"),
  new FileRef("images", "/users/msanchezdev/profile.jpg"),
]);

Duration

image
print("Duration:", [
  new Duration("1h30m14s"),
  new Duration("2h15m30s"),
  new Duration("3h20m45s"),
  new Duration("4h25m00s"),
  new Duration("5h30m15s"),
]);

Decimal

image
print("Decimal:", [
  new Decimal("123"),
  new Decimal("123.456"),
  new Decimal("1.256789e12"),
]);

Query

image
const query = surql`
  CREATE ${new RecordId("user", "johndoe")} CONTENT {
    name: ${{
      given: "John",
      family: "Doe",
    }},
    age: ${18},
    salaery: ${new Decimal("1.5")},
    birth_date: ${new DateTime()},
    active: ${true},
    contact_info: ${[
      {
        primary: "1234567890",
        countryCode: "+1",
      },
      {
        primary: "1234567890",
        countryCode: "+1",
      },
    ]},
    session_duration: ${new Duration("1h30m14s")},
  }
`;
console.log(query);

Geometry

These are long and it's mostly showing how they react with different inspect depth, so please refer to the example gist: https://gist.github.com/msanchezdev/c45b1393084a4cbe68d556ea9d06b33d

image image image image image image image

What is your testing strategy?

Each case above has it's own snippet, snapshot testing can be added. There is also a gist that can be run with all these examples: https://gist.github.com/msanchezdev/c45b1393084a4cbe68d556ea9d06b33d

Is this related to any issues?

No

Have you read the Contributing Guidelines?

@msanchezdev msanchezdev requested a review from kearfy as a code owner November 17, 2025 17:02
@msanchezdev msanchezdev force-pushed the custom-record-id-inspect branch from e02c6be to ce3add4 Compare November 17, 2025 17:42
@msanchezdev msanchezdev marked this pull request as draft December 12, 2025 17:41
@msanchezdev msanchezdev marked this pull request as ready for review December 12, 2025 21:04
@msanchezdev msanchezdev changed the title Print record id values for easier inspection Custom Inspector for all SurrealDB Data Types Dec 12, 2025
@msanchezdev msanchezdev force-pushed the custom-record-id-inspect branch 2 times, most recently from b329c8d to b0f3da1 Compare December 13, 2025 19:10
@macjuul
Copy link
Copy Markdown
Member

macjuul commented Dec 17, 2025

Can we change the approach to keep the SDK in a single bundle and only split the inspector logic to a separable importable bundle?

e.g.

// One time inspector import
import "surrealdb/inspector/node";

// Import from main bundle
import { ... } from "surrealdb";

@msanchezdev
Copy link
Copy Markdown
Contributor Author

msanchezdev commented Dec 17, 2025

Can we change the approach to keep the SDK in a single bundle and only split the inspector logic to a separable importable bundle?

e.g.

// One time inspector import
import "surrealdb/inspector/node";

// Import from main bundle
import { ... } from "surrealdb";

@macjuul That's doable (already did locally), my only concern for being against this approach is that this is a side-effect module which patches the classess in the "surrealdb" module. This tends to break on cases where there are dependent/depending libraries with a different "surrealdb" version or when you locally link the sdk in a project.

After doing those changes, you would not be able to test this PR by doing bun link surrealdb, you would have to run:

  • bun pm pack
  • bun install <...path-to-packed>.tgz
    As it looks like bun is preferring the source code rather than the dist files, can be confirmed with:
// Compile sdk with these lines in src/inspect/node.ts
const req = createRequire(import.meta.url);
console.log("sdk surrealdb =", req.resolve("surrealdb"));

// And in a separate app with the sdk linked do
const req = createRequire(import.meta.url);
console.log("app surrealdb =", req.resolve("surrealdb"));

For this to work we would have to do something like, which I am not very fond of:

import setupInspectors from 'surrealdb/inspector/node';
import * as surreal from 'surrealdb';
setupInspectors(surreal);

I think the current approach is best as we have the regular bundle which can be used in both clients and servers, and then we have the server bundle which includes the inspector goodies for better logging. Without having to do any extra steps or risks of something leaking, just letting the runtimes decide for themselves which bundle to use, server or default.

@msanchezdev msanchezdev force-pushed the custom-record-id-inspect branch from b0f3da1 to 3e1e064 Compare December 18, 2025 00:17
@macjuul
Copy link
Copy Markdown
Member

macjuul commented Dec 18, 2025

Makes sense! In that case, is it an option to re-export the main bundle from the node bundle, rather than embedding it?

@msanchezdev
Copy link
Copy Markdown
Contributor Author

Makes sense! In that case, is it an option to re-export the main bundle from the node bundle, rather than embedding it?

Done, works nicely

@msanchezdev msanchezdev force-pushed the custom-record-id-inspect branch from c5e2a8a to 4d7ccd3 Compare December 18, 2025 12:46
@macjuul
Copy link
Copy Markdown
Member

macjuul commented Dec 18, 2025

Awesome, LGTM!

@macjuul macjuul merged commit ee7e7e8 into surrealdb:main Dec 18, 2025
12 checks passed
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