Skip to content

feat: add surreal schema driver foundation#114

Open
ibourgeois wants to merge 1 commit intomainfrom
codex/feat-surreal-migration-driver
Open

feat: add surreal schema driver foundation#114
ibourgeois wants to merge 1 commit intomainfrom
codex/feat-surreal-migration-driver

Conversation

@ibourgeois
Copy link
Contributor

Summary

  • register a first Laravel-compatible database connection for schema work
  • add a narrow Surreal schema grammar, builder, and manager for common Katra field types
  • prove the flow with a real Surreal-backed Pest feature test and document the current scope

Testing

  • vendor/bin/pint --dirty --format agent
  • php artisan test --compact tests/Feature/SurrealWorkspaceModelTest.php tests/Feature/SurrealSchemaDriverTest.php

Closes #113

Copilot AI review requested due to automatic review settings March 23, 2026 02:46
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Introduces a first Laravel Schema/Migration “driver” foundation for SurrealDB so migrations can target Surreal-backed application data via Laravel’s Schema API.

Changes:

  • Registers a new surreal database driver/connection for schema operations.
  • Adds Surreal schema grammar/builder/manager to support create/add/drop columns and create/drop tables for a narrow set of column types.
  • Adds a Surreal-backed Pest feature test and documents current scope/limitations in the README.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
config/database.php Adds a surreal connection entry pointing at the new surreal driver.
app/Providers/AppServiceProvider.php Registers the surreal database driver via DatabaseManager::extend().
app/Services/Surreal/Schema/SurrealSchemaConnection.php New Laravel Connection implementation used for Surreal schema operations.
app/Services/Surreal/Schema/SurrealSchemaBuilder.php New schema builder that delegates table/column introspection & drops to Surreal.
app/Services/Surreal/Schema/SurrealSchemaGrammar.php New schema grammar compiling Laravel schema commands into Surreal DEFINE/REMOVE statements.
app/Services/Surreal/Schema/SurrealSchemaManager.php New manager running INFO queries and executing schema statements through the Surreal CLI.
tests/Feature/SurrealSchemaDriverTest.php End-to-end test proving create/alter/drop via Schema::connection('surreal').
README.md Documents how to use Surreal-backed migrations and clarifies current scope.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

$config,
);
}

Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

SurrealSchemaConnection is constructed with an in-memory SQLite PDO. That means any accidental use of DB::connection('surreal')->select()/insert()/transaction() (or other non-schema operations that hit the base Connection implementation) would silently run against SQLite instead of SurrealDB, producing incorrect behavior without obvious failures. Consider explicitly disabling query/transaction APIs on this connection (override the relevant methods to throw a clear RuntimeException), and/or override getDriverName() to surreal to avoid Laravel treating it as SQLite anywhere internally.

Suggested change
public function getDriverName(): string
{
return 'surreal';
}
/**
* SurrealSchemaConnection is schema-only; data queries are not supported.
*
* @param string $query
* @param array<int, mixed> $bindings
* @param bool $useReadPdo
* @return array<int, mixed>
*/
public function select($query, $bindings = [], $useReadPdo = true)
{
throw new \RuntimeException('SurrealSchemaConnection does not support select queries. Use SurrealConnection for data access.');
}
/**
* SurrealSchemaConnection is schema-only; data queries are not supported.
*
* @param string $query
* @param array<int, mixed> $bindings
* @param bool $useReadPdo
* @return \Generator
*/
public function cursor($query, $bindings = [], $useReadPdo = true)
{
throw new \RuntimeException('SurrealSchemaConnection does not support cursors. Use SurrealConnection for data access.');
}
/**
* SurrealSchemaConnection is schema-only; data queries are not supported.
*
* @param string $query
* @param array<int, mixed> $bindings
* @return bool
*/
public function insert($query, $bindings = [])
{
throw new \RuntimeException('SurrealSchemaConnection does not support insert queries. Use SurrealConnection for data access.');
}
/**
* SurrealSchemaConnection is schema-only; data queries are not supported.
*
* @param string $query
* @param array<int, mixed> $bindings
* @return int
*/
public function update($query, $bindings = [])
{
throw new \RuntimeException('SurrealSchemaConnection does not support update queries. Use SurrealConnection for data access.');
}
/**
* SurrealSchemaConnection is schema-only; data queries are not supported.
*
* @param string $query
* @param array<int, mixed> $bindings
* @return int
*/
public function delete($query, $bindings = [])
{
throw new \RuntimeException('SurrealSchemaConnection does not support delete queries. Use SurrealConnection for data access.');
}
/**
* SurrealSchemaConnection is schema-only; transactions are not supported.
*
* @param \Closure $callback
* @param int $attempts
* @return mixed
*/
public function transaction(\Closure $callback, $attempts = 1)
{
throw new \RuntimeException('SurrealSchemaConnection does not support transactions. Use SurrealConnection for data access.');
}
/**
* SurrealSchemaConnection is schema-only; transactions are not supported.
*/
public function beginTransaction()
{
throw new \RuntimeException('SurrealSchemaConnection does not support transactions. Use SurrealConnection for data access.');
}
/**
* SurrealSchemaConnection is schema-only; transactions are not supported.
*/
public function commit()
{
throw new \RuntimeException('SurrealSchemaConnection does not support transactions. Use SurrealConnection for data access.');
}
/**
* SurrealSchemaConnection is schema-only; transactions are not supported.
*
* @param int|null $toLevel
*/
public function rollBack($toLevel = null)
{
throw new \RuntimeException('SurrealSchemaConnection does not support transactions. Use SurrealConnection for data access.');
}

Copilot uses AI. Check for mistakes.
Comment on lines +92 to +145
function retryStartingSurrealSchemaServer(SurrealCliClient $client, string $storagePath, int $attempts = 3): array
{
$lastException = null;

for ($attempt = 1; $attempt <= $attempts; $attempt++) {
$port = reserveSurrealSchemaPort();
$endpoint = sprintf('ws://127.0.0.1:%d', $port);
$process = $client->startLocalServer(
bindAddress: sprintf('127.0.0.1:%d', $port),
datastorePath: $storagePath,
username: 'root',
password: 'root',
storageEngine: 'surrealkv',
);

if ($client->waitUntilReady($endpoint)) {
return [
'endpoint' => $endpoint,
'port' => $port,
'process' => $process,
];
}

$process->stop(1);
$lastException = new RuntimeException(sprintf('SurrealDB did not become ready on %s.', $endpoint));
}

throw $lastException ?? new RuntimeException('Unable to start the SurrealDB schema test runtime.');
}

function reserveSurrealSchemaPort(): int
{
$socket = stream_socket_server('tcp://127.0.0.1:0', $errorCode, $errorMessage);

if ($socket === false) {
throw new RuntimeException(sprintf('Unable to reserve a free TCP port: %s (%d)', $errorMessage, $errorCode));
}

$address = stream_socket_get_name($socket, false);

fclose($socket);

if ($address === false) {
throw new RuntimeException('Unable to determine the reserved TCP port.');
}

$port = (int) ltrim((string) strrchr($address, ':'), ':');

if ($port <= 0) {
throw new RuntimeException(sprintf('Unable to parse the reserved TCP port from [%s].', $address));
}

return $port;
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

This test duplicates the same port-reservation + retry-start-server helpers already present in other Surreal feature tests (e.g. retryStartingWorkspaceServer / reserveWorkspacePort). Consider extracting these helpers into a shared test support file/trait (or a Pest helper) to reduce duplication and keep the startup logic consistent across tests.

Copilot uses AI. Check for mistakes.
@ibourgeois ibourgeois force-pushed the codex/feat-surreal-migration-driver branch from bbb174f to e9ee757 Compare March 23, 2026 03:06
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.

feat: add a SurrealDB Laravel schema and migration driver foundation

2 participants